From fdd9ac9d97e916d4f382e099478fd77c50cc6014 Mon Sep 17 00:00:00 2001 From: Cyd Date: Thu, 2 Jul 2026 13:21:58 -0500 Subject: [PATCH] Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet) Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 --- .gitattributes | 3 + ARTTOOLS/.gitkeep | 0 BORLAND/.gitkeep | 0 CODE/BT/32RTM.EXE | Bin 0 -> 152108 bytes CODE/BT/32STUB.EXE | Bin 0 -> 2160 bytes CODE/BT/ARCBT.BAT | 58 + CODE/BT/ARCFILES.LST | 41 + CODE/BT/BT/AMMOBIN.TCP | 15 + CODE/BT/BT/BT.HPP | 24 + CODE/BT/BT/BT.MAK | 112 + CODE/BT/BT/BTCNSL.CPP | 107 + CODE/BT/BT/BTDIRECT.HPP | 76 + CODE/BT/BT/BTMSSN.CPP | 70 + CODE/BT/BT/BTMSSN.HPP | 96 + CODE/BT/BT/BTREG.CPP | 162 + CODE/BT/BT/BTREG.HPP | 74 + CODE/BT/BT/BTSCNRL.CPP | 22 + CODE/BT/BT/BTTEAM.CPP | 152 + CODE/BT/BT/BTTEAM.HPP | 88 + CODE/BT/BT/BTTOOL.CPP | 209 + CODE/BT/BT/BTTOOL.HPP | 64 + CODE/BT/BT/EMITTER.TCP | 101 + CODE/BT/BT/GAUSS.CPP | 153 + CODE/BT/BT/GAUSS.HPP | 144 + CODE/BT/BT/GNRATOR.TCP | 18 + CODE/BT/BT/HEAT.TCP | 58 + CODE/BT/BT/MECHDMG.HPP | 208 + CODE/BT/BT/MECHTECH.HPP | 149 + CODE/BT/BT/MESSMGR.HPP | 184 + CODE/BT/BT/MISLANCH.HPP | 120 + CODE/BT/BT/MISSILE.TCP | 44 + CODE/BT/BT/MISTHRST.HPP | 141 + CODE/BT/BT/MSSCCPRJ.SCC | 5 + CODE/BT/BT/PPC.CPP | 166 + CODE/BT/BT/PPC.HPP | 67 + CODE/BT/BT/PROJTILE.TCP | 12 + CODE/BT/BT/PROJWEAP.TCP | 20 + CODE/BT/BT/SEEKER.HPP | 134 + CODE/BT/BT/SENSOR.HPP | 143 + CODE/BT/BT/TESTBT.HPP | 68 + CODE/BT/BT/TURRET.HPP | 148 + CODE/BT/BT/VSSVER.SCC | Bin 0 -> 1376 bytes CODE/BT/BTL4.BLD | 211 + CODE/BT/BTL4.PTH | 26 + CODE/BT/BT_L4/BTL4.HPP | 12 + CODE/BT/BT_L4/BTL4.MAK | 153 + CODE/BT/BT_L4/BTL4APP.HPP | 88 + CODE/BT/BT_L4/BTL4ARND.CPP | 185 + CODE/BT/BT_L4/BTL4ARND.HPP | 112 + CODE/BT/BT_L4/BTL4GALM.HPP | 44 + CODE/BT/BT_L4/BTL4GRND.HPP | 48 + CODE/BT/BT_L4/BTL4MODE.CPP | 104 + CODE/BT/BT_L4/BTL4MODE.HPP | 152 + CODE/BT/BT_L4/BTL4MSSN.HPP | 46 + CODE/BT/BT_L4/BTL4PB.HPP | 116 + CODE/BT/BT_L4/BTL4RDR.HPP | 238 + CODE/BT/BT_L4/BTL4VER.HPP | 9 + CODE/BT/BT_L4/MSSCCPRJ.SCC | 5 + CODE/BT/BT_L4/VSSVER.SCC | Bin 0 -> 544 bytes CODE/BT/BUILDRES.BAT | 40 + CODE/BT/C0X32.OBJ | Bin 0 -> 1152 bytes CODE/BT/D0.MAK | 49 + CODE/BT/D1.MAK | 33 + CODE/BT/D2S.MAK | 33 + CODE/BT/D3S.MAK | 48 + CODE/BT/DEARCBT.BAT | 19 + CODE/BT/DPMI32VM.OVL | Bin 0 -> 58392 bytes CODE/BT/EXAMPLE.BAT | 11 + CODE/BT/EXAMPLE.CFG | 12 + CODE/BT/EXCLUDE.LST | 7 + CODE/BT/HMIDET.386 | Bin 0 -> 87624 bytes CODE/BT/HMIDRV.386 | Bin 0 -> 261257 bytes CODE/BT/MSSCCPRJ.SCC | 21 + CODE/BT/MUNGA/AFFNMTRX.TCP | 27 + CODE/BT/MUNGA/ANGLE.TCP | 170 + CODE/BT/MUNGA/APP.THP | 45 + CODE/BT/MUNGA/APPMGR.HPP | 33 + CODE/BT/MUNGA/AUDTIME.CPP | 87 + CODE/BT/MUNGA/AUDTOOLS.HPP | 51 + CODE/BT/MUNGA/AUDWGT.CPP | 38 + CODE/BT/MUNGA/AVERAGE.CPP | 21 + CODE/BT/MUNGA/BOXLIST.HPP | 177 + CODE/BT/MUNGA/CMPNNT.HPP | 73 + CODE/BT/MUNGA/COLOR.CPP | 106 + CODE/BT/MUNGA/COLOR.HPP | 190 + CODE/BT/MUNGA/CSTR.TCP | 79 + CODE/BT/MUNGA/DEBUGOFF.HPP | 72 + CODE/BT/MUNGA/DEBUGOLD.HPP | 24 + CODE/BT/MUNGA/EVTSTAT.CPP | 168 + CODE/BT/MUNGA/EVTSTAT.HPP | 96 + CODE/BT/MUNGA/FILESTRM.CPP | 152 + CODE/BT/MUNGA/FILESTRM.HPP | 121 + CODE/BT/MUNGA/FILESTRM.TCP | 52 + CODE/BT/MUNGA/FILESTUB.CPP | 78 + CODE/BT/MUNGA/HEAP.HPP | 125 + CODE/BT/MUNGA/HOST.TCP | 56 + CODE/BT/MUNGA/HOSTID.HPP | 34 + CODE/BT/MUNGA/LINE.CPP | 87 + CODE/BT/MUNGA/LINE.HPP | 70 + CODE/BT/MUNGA/LINK.CPP | 136 + CODE/BT/MUNGA/LINMTRX.TCP | 23 + CODE/BT/MUNGA/MATRIX.TCP | 22 + CODE/BT/MUNGA/MEMBLOCK.TCP | 43 + CODE/BT/MUNGA/MODE.CPP | 75 + CODE/BT/MUNGA/MOTION.HPP | 88 + CODE/BT/MUNGA/MSSCCPRJ.SCC | 5 + CODE/BT/MUNGA/MTRXSTK.CPP | 65 + CODE/BT/MUNGA/MUNGA.HPP | 82 + CODE/BT/MUNGA/NODE.CPP | 52 + CODE/BT/MUNGA/NORMAL.CPP | 69 + CODE/BT/MUNGA/NORMAL.TCP | 22 + CODE/BT/MUNGA/ORIGIN.TCP | 67 + CODE/BT/MUNGA/POINT2D.HPP | 149 + CODE/BT/MUNGA/RANDOM.HPP | 74 + CODE/BT/MUNGA/RANDOM.TCP | 44 + CODE/BT/MUNGA/RAY.HPP | 101 + CODE/BT/MUNGA/RAY.TCP | 22 + CODE/BT/MUNGA/RECT2D.HPP | 90 + CODE/BT/MUNGA/RENDERER.TCP | 57 + CODE/BT/MUNGA/RENDERER.THP | 48 + CODE/BT/MUNGA/RESVER.HPP | 7 + CODE/BT/MUNGA/SCALAR.CPP | 246 + CODE/BT/MUNGA/SCALAR.HPP | 72 + CODE/BT/MUNGA/SCNROLE.HPP | 175 + CODE/BT/MUNGA/SET.CPP | 165 + CODE/BT/MUNGA/SFESKT.HPP | 86 + CODE/BT/MUNGA/SPHERE.CPP | 55 + CODE/BT/MUNGA/SPHERE.HPP | 62 + CODE/BT/MUNGA/SPLINE.HPP | 43 + CODE/BT/MUNGA/SPOOLER.HPP | 76 + CODE/BT/MUNGA/SRTSKT.CPP | 75 + CODE/BT/MUNGA/SRTSKT.HPP | 88 + CODE/BT/MUNGA/TEAM.HPP | 197 + CODE/BT/MUNGA/TESTCLAS.HPP | 137 + CODE/BT/MUNGA/TIME.TCP | 100 + CODE/BT/MUNGA/TIMESTUB.CPP | 56 + CODE/BT/MUNGA/TRACSTUB.CPP | 38 + CODE/BT/MUNGA/UNITVEC.CPP | 66 + CODE/BT/MUNGA/UNITVEC.TCP | 77 + CODE/BT/MUNGA/VECTOR4D.HPP | 228 + CODE/BT/MUNGA/VERIFY.HPP | 61 + CODE/BT/MUNGA/VIDREND.TCP | 21 + CODE/BT/MUNGA_L4/L4APP.THP | 50 + CODE/BT/MUNGA_L4/L4AUDTUL.CPP | 83 + CODE/BT/MUNGA_L4/L4CTLTUL.CPP | 31 + CODE/BT/MUNGA_L4/L4DPLMEM.CPP | 45 + CODE/BT/MUNGA_L4/L4GAUIMM.HPP | 7 + CODE/BT/MUNGA_L4/L4HOST.CPP | 61 + CODE/BT/MUNGA_L4/L4KEYBD.CPP | 37 + CODE/BT/MUNGA_L4/L4MOUSE.HPP | 37 + CODE/BT/MUNGA_L4/L4MSSN.HPP | 50 + CODE/BT/MUNGA_L4/L4PLASMA.HPP | 70 + CODE/BT/MUNGA_L4/L4TIME.HPP | 12 + CODE/BT/MUNGA_L4/L4VIDEO.TCP | 75 + CODE/BT/MUNGA_L4/L4VIDTUL.CPP | 43 + CODE/BT/MUNGA_L4/L4WRHOUS.CPP | 63 + CODE/BT/MUNGA_L4/L4WRHOUS.HPP | 42 + CODE/BT/MUNGA_L4/LIBDPL/DPL/MATRIX.H | 47 + CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL2DTAG.H | 33 + CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL_MEM.H | 24 + CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/MATRIX.H | 47 + CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/TRICODER.H | 35 + CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VR_PROT.H | 95 + CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VSSVER.SCC | Bin 0 -> 160 bytes CODE/BT/MUNGA_L4/LIBDPL/DPL/VSSVER.SCC | Bin 0 -> 144 bytes CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.DEF | 75 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.H | 73 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVVERS.H | 54 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/DP.H | 47 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/DS.H | 48 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/GETPARAM.H | 73 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/MAPFILE.H | 99 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/PFPARSER.H | 97 + CODE/BT/MUNGA_L4/LIBDPL/DSYS/VSSVER.SCC | Bin 0 -> 384 bytes CODE/BT/MUNGA_L4/LIBDPL/DSYS/__PTOOL.H | 84 + CODE/BT/MUNGA_L4/LIBDPL/DVS/DM.H | 29 + CODE/BT/MUNGA_L4/LIBDPL/DVS/VCBODAPP.H | 47 + CODE/BT/MUNGA_L4/LIBDPL/DVS/VCERROR.H | 33 + CODE/BT/MUNGA_L4/LIBDPL/DVS/VCINPDEF.H | 71 + CODE/BT/MUNGA_L4/LIBDPL/DVS/VCMACROS.H | 33 + CODE/BT/MUNGA_L4/LIBDPL/DVS/VSSVER.SCC | Bin 0 -> 368 bytes CODE/BT/MUNGA_L4/LIBDPL/DVS/_VCTYPES.H | 10 + CODE/BT/MUNGA_L4/LIBDPL/VSSVER.SCC | Bin 0 -> 224 bytes CODE/BT/MUNGA_L4/MSSCCPRJ.SCC | 5 + CODE/BT/MUNGA_L4/MUNGAL4.HPP | 28 + CODE/BT/MUNGA_L4/NETNUB/ANALYSIS.HPP | 58 + CODE/BT/MUNGA_L4/NETNUB/INCLUDE/BOOTP.H | 73 + CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ELIB.H | 25 + CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ETHDEV.H | 16 + CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ICMP.H | 101 + CODE/BT/MUNGA_L4/NETNUB/INCLUDE/STATE.RST | 13 + CODE/BT/MUNGA_L4/NETNUB/INCLUDE/TCP.H | 98 + CODE/BT/MUNGA_L4/NETNUB/INCLUDE/VSSVER.SCC | Bin 0 -> 176 bytes CODE/BT/MUNGA_L4/NETNUB/LIB/VSSVER.SCC | Bin 0 -> 48 bytes CODE/BT/MUNGA_L4/NETNUB/MAKEFILE.MAK | 103 + CODE/BT/MUNGA_L4/NETNUB/MSSCCPRJ.SCC | 5 + CODE/BT/MUNGA_L4/NETNUB/NOPAUSE.CPP | 72 + CODE/BT/MUNGA_L4/NETNUB/VSSVER.SCC | Bin 0 -> 144 bytes CODE/BT/MUNGA_L4/PCPIC.INC | 82 + CODE/BT/MUNGA_L4/SOS/BC4/SOSDEFS.H | 65 + CODE/BT/MUNGA_L4/SOS/BC4/SOSMAWE.H | 16 + CODE/BT/MUNGA_L4/SOS/BC4/SOSRES.H | 110 + CODE/BT/MUNGA_L4/SOS/BC4/VSSVER.SCC | Bin 0 -> 192 bytes CODE/BT/MUNGA_L4/SOS/VSSVER.SCC | Bin 0 -> 176 bytes CODE/BT/MUNGA_L4/SOS/WC/SOSDEFS.H | 65 + CODE/BT/MUNGA_L4/SOS/WC/SOSRES.H | 110 + CODE/BT/MUNGA_L4/SOS/WC/VSSVER.SCC | Bin 0 -> 160 bytes CODE/BT/MUNGA_L4/SOSMAWE.H | 16 + CODE/BT/MUNGA_L4/SPEAKER.HPP | 9 + CODE/BT/MUNGA_L4/VSSVER.SCC | Bin 0 -> 1520 bytes CODE/BT/NEWSTUFF.BLD | 21 + CODE/BT/OPT.MAK | 47 + CODE/BT/SETENV.BAT | 220 + CODE/BT/VSSVER.SCC | Bin 0 -> 512 bytes CODE/RP/32STUB.EXE | Bin 0 -> 2160 bytes CODE/RP/C0X32.OBJ | Bin 0 -> 1152 bytes CODE/RP/CW32.LIB | Bin 0 -> 450560 bytes CODE/RP/D0.mak | 49 + CODE/RP/DPMI32.LIB | Bin 0 -> 29184 bytes CODE/RP/MUNGA/AFFNMTRX.CPP | 831 ++ CODE/RP/MUNGA/AFFNMTRX.HPP | 195 + CODE/RP/MUNGA/AFFNMTRX.TCP | 27 + CODE/RP/MUNGA/ANGLE.CPP | 205 + CODE/RP/MUNGA/ANGLE.HPP | 276 + CODE/RP/MUNGA/ANGLE.TCP | 170 + CODE/RP/MUNGA/APP.TCP | 97 + CODE/RP/MUNGA/APP.THP | 45 + CODE/RP/MUNGA/APPMGR.CPP | 131 + CODE/RP/MUNGA/APPMGR.HPP | 33 + CODE/RP/MUNGA/APPMSG.CPP | 87 + CODE/RP/MUNGA/APPMSG.HPP | 246 + CODE/RP/MUNGA/APPTASK.CPP | 206 + CODE/RP/MUNGA/APPTASK.HPP | 179 + CODE/RP/MUNGA/AUDCMP.HPP | 751 ++ CODE/RP/MUNGA/AUDENT.CPP | 203 + CODE/RP/MUNGA/AUDENT.HPP | 118 + CODE/RP/MUNGA/AUDIO.CPP | 488 ++ CODE/RP/MUNGA/AUDIO.HPP | 687 ++ CODE/RP/MUNGA/AUDLOC.CPP | 531 ++ CODE/RP/MUNGA/AUDLOC.HPP | 221 + CODE/RP/MUNGA/AUDLVL.CPP | 480 ++ CODE/RP/MUNGA/AUDLVL.HPP | 270 + CODE/RP/MUNGA/AUDMIDI.CPP | 706 ++ CODE/RP/MUNGA/AUDMIDI.HPP | 166 + CODE/RP/MUNGA/AUDSEQ.CPP | 894 +++ CODE/RP/MUNGA/AUDSEQ.HPP | 279 + CODE/RP/MUNGA/AUDSRC.CPP | 848 +++ CODE/RP/MUNGA/AUDSRC.HPP | 699 ++ CODE/RP/MUNGA/AUDTIME.CPP | 83 + CODE/RP/MUNGA/AUDTIME.HPP | 279 + CODE/RP/MUNGA/AUDTOOLS.CPP | 160 + CODE/RP/MUNGA/AUDTOOLS.HPP | 51 + CODE/RP/MUNGA/AUDWGT.CPP | 38 + CODE/RP/MUNGA/AUDWGT.HPP | 164 + CODE/RP/MUNGA/AUDWTHR.CPP | 1072 +++ CODE/RP/MUNGA/AUDWTHR.HPP | 1593 ++++ CODE/RP/MUNGA/AVERAGE.CPP | 21 + CODE/RP/MUNGA/AVERAGE.HPP | 317 + CODE/RP/MUNGA/BNDGBOX.CPP | 458 ++ CODE/RP/MUNGA/BNDGBOX.HPP | 214 + CODE/RP/MUNGA/BOXCONE.CPP | 484 ++ CODE/RP/MUNGA/BOXDISKS.CPP | 1796 +++++ CODE/RP/MUNGA/BOXIRAMP.CPP | 930 +++ CODE/RP/MUNGA/BOXLIST.CPP | 329 + CODE/RP/MUNGA/BOXLIST.HPP | 173 + CODE/RP/MUNGA/BOXRAMP.CPP | 947 +++ CODE/RP/MUNGA/BOXSOLID.CPP | 1439 ++++ CODE/RP/MUNGA/BOXSOLID.HPP | 1004 +++ CODE/RP/MUNGA/BOXSOLID.TCP | 378 + CODE/RP/MUNGA/BOXSORT.CPP | 495 ++ CODE/RP/MUNGA/BOXSPHR.CPP | 260 + CODE/RP/MUNGA/BOXTILE.CPP | 672 ++ CODE/RP/MUNGA/BOXTREE.CPP | 1365 ++++ CODE/RP/MUNGA/BOXWEDGE.CPP | 892 +++ CODE/RP/MUNGA/CAMINST.CPP | 590 ++ CODE/RP/MUNGA/CAMINST.HPP | 201 + CODE/RP/MUNGA/CAMMGR.CPP | 779 ++ CODE/RP/MUNGA/CAMMGR.HPP | 159 + CODE/RP/MUNGA/CAMMPPR.CPP | 262 + CODE/RP/MUNGA/CAMMPPR.HPP | 163 + CODE/RP/MUNGA/CAMSHIP.CPP | 767 ++ CODE/RP/MUNGA/CAMSHIP.HPP | 284 + CODE/RP/MUNGA/CHAIN.CPP | 474 ++ CODE/RP/MUNGA/CHAIN.HPP | 367 + CODE/RP/MUNGA/CMPNNT.CPP | 90 + CODE/RP/MUNGA/CMPNNT.HPP | 73 + CODE/RP/MUNGA/COLLASST.CPP | 392 + CODE/RP/MUNGA/COLLASST.HPP | 206 + CODE/RP/MUNGA/COLLORGN.CPP | 167 + CODE/RP/MUNGA/COLLORGN.HPP | 80 + CODE/RP/MUNGA/COLOR.CPP | 97 + CODE/RP/MUNGA/COLOR.HPP | 194 + CODE/RP/MUNGA/CONFIG.HPP | 158 + CODE/RP/MUNGA/CONSOLE.CPP | 103 + CODE/RP/MUNGA/CONSOLE.HPP | 306 + CODE/RP/MUNGA/CONTROLS.CPP | 682 ++ CODE/RP/MUNGA/CONTROLS.HPP | 947 +++ CODE/RP/MUNGA/CONTROLS.TCP | 303 + CODE/RP/MUNGA/CONTROLS.THP | 88 + CODE/RP/MUNGA/CSTR.HPP | 1089 +++ CODE/RP/MUNGA/CSTR.TCP | 79 + CODE/RP/MUNGA/CULTURAL.HPP | 388 + CODE/RP/MUNGA/DAMAGE.CPP | 834 ++ CODE/RP/MUNGA/DAMAGE.HPP | 428 ++ CODE/RP/MUNGA/DEBUG1ON.HPP | 141 + CODE/RP/MUNGA/DEBUG2ON.HPP | 185 + CODE/RP/MUNGA/DEBUGOFF.HPP | 72 + CODE/RP/MUNGA/DEBUGOLD.HPP | 24 + CODE/RP/MUNGA/DIRECTOR.CPP | 346 + CODE/RP/MUNGA/DIRECTOR.HPP | 192 + CODE/RP/MUNGA/DOOR.CPP | 566 ++ CODE/RP/MUNGA/DOOR.HPP | 185 + CODE/RP/MUNGA/DOORFRAM.CPP | 309 + CODE/RP/MUNGA/DOORFRAM.HPP | 90 + CODE/RP/MUNGA/DROPZONE.HPP | 174 + CODE/RP/MUNGA/ENTITY.CPP | 1622 ++++ CODE/RP/MUNGA/ENTITY.HPP | 645 ++ CODE/RP/MUNGA/ENTITY.TCP | 255 + CODE/RP/MUNGA/ENTITY.THP | 118 + CODE/RP/MUNGA/ENTITY2.CPP | 129 + CODE/RP/MUNGA/ENTITY2.HPP | 163 + CODE/RP/MUNGA/ENTITY3.HPP | 341 + CODE/RP/MUNGA/ENTITYID.CPP | 226 + CODE/RP/MUNGA/ENTITYID.HPP | 101 + CODE/RP/MUNGA/ENVIRNMT.CPP | 125 + CODE/RP/MUNGA/ENVIRNMT.HPP | 131 + CODE/RP/MUNGA/EVENT.CPP | 1110 +++ CODE/RP/MUNGA/EVENT.HPP | 375 + CODE/RP/MUNGA/EVENT.TCP | 174 + CODE/RP/MUNGA/EVTSTAT.CPP | 167 + CODE/RP/MUNGA/EVTSTAT.HPP | 92 + CODE/RP/MUNGA/EXPLODE.HPP | 216 + CODE/RP/MUNGA/EXPTBL.HPP | 236 + CODE/RP/MUNGA/EXTNTBOX.CPP | 280 + CODE/RP/MUNGA/EXTNTBOX.HPP | 110 + CODE/RP/MUNGA/EYECANDY.CPP | 262 + CODE/RP/MUNGA/EYECANDY.HPP | 120 + CODE/RP/MUNGA/FILESTRM.CPP | 152 + CODE/RP/MUNGA/FILESTRM.HPP | 118 + CODE/RP/MUNGA/FILESTUB.CPP | 77 + CODE/RP/MUNGA/FILEUTIL.HPP | 177 + CODE/RP/MUNGA/GAUGALRM.CPP | 437 ++ CODE/RP/MUNGA/GAUGALRM.HPP | 128 + CODE/RP/MUNGA/GAUGE.TCP | 144 + CODE/RP/MUNGA/GAUGMAP.HPP | 165 + CODE/RP/MUNGA/GRAPH2D.HPP | 806 ++ CODE/RP/MUNGA/HASH.CPP | 546 ++ CODE/RP/MUNGA/HASH.HPP | 354 + CODE/RP/MUNGA/HASH.TCP | 420 + CODE/RP/MUNGA/HEAP.HPP | 121 + CODE/RP/MUNGA/HOST.CPP | 159 + CODE/RP/MUNGA/HOST.HPP | 238 + CODE/RP/MUNGA/HOST.TCP | 56 + CODE/RP/MUNGA/HOSTID.HPP | 34 + CODE/RP/MUNGA/HOSTMGR.CPP | 733 ++ CODE/RP/MUNGA/HOSTMGR.HPP | 404 + CODE/RP/MUNGA/ICOM.CPP | 496 ++ CODE/RP/MUNGA/ICOM.HPP | 263 + CODE/RP/MUNGA/INTEREST.CPP | 2629 +++++++ CODE/RP/MUNGA/INTEREST.HPP | 603 ++ CODE/RP/MUNGA/INTORGN.CPP | 177 + CODE/RP/MUNGA/INTORGN.HPP | 205 + CODE/RP/MUNGA/ITERATOR.CPP | 179 + CODE/RP/MUNGA/ITERATOR.HPP | 174 + CODE/RP/MUNGA/JMOVER.CPP | 2068 +++++ CODE/RP/MUNGA/JMOVER.HPP | 270 + CODE/RP/MUNGA/JOINT.CPP | 534 ++ CODE/RP/MUNGA/JOINT.HPP | 297 + CODE/RP/MUNGA/LAMP.CPP | 380 + CODE/RP/MUNGA/LATTICE.CPP | 718 ++ CODE/RP/MUNGA/LATTICE.HPP | 512 ++ CODE/RP/MUNGA/LINE.CPP | 87 + CODE/RP/MUNGA/LINE.HPP | 70 + CODE/RP/MUNGA/LINK.CPP | 128 + CODE/RP/MUNGA/LINK.HPP | 99 + CODE/RP/MUNGA/LINMTRX.CPP | 165 + CODE/RP/MUNGA/LINMTRX.HPP | 181 + CODE/RP/MUNGA/LINMTRX.TCP | 23 + CODE/RP/MUNGA/MATRIX.CPP | 689 ++ CODE/RP/MUNGA/MATRIX.HPP | 261 + CODE/RP/MUNGA/MATRIX.TCP | 22 + CODE/RP/MUNGA/MEMBLOCK.CPP | 678 ++ CODE/RP/MUNGA/MEMBLOCK.HPP | 205 + CODE/RP/MUNGA/MEMBLOCK.TCP | 43 + CODE/RP/MUNGA/MEMREG.HPP | 121 + CODE/RP/MUNGA/MEMSTRM.CPP | 269 + CODE/RP/MUNGA/MEMSTRM.HPP | 346 + CODE/RP/MUNGA/MISSION.CPP | 649 ++ CODE/RP/MUNGA/MISSION.HPP | 316 + CODE/RP/MUNGA/MODE.CPP | 75 + CODE/RP/MUNGA/MODE.HPP | 107 + CODE/RP/MUNGA/MOTION.CPP | 110 + CODE/RP/MUNGA/MOTION.HPP | 88 + CODE/RP/MUNGA/MOVER.CPP | 2126 ++++++ CODE/RP/MUNGA/MOVER.HPP | 484 ++ CODE/RP/MUNGA/MTRXSTK.CPP | 65 + CODE/RP/MUNGA/MTRXSTK.HPP | 150 + CODE/RP/MUNGA/MUNGA.HPP | 83 + CODE/RP/MUNGA/MUNGA.MAK | 255 + CODE/RP/MUNGA/NAMELIST.CPP | 475 ++ CODE/RP/MUNGA/NAMELIST.HPP | 230 + CODE/RP/MUNGA/NAMELIST.TCP | 305 + CODE/RP/MUNGA/NETWORK.HPP | 289 + CODE/RP/MUNGA/NODE.CPP | 52 + CODE/RP/MUNGA/NODE.HPP | 76 + CODE/RP/MUNGA/NORMAL.CPP | 69 + CODE/RP/MUNGA/NORMAL.HPP | 116 + CODE/RP/MUNGA/NORMAL.TCP | 22 + CODE/RP/MUNGA/NOTATION.CPP | 2151 ++++++ CODE/RP/MUNGA/NOTATION.HPP | 511 ++ CODE/RP/MUNGA/NOTATION.TCP | 450 ++ CODE/RP/MUNGA/NTTMGR.CPP | 251 + CODE/RP/MUNGA/NTTMGR.HPP | 149 + CODE/RP/MUNGA/OBJSTRM.HPP | 363 + CODE/RP/MUNGA/ORIGIN.CPP | 159 + CODE/RP/MUNGA/ORIGIN.HPP | 133 + CODE/RP/MUNGA/ORIGIN.TCP | 67 + CODE/RP/MUNGA/PLANE.CPP | 219 + CODE/RP/MUNGA/PLANE.HPP | 139 + CODE/RP/MUNGA/PLAYER.HPP | 486 ++ CODE/RP/MUNGA/PLUG.CPP | 523 ++ CODE/RP/MUNGA/PLUG.HPP | 383 + CODE/RP/MUNGA/POINT2D.HPP | 149 + CODE/RP/MUNGA/POINT3D.CPP | 92 + CODE/RP/MUNGA/POINT3D.HPP | 192 + CODE/RP/MUNGA/POINT3D.TCP | 137 + CODE/RP/MUNGA/RANDOM.HPP | 74 + CODE/RP/MUNGA/RANDOM.TCP | 44 + CODE/RP/MUNGA/RAY.HPP | 103 + CODE/RP/MUNGA/RAY.TCP | 22 + CODE/RP/MUNGA/RECEIVER.HPP | 589 ++ CODE/RP/MUNGA/RECEIVER.TCP | 510 ++ CODE/RP/MUNGA/RECEIVER.THP | 137 + CODE/RP/MUNGA/RECT2D.CPP | 162 + CODE/RP/MUNGA/RECT2D.HPP | 90 + CODE/RP/MUNGA/RECT2D.TCP | 128 + CODE/RP/MUNGA/REGISTRY.CPP | 738 ++ CODE/RP/MUNGA/REGISTRY.HPP | 237 + CODE/RP/MUNGA/RENDERER.CPP | 1069 +++ CODE/RP/MUNGA/RENDERER.HPP | 782 ++ CODE/RP/MUNGA/RENDERER.TCP | 57 + CODE/RP/MUNGA/RENDERER.THP | 48 + CODE/RP/MUNGA/RESOURCE.HPP | 462 ++ CODE/RP/MUNGA/RESOURCE.TCP | 759 ++ CODE/RP/MUNGA/RESVER.HPP | 7 + CODE/RP/MUNGA/RETICLE.CPP | 120 + CODE/RP/MUNGA/RETICLE.HPP | 91 + CODE/RP/MUNGA/RNDORGN.CPP | 214 + CODE/RP/MUNGA/RNDORGN.HPP | 144 + CODE/RP/MUNGA/ROTATION.TCP | 202 + CODE/RP/MUNGA/SCALAR.CPP | 247 + CODE/RP/MUNGA/SCALAR.HPP | 74 + CODE/RP/MUNGA/SCHAIN.CPP | 505 ++ CODE/RP/MUNGA/SCHAIN.HPP | 324 + CODE/RP/MUNGA/SCHAIN.TCP | 526 ++ CODE/RP/MUNGA/SCNROLE.HPP | 162 + CODE/RP/MUNGA/SEGMENT.CPP | 294 + CODE/RP/MUNGA/SEGMENT.HPP | 266 + CODE/RP/MUNGA/SET.CPP | 162 + CODE/RP/MUNGA/SFESKT.CPP | 169 + CODE/RP/MUNGA/SFESKT.HPP | 86 + CODE/RP/MUNGA/SIMULATE.CPP | 733 ++ CODE/RP/MUNGA/SIMULATE.HPP | 413 + CODE/RP/MUNGA/SIMULATE.TCP | 201 + CODE/RP/MUNGA/SLOT.CPP | 192 + CODE/RP/MUNGA/SLOT.HPP | 166 + CODE/RP/MUNGA/SOCKET.CPP | 280 + CODE/RP/MUNGA/SOCKET.HPP | 256 + CODE/RP/MUNGA/SPHERE.CPP | 55 + CODE/RP/MUNGA/SPHERE.HPP | 62 + CODE/RP/MUNGA/SPLINE.CPP | 117 + CODE/RP/MUNGA/SPLINE.HPP | 43 + CODE/RP/MUNGA/SPOOLER.CPP | 297 + CODE/RP/MUNGA/SPOOLER.HPP | 76 + CODE/RP/MUNGA/SRTSKT.CPP | 75 + CODE/RP/MUNGA/SRTSKT.HPP | 88 + CODE/RP/MUNGA/STATE.HPP | 108 + CODE/RP/MUNGA/STYLE.HPP | 166 + CODE/RP/MUNGA/SUBSYSTM.HPP | 202 + CODE/RP/MUNGA/TABLE.CPP | 813 ++ CODE/RP/MUNGA/TABLE.HPP | 559 ++ CODE/RP/MUNGA/TABLE.TCP | 532 ++ CODE/RP/MUNGA/TEAM.HPP | 197 + CODE/RP/MUNGA/TERRAIN.HPP | 182 + CODE/RP/MUNGA/TESTALL.CPP | 244 + CODE/RP/MUNGA/TESTCLAS.HPP | 137 + CODE/RP/MUNGA/TIME.CPP | 137 + CODE/RP/MUNGA/TIME.HPP | 164 + CODE/RP/MUNGA/TIME.TCP | 100 + CODE/RP/MUNGA/TIMESTUB.CPP | 56 + CODE/RP/MUNGA/TOOL.CPP | 891 +++ CODE/RP/MUNGA/TOOL.HPP | 257 + CODE/RP/MUNGA/TRACE.CPP | 584 ++ CODE/RP/MUNGA/TRACE.HPP | 420 + CODE/RP/MUNGA/TRACSTUB.CPP | 38 + CODE/RP/MUNGA/TREE.CPP | 865 +++ CODE/RP/MUNGA/TREE.HPP | 571 ++ CODE/RP/MUNGA/TREE.TCP | 521 ++ CODE/RP/MUNGA/UNITVEC.CPP | 66 + CODE/RP/MUNGA/UNITVEC.HPP | 118 + CODE/RP/MUNGA/UNITVEC.TCP | 77 + CODE/RP/MUNGA/UPDATE.CPP | 273 + CODE/RP/MUNGA/UPDATE.HPP | 109 + CODE/RP/MUNGA/VCHAIN.CPP | 647 ++ CODE/RP/MUNGA/VCHAIN.HPP | 631 ++ CODE/RP/MUNGA/VCHAIN.TCP | 531 ++ CODE/RP/MUNGA/VDATA.CPP | 158 + CODE/RP/MUNGA/VECTOR3D.CPP | 479 ++ CODE/RP/MUNGA/VECTOR3D.HPP | 421 ++ CODE/RP/MUNGA/VECTOR3D.TCP | 185 + CODE/RP/MUNGA/VECTOR4D.CPP | 393 + CODE/RP/MUNGA/VECTOR4D.HPP | 229 + CODE/RP/MUNGA/VECTOR4D.TCP | 140 + CODE/RP/MUNGA/VERIFY.HPP | 61 + CODE/RP/MUNGA/VIDREND.CPP | 283 + CODE/RP/MUNGA/VIDREND.HPP | 150 + CODE/RP/MUNGA/VIDREND.TCP | 21 + CODE/RP/MUNGA/WATCHER.CPP | 224 + CODE/RP/MUNGA/WATCHER.HPP | 337 + CODE/RP/MUNGA/WATCHER.TCP | 198 + CODE/RP/MUNGA/WRHOUS.CPP | 185 + CODE/RP/MUNGA/WRHOUS.HPP | 481 ++ CODE/RP/MUNGA/mssccprj.scc | 5 + CODE/RP/MUNGA/opt/ANGLE.obj | Bin 0 -> 3671 bytes CODE/RP/MUNGA/opt/APPMSG.obj | Bin 0 -> 3052 bytes CODE/RP/MUNGA/opt/AUDWGT.obj | Bin 0 -> 4960 bytes CODE/RP/MUNGA/opt/BOXLIST.obj | Bin 0 -> 4388 bytes CODE/RP/MUNGA/opt/BOXSORT.obj | Bin 0 -> 4512 bytes CODE/RP/MUNGA/opt/BOXSPHR.obj | Bin 0 -> 4714 bytes CODE/RP/MUNGA/opt/CMPNNT.obj | Bin 0 -> 4094 bytes CODE/RP/MUNGA/opt/COLOR.obj | Bin 0 -> 3659 bytes CODE/RP/MUNGA/opt/CONSOLE.obj | Bin 0 -> 2901 bytes CODE/RP/MUNGA/opt/ENTITYID.obj | Bin 0 -> 3728 bytes CODE/RP/MUNGA/opt/ENVIRNMT.obj | Bin 0 -> 4370 bytes CODE/RP/MUNGA/opt/FILESTRM.obj | Bin 0 -> 3913 bytes CODE/RP/MUNGA/opt/FILESTUB.obj | Bin 0 -> 2882 bytes CODE/RP/MUNGA/opt/INTORGN.obj | Bin 0 -> 4647 bytes CODE/RP/MUNGA/opt/ITERATOR.obj | Bin 0 -> 4318 bytes CODE/RP/MUNGA/opt/LINE.obj | Bin 0 -> 2978 bytes CODE/RP/MUNGA/opt/LINK.obj | Bin 0 -> 2643 bytes CODE/RP/MUNGA/opt/LINMTRX.obj | Bin 0 -> 3568 bytes CODE/RP/MUNGA/opt/MEMBLOCK.obj | Bin 0 -> 4488 bytes CODE/RP/MUNGA/opt/MEMSTRM.obj | Bin 0 -> 4719 bytes CODE/RP/MUNGA/opt/MODE.obj | Bin 0 -> 2656 bytes CODE/RP/MUNGA/opt/MOTION.obj | Bin 0 -> 3218 bytes CODE/RP/MUNGA/opt/MTRXSTK.obj | Bin 0 -> 3102 bytes CODE/RP/MUNGA/opt/NAMELIST.obj | Bin 0 -> 4408 bytes CODE/RP/MUNGA/opt/NODE.obj | Bin 0 -> 2744 bytes CODE/RP/MUNGA/opt/NORMAL.obj | Bin 0 -> 2621 bytes CODE/RP/MUNGA/opt/ORIGIN.obj | Bin 0 -> 3839 bytes CODE/RP/MUNGA/opt/PLANE.obj | Bin 0 -> 4395 bytes CODE/RP/MUNGA/opt/POINT3D.obj | Bin 0 -> 2990 bytes CODE/RP/MUNGA/opt/RANDOM.obj | Bin 0 -> 3191 bytes CODE/RP/MUNGA/opt/RAY.obj | Bin 0 -> 3844 bytes CODE/RP/MUNGA/opt/RECT2D.obj | Bin 0 -> 4316 bytes CODE/RP/MUNGA/opt/RETICLE.obj | Bin 0 -> 3888 bytes CODE/RP/MUNGA/opt/SCALAR.obj | Bin 0 -> 3717 bytes CODE/RP/MUNGA/opt/SFESKT.obj | Bin 0 -> 4389 bytes CODE/RP/MUNGA/opt/SLOT.obj | Bin 0 -> 3609 bytes CODE/RP/MUNGA/opt/SOCKET.obj | Bin 0 -> 4575 bytes CODE/RP/MUNGA/opt/SPHERE.obj | Bin 0 -> 2874 bytes CODE/RP/MUNGA/opt/SPLINE.obj | Bin 0 -> 3252 bytes CODE/RP/MUNGA/opt/SRTSKT.obj | Bin 0 -> 4683 bytes CODE/RP/MUNGA/opt/TESTALL.obj | Bin 0 -> 3025 bytes CODE/RP/MUNGA/opt/TIME.obj | Bin 0 -> 2820 bytes CODE/RP/MUNGA/opt/TIMESTUB.obj | Bin 0 -> 2670 bytes CODE/RP/MUNGA/opt/TRACE.obj | Bin 0 -> 2271 bytes CODE/RP/MUNGA/opt/TRACSTUB.obj | Bin 0 -> 2329 bytes CODE/RP/MUNGA/opt/UNITVEC.obj | Bin 0 -> 2615 bytes CODE/RP/MUNGA/opt/opt.cfg | 34 + CODE/RP/MUNGA_L4/JOYSTICK.ASM | 147 + CODE/RP/MUNGA_L4/L4APP.HPP | 237 + CODE/RP/MUNGA_L4/L4APP.TCP | 82 + CODE/RP/MUNGA_L4/L4APP.THP | 50 + CODE/RP/MUNGA_L4/L4ASM.INC | 386 + CODE/RP/MUNGA_L4/L4AUDHDW.CPP | 1006 +++ CODE/RP/MUNGA_L4/L4AUDHDW.HPP | 821 ++ CODE/RP/MUNGA_L4/L4AUDHDW.TCP | 1854 +++++ CODE/RP/MUNGA_L4/L4AUDIO.CPP | 2329 ++++++ CODE/RP/MUNGA_L4/L4AUDIO.HPP | 819 ++ CODE/RP/MUNGA_L4/L4AUDLVL.CPP | 220 + CODE/RP/MUNGA_L4/L4AUDLVL.HPP | 142 + CODE/RP/MUNGA_L4/L4AUDRES.CPP | 1019 +++ CODE/RP/MUNGA_L4/L4AUDRES.HPP | 185 + CODE/RP/MUNGA_L4/L4AUDRND.CPP | 1383 ++++ CODE/RP/MUNGA_L4/L4AUDRND.HPP | 231 + CODE/RP/MUNGA_L4/L4AUDTUL.CPP | 83 + CODE/RP/MUNGA_L4/L4AUDWTR.CPP | 210 + CODE/RP/MUNGA_L4/L4AUDWTR.HPP | 113 + CODE/RP/MUNGA_L4/L4CTLTUL.CPP | 31 + CODE/RP/MUNGA_L4/L4CTRL.CPP | 2429 ++++++ CODE/RP/MUNGA_L4/L4CTRL.HPP | 692 ++ CODE/RP/MUNGA_L4/L4CTRL.TCP | 448 ++ CODE/RP/MUNGA_L4/L4CTRL.THP | 88 + CODE/RP/MUNGA_L4/L4DPLMEM.CPP | 45 + CODE/RP/MUNGA_L4/L4FILE.CPP | 210 + CODE/RP/MUNGA_L4/L4GAUIMA.CPP | 1696 +++++ CODE/RP/MUNGA_L4/L4GAUIMA.HPP | 279 + CODE/RP/MUNGA_L4/L4GAUIMM.HPP | 7 + CODE/RP/MUNGA_L4/L4GAUTUL.CPP | 122 + CODE/RP/MUNGA_L4/L4GREND.CPP | 858 +++ CODE/RP/MUNGA_L4/L4GREND.HPP | 182 + CODE/RP/MUNGA_L4/L4HOST.CPP | 61 + CODE/RP/MUNGA_L4/L4HOST.HPP | 115 + CODE/RP/MUNGA_L4/L4ICOM.CPP | 1054 +++ CODE/RP/MUNGA_L4/L4ICOM.HPP | 194 + CODE/RP/MUNGA_L4/L4JOYSTK.HPP | 118 + CODE/RP/MUNGA_L4/L4KEYBD.CPP | 37 + CODE/RP/MUNGA_L4/L4KEYBD.HPP | 142 + CODE/RP/MUNGA_L4/L4LAMP.CPP | 411 + CODE/RP/MUNGA_L4/L4LAMP.HPP | 169 + CODE/RP/MUNGA_L4/L4MOUSE.CPP | 188 + CODE/RP/MUNGA_L4/L4MOUSE.HPP | 37 + CODE/RP/MUNGA_L4/L4MPPR.CPP | 393 + CODE/RP/MUNGA_L4/L4MPPR.HPP | 174 + CODE/RP/MUNGA_L4/L4MSSN.CPP | 228 + CODE/RP/MUNGA_L4/L4MSSN.HPP | 50 + CODE/RP/MUNGA_L4/L4NET.HPP | 464 ++ CODE/RP/MUNGA_L4/L4NET.TCP | 418 + CODE/RP/MUNGA_L4/L4PCSPAK.HPP | 280 + CODE/RP/MUNGA_L4/L4PLASMA.CPP | 333 + CODE/RP/MUNGA_L4/L4PLASMA.HPP | 70 + CODE/RP/MUNGA_L4/L4RIO.CPP | 1675 ++++ CODE/RP/MUNGA_L4/L4RIO.HPP | 342 + CODE/RP/MUNGA_L4/L4SERIAL.ASM | 1248 +++ CODE/RP/MUNGA_L4/L4SERIAL.HPP | 260 + CODE/RP/MUNGA_L4/L4SPLR.HPP | 234 + CODE/RP/MUNGA_L4/L4SVGA16.ASM | 654 ++ CODE/RP/MUNGA_L4/L4TIME.CPP | 153 + CODE/RP/MUNGA_L4/L4TIME.HPP | 12 + CODE/RP/MUNGA_L4/L4TOOL.HPP | 89 + CODE/RP/MUNGA_L4/L4TRACE.CPP | 133 + CODE/RP/MUNGA_L4/L4TSTALL.CPP | 143 + CODE/RP/MUNGA_L4/L4VB16.CPP | 5500 ++++++++++++++ CODE/RP/MUNGA_L4/L4VB16.HPP | 505 ++ CODE/RP/MUNGA_L4/L4VB8.CPP | 3035 ++++++++ CODE/RP/MUNGA_L4/L4VB8.HPP | 278 + CODE/RP/MUNGA_L4/L4VIDEO.CPP | 6708 ++++++++++++++++ CODE/RP/MUNGA_L4/L4VIDEO.HPP | 637 ++ CODE/RP/MUNGA_L4/L4VIDEO.TCP | 75 + CODE/RP/MUNGA_L4/L4VIDPER.CPP | 484 ++ CODE/RP/MUNGA_L4/L4VIDPER.HPP | 148 + CODE/RP/MUNGA_L4/L4VIDRND.CPP | 6725 +++++++++++++++++ CODE/RP/MUNGA_L4/L4VIDRND.HPP | 2442 ++++++ CODE/RP/MUNGA_L4/L4VIDTUL.CPP | 43 + CODE/RP/MUNGA_L4/L4WRHOUS.CPP | 63 + CODE/RP/MUNGA_L4/L4WRHOUS.HPP | 42 + CODE/RP/MUNGA_L4/MUNGAL4.HPP | 28 + CODE/RP/MUNGA_L4/NETSHARE.ASM | 138 + CODE/RP/MUNGA_L4/NetNub/ANALYSIS.CPP | 239 + CODE/RP/MUNGA_L4/NetNub/ANALYSIS.HPP | 58 + CODE/RP/MUNGA_L4/NetNub/NETNUB.HPP | 387 + CODE/RP/MUNGA_L4/NetNub/NOPAUSE.CPP | 72 + CODE/RP/MUNGA_L4/NetNub/PROFILE.HPP | 715 ++ CODE/RP/MUNGA_L4/NetNub/include/BOOTP.H | 73 + CODE/RP/MUNGA_L4/NetNub/include/COPYRIGH.H | 110 + CODE/RP/MUNGA_L4/NetNub/include/ELIB.H | 25 + CODE/RP/MUNGA_L4/NetNub/include/ETHDEV.H | 16 + CODE/RP/MUNGA_L4/NetNub/include/ICMP.H | 101 + CODE/RP/MUNGA_L4/NetNub/include/STATE.RST | 13 + CODE/RP/MUNGA_L4/NetNub/include/TCP.H | 98 + CODE/RP/MUNGA_L4/NetNub/include/TCP.MOD | 288 + CODE/RP/MUNGA_L4/NetNub/include/WATTCP.H | 735 ++ CODE/RP/MUNGA_L4/NetNub/include/vssver.scc | Bin 0 -> 176 bytes CODE/RP/MUNGA_L4/NetNub/lib/WATTCPLG.LIB | Bin 0 -> 150016 bytes CODE/RP/MUNGA_L4/NetNub/lib/vssver.scc | Bin 0 -> 48 bytes CODE/RP/MUNGA_L4/NetNub/mssccprj.scc | 5 + CODE/RP/MUNGA_L4/NetNub/netnub.mak | 95 + CODE/RP/MUNGA_L4/NetNub/vssver.scc | Bin 0 -> 144 bytes CODE/RP/MUNGA_L4/PCDPMI.INC | 192 + CODE/RP/MUNGA_L4/PCPIC.INC | 82 + CODE/RP/MUNGA_L4/PCSERIAL.INC | 266 + CODE/RP/MUNGA_L4/PCSPAK.ASM | 2044 +++++ CODE/RP/MUNGA_L4/SOSMAWE.C | 458 ++ CODE/RP/MUNGA_L4/SOSMAWE.H | 16 + CODE/RP/MUNGA_L4/SPEAKER.HPP | 9 + CODE/RP/MUNGA_L4/STARTDPL.C | 275 + CODE/RP/MUNGA_L4/joystick.OBJ | Bin 0 -> 612 bytes CODE/RP/MUNGA_L4/l4serial.OBJ | Bin 0 -> 2312 bytes CODE/RP/MUNGA_L4/l4svga16.OBJ | Bin 0 -> 1260 bytes CODE/RP/MUNGA_L4/libDPL/LIBDPL.LIB | Bin 0 -> 599040 bytes CODE/RP/MUNGA_L4/libDPL/VREND.MNG | Bin 0 -> 385404 bytes CODE/RP/MUNGA_L4/libDPL/VREND2.BTL | Bin 0 -> 87075 bytes CODE/RP/MUNGA_L4/libDPL/VREND3.BTL | Bin 0 -> 88860 bytes CODE/RP/MUNGA_L4/libDPL/VREND4.BTL | Bin 0 -> 90689 bytes CODE/RP/MUNGA_L4/libDPL/VREND5.BTL | Bin 0 -> 92518 bytes CODE/RP/MUNGA_L4/libDPL/VREND6.BTL | Bin 0 -> 94391 bytes CODE/RP/MUNGA_L4/libDPL/VREND7.BTL | Bin 0 -> 96264 bytes CODE/RP/MUNGA_L4/libDPL/VREND8.BTL | Bin 0 -> 98181 bytes CODE/RP/MUNGA_L4/libDPL/VREND9.BTL | Bin 0 -> 100098 bytes CODE/RP/MUNGA_L4/libDPL/VRENDMON.BTL | Bin 0 -> 85298 bytes CODE/RP/MUNGA_L4/libDPL/VRNOSTEX.MNG | Bin 0 -> 336252 bytes CODE/RP/MUNGA_L4/libDPL/dpl/DPL.H | 590 ++ CODE/RP/MUNGA_L4/libDPL/dpl/DPLTYPES.H | 387 + CODE/RP/MUNGA_L4/libDPL/dpl/DPLUTILS.H | 408 + CODE/RP/MUNGA_L4/libDPL/dpl/DPL_2D.H | 123 + CODE/RP/MUNGA_L4/libDPL/dpl/DPL_PRIV.H | 531 ++ CODE/RP/MUNGA_L4/libDPL/dpl/DPL_VPX.H | 220 + CODE/RP/MUNGA_L4/libDPL/dpl/MATRIX.H | 47 + CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H | 33 + CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H | 24 + CODE/RP/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H | 47 + CODE/RP/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H | 35 + CODE/RP/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H | 95 + CODE/RP/MUNGA_L4/libDPL/dpl/vpx/vssver.scc | Bin 0 -> 160 bytes CODE/RP/MUNGA_L4/libDPL/dpl/vssver.scc | Bin 0 -> 144 bytes CODE/RP/MUNGA_L4/libDPL/dsys/DIVTYPES.DEF | 75 + CODE/RP/MUNGA_L4/libDPL/dsys/DIVTYPES.H | 73 + CODE/RP/MUNGA_L4/libDPL/dsys/DIVVERS.H | 54 + CODE/RP/MUNGA_L4/libDPL/dsys/DLINK.H | 258 + CODE/RP/MUNGA_L4/libDPL/dsys/DM.H | 635 ++ CODE/RP/MUNGA_L4/libDPL/dsys/DP.H | 47 + CODE/RP/MUNGA_L4/libDPL/dsys/DS.H | 48 + CODE/RP/MUNGA_L4/libDPL/dsys/DTCP.H | 165 + CODE/RP/MUNGA_L4/libDPL/dsys/DU.H | 214 + CODE/RP/MUNGA_L4/libDPL/dsys/FILELIB.H | 315 + CODE/RP/MUNGA_L4/libDPL/dsys/GETPARAM.H | 73 + CODE/RP/MUNGA_L4/libDPL/dsys/MAPFILE.H | 99 + CODE/RP/MUNGA_L4/libDPL/dsys/PARSER.H | 122 + CODE/RP/MUNGA_L4/libDPL/dsys/PFBIZTAG.H | 197 + CODE/RP/MUNGA_L4/libDPL/dsys/PFILE.H | 1166 +++ CODE/RP/MUNGA_L4/libDPL/dsys/PFPARSER.H | 97 + CODE/RP/MUNGA_L4/libDPL/dsys/PGENERAL.H | 183 + CODE/RP/MUNGA_L4/libDPL/dsys/PIMAGE.H | 199 + CODE/RP/MUNGA_L4/libDPL/dsys/PTOOL.H | 666 ++ CODE/RP/MUNGA_L4/libDPL/dsys/VDIFILE.H | 229 + CODE/RP/MUNGA_L4/libDPL/dsys/__PFILE.H | 603 ++ CODE/RP/MUNGA_L4/libDPL/dsys/__PTOOL.H | 84 + CODE/RP/MUNGA_L4/libDPL/dsys/vssver.scc | Bin 0 -> 384 bytes CODE/RP/MUNGA_L4/libDPL/dvs/DM.H | 29 + CODE/RP/MUNGA_L4/libDPL/dvs/DMELEM.H | 132 + CODE/RP/MUNGA_L4/libDPL/dvs/VC.H | 818 ++ CODE/RP/MUNGA_L4/libDPL/dvs/VCBODAPP.H | 47 + CODE/RP/MUNGA_L4/libDPL/dvs/VCDATA.H | 60 + CODE/RP/MUNGA_L4/libDPL/dvs/VCDEFS.H | 597 ++ CODE/RP/MUNGA_L4/libDPL/dvs/VCDTYPES.H | 394 + CODE/RP/MUNGA_L4/libDPL/dvs/VCDYNAM.H | 538 ++ CODE/RP/MUNGA_L4/libDPL/dvs/VCELEMEN.H | 840 ++ CODE/RP/MUNGA_L4/libDPL/dvs/VCELTYPE.H | 629 ++ CODE/RP/MUNGA_L4/libDPL/dvs/VCERROR.H | 33 + CODE/RP/MUNGA_L4/libDPL/dvs/VCINPDEF.H | 71 + CODE/RP/MUNGA_L4/libDPL/dvs/VCMACROS.H | 33 + CODE/RP/MUNGA_L4/libDPL/dvs/VCOBJECT.H | 686 ++ CODE/RP/MUNGA_L4/libDPL/dvs/VCSTRUCT.H | 215 + CODE/RP/MUNGA_L4/libDPL/dvs/VCTYPES.H | 178 + CODE/RP/MUNGA_L4/libDPL/dvs/VCVBOSE.H | 100 + CODE/RP/MUNGA_L4/libDPL/dvs/VL.H | 476 ++ CODE/RP/MUNGA_L4/libDPL/dvs/VLTYPES.H | 161 + CODE/RP/MUNGA_L4/libDPL/dvs/_VCSTRUC.H | 569 ++ CODE/RP/MUNGA_L4/libDPL/dvs/_VCTYPES.H | 10 + CODE/RP/MUNGA_L4/libDPL/dvs/vssver.scc | Bin 0 -> 368 bytes CODE/RP/MUNGA_L4/libDPL/vssver.scc | Bin 0 -> 224 bytes CODE/RP/MUNGA_L4/mssccprj.scc | 5 + CODE/RP/MUNGA_L4/mungal4.mak | 160 + CODE/RP/MUNGA_L4/netshare.OBJ | Bin 0 -> 676 bytes CODE/RP/MUNGA_L4/opt/L4DPLMEM.obj | Bin 0 -> 4961 bytes CODE/RP/MUNGA_L4/opt/L4HOST.obj | Bin 0 -> 3421 bytes CODE/RP/MUNGA_L4/opt/L4KEYBD.obj | Bin 0 -> 3086 bytes CODE/RP/MUNGA_L4/opt/L4MOUSE.obj | Bin 0 -> 3325 bytes CODE/RP/MUNGA_L4/opt/L4TIME.obj | Bin 0 -> 4392 bytes CODE/RP/MUNGA_L4/opt/L4TRACE.obj | Bin 0 -> 2969 bytes CODE/RP/MUNGA_L4/opt/L4TSTALL.obj | Bin 0 -> 2985 bytes CODE/RP/MUNGA_L4/opt/SOSMAWE.obj | Bin 0 -> 3448 bytes CODE/RP/MUNGA_L4/opt/STARTDPL.obj | Bin 0 -> 3343 bytes CODE/RP/MUNGA_L4/opt/joystick.OBJ | Bin 0 -> 612 bytes CODE/RP/MUNGA_L4/opt/l4serial.OBJ | Bin 0 -> 2312 bytes CODE/RP/MUNGA_L4/opt/l4svga16.OBJ | Bin 0 -> 1260 bytes CODE/RP/MUNGA_L4/opt/netshare.OBJ | Bin 0 -> 676 bytes CODE/RP/MUNGA_L4/opt/opt.cfg | 34 + CODE/RP/MUNGA_L4/pcspak.OBJ | Bin 0 -> 4499 bytes CODE/RP/MUNGA_L4/sos/HMIMDRV.386 | Bin 0 -> 118008 bytes CODE/RP/MUNGA_L4/sos/SOSDBXC.LIB | Bin 0 -> 45568 bytes CODE/RP/MUNGA_L4/sos/SOSDWXCR.LIB | Bin 0 -> 62464 bytes CODE/RP/MUNGA_L4/sos/SOSDWXCS.LIB | Bin 0 -> 87552 bytes CODE/RP/MUNGA_L4/sos/SOSMAWE.C | 443 ++ CODE/RP/MUNGA_L4/sos/SOSMBXC.LIB | Bin 0 -> 163328 bytes CODE/RP/MUNGA_L4/sos/SOSMW1CR.LIB | Bin 0 -> 99328 bytes CODE/RP/MUNGA_L4/sos/SOSMWXCR.LIB | Bin 0 -> 142336 bytes CODE/RP/MUNGA_L4/sos/SOSMWXCS.LIB | Bin 0 -> 142848 bytes CODE/RP/MUNGA_L4/sos/bc4/SOS.H | 554 ++ CODE/RP/MUNGA_L4/sos/bc4/SOS.INC | 192 + CODE/RP/MUNGA_L4/sos/bc4/SOSDATA.H | 112 + CODE/RP/MUNGA_L4/sos/bc4/SOSDEFS.H | 65 + CODE/RP/MUNGA_L4/sos/bc4/SOSFNCT.H | 209 + CODE/RP/MUNGA_L4/sos/bc4/SOSM.H | 450 ++ CODE/RP/MUNGA_L4/sos/bc4/SOSMAWE.H | 16 + CODE/RP/MUNGA_L4/sos/bc4/SOSMDATA.H | 125 + CODE/RP/MUNGA_L4/sos/bc4/SOSMFNCT.H | 190 + CODE/RP/MUNGA_L4/sos/bc4/SOSRES.H | 110 + CODE/RP/MUNGA_L4/sos/bc4/vssver.scc | Bin 0 -> 192 bytes CODE/RP/MUNGA_L4/sos/vssver.scc | Bin 0 -> 176 bytes CODE/RP/MUNGA_L4/sos/wc/SOS.H | 553 ++ CODE/RP/MUNGA_L4/sos/wc/SOSDATA.H | 110 + CODE/RP/MUNGA_L4/sos/wc/SOSDEFS.H | 65 + CODE/RP/MUNGA_L4/sos/wc/SOSFNCT.H | 208 + CODE/RP/MUNGA_L4/sos/wc/SOSM.H | 455 ++ CODE/RP/MUNGA_L4/sos/wc/SOSMDATA.H | 125 + CODE/RP/MUNGA_L4/sos/wc/SOSMFNCT.H | 175 + CODE/RP/MUNGA_L4/sos/wc/SOSRES.H | 110 + CODE/RP/MUNGA_L4/sos/wc/vssver.scc | Bin 0 -> 160 bytes CODE/RP/MUNGA_L4/vssver.scc | Bin 0 -> 1600 bytes CODE/RP/OPT.mak | 47 + CODE/RP/RP/BLOCKER.HPP | 90 + CODE/RP/RP/BOOSTER.HPP | 174 + CODE/RP/RP/CRUSHER.HPP | 98 + CODE/RP/RP/DEMOPACK.HPP | 142 + CODE/RP/RP/DEMOPACK.bak | 144 + CODE/RP/RP/RP.HPP | 22 + CODE/RP/RP/RPCNSL.CPP | 99 + CODE/RP/RP/RPDIRECT.HPP | 80 + CODE/RP/RP/RPMSSN.CPP | 49 + CODE/RP/RP/RPMSSN.HPP | 51 + CODE/RP/RP/RPREG.HPP | 74 + CODE/RP/RP/RPTOOL.CPP | 209 + CODE/RP/RP/RPTOOL.HPP | 64 + CODE/RP/RP/RUNNER.HPP | 94 + CODE/RP/RP/THRUSTER.HPP | 161 + CODE/RP/RP/VTVPWR.CPP | 154 + CODE/RP/RP/VTVPWR.HPP | 118 + CODE/RP/RP/VTVSUB.CPP | 174 + CODE/RP/RP/VTVSUB.HPP | 102 + CODE/RP/RP/mssccprj.scc | 5 + CODE/RP/RP/opt/opt.cfg | 34 + CODE/RP/RP/rp.mak | 96 + CODE/RP/RP/vssver.scc | Bin 0 -> 704 bytes CODE/RP/RPL4.PTH | 26 + CODE/RP/RP_L4/RPL4.HPP | 12 + CODE/RP/RP_L4/RPL4APP.HPP | 64 + CODE/RP/RP_L4/RPL4ARND.CPP | 46 + CODE/RP/RP_L4/RPL4ARND.HPP | 41 + CODE/RP/RP_L4/RPL4GRND.HPP | 62 + CODE/RP/RP_L4/RPL4MODE.CPP | 84 + CODE/RP/RP_L4/RPL4MODE.HPP | 98 + CODE/RP/RP_L4/RPL4MSSN.HPP | 43 + CODE/RP/RP_L4/RPL4PB.HPP | 116 + CODE/RP/RP_L4/RPL4TOOL.CPP | 158 + CODE/RP/RP_L4/RPL4VER.HPP | 11 + CODE/RP/RP_L4/RPL4VID.HPP | 83 + CODE/RP/RP_L4/mssccprj.scc | 5 + CODE/RP/RP_L4/opt/opt.cfg | 34 + CODE/RP/RP_L4/rpL4.mak | 134 + CODE/RP/RP_L4/vssver.scc | Bin 0 -> 400 bytes CODE/RP/clropt.bat | 5 + CODE/RP/d1.mak | 32 + CODE/RP/d2s.mak | 34 + CODE/RP/d3s.mak | 48 + CODE/RP/example.cfg | 9 + CODE/RP/make.cfg | 12 + CODE/RP/mssccprj.scc | 21 + CODE/RP/opt.bat | 11 + CODE/RP/opt.cfg | 13 + CODE/RP/transfr.bat | 1 + CODE/RP/vssver.scc | Bin 0 -> 336 bytes CONTENT/BT/32STUB.EXE | Bin 0 -> 2160 bytes CONTENT/BT/ANIM.BAT | 64 + CONTENT/BT/ANIM1.BAT | 2 + CONTENT/BT/ANIMCAM.BAT | 2 + CONTENT/BT/ANIMS/AVABMP.ANI | 110 + CONTENT/BT/ANIMS/AVAGSLI.ANI | 160 + CONTENT/BT/ANIMS/AVAGSRI.ANI | 160 + CONTENT/BT/ANIMS/BATBMP.ANI | 110 + CONTENT/BT/ANIMS/BATGSLI.ANI | 160 + CONTENT/BT/ANIMS/BATGSRI.ANI | 160 + CONTENT/BT/ANIMS/BATSQUI.ANI | 274 + CONTENT/BT/ANIMS/BLHBBLI.ANI | 166 + CONTENT/BT/ANIMS/BLHBBRI.ANI | 166 + CONTENT/BT/ANIMS/BLHBMP.ANI | 70 + CONTENT/BT/ANIMS/BLHBMPI.ANI | 70 + CONTENT/BT/ANIMS/BLHGSLI.ANI | 127 + CONTENT/BT/ANIMS/BLHGSRI.ANI | 127 + CONTENT/BT/ANIMS/BLHRRL.ANI | 120 + CONTENT/BT/ANIMS/BLHRRLI.ANI | 153 + CONTENT/BT/ANIMS/BLHRRR.ANI | 120 + CONTENT/BT/ANIMS/BLHRRRI.ANI | 153 + CONTENT/BT/ANIMS/BLHSQI.ANI | 0 CONTENT/BT/ANIMS/BLHSQT.ANI | 0 CONTENT/BT/ANIMS/BLHWWLI.ANI | 166 + CONTENT/BT/ANIMS/FIRBBL.ANI | 98 + CONTENT/BT/ANIMS/FIRBBLI.ANI | 106 + CONTENT/BT/ANIMS/FIRBBR.ANI | 98 + CONTENT/BT/ANIMS/FIRBBRI.ANI | 106 + CONTENT/BT/ANIMS/FIRBMP.ANI | 80 + CONTENT/BT/ANIMS/FIRBMPI.ANI | 85 + CONTENT/BT/ANIMS/FIRBSL.ANI | 140 + CONTENT/BT/ANIMS/FIRBSLI.ANI | 150 + CONTENT/BT/ANIMS/FIRBSR.ANI | 120 + CONTENT/BT/ANIMS/FIRBSRI.ANI | 130 + CONTENT/BT/ANIMS/FIRGGL.ANI | 142 + CONTENT/BT/ANIMS/FIRGGLI.ANI | 154 + CONTENT/BT/ANIMS/FIRGGR.ANI | 142 + CONTENT/BT/ANIMS/FIRGGRI.ANI | 154 + CONTENT/BT/ANIMS/FIRGSLI.ANI | 106 + CONTENT/BT/ANIMS/FIRGSRI.ANI | 106 + CONTENT/BT/ANIMS/FIRRRL.ANI | 87 + CONTENT/BT/ANIMS/FIRRRLI.ANI | 94 + CONTENT/BT/ANIMS/FIRRRR.ANI | 87 + CONTENT/BT/ANIMS/FIRRRRI.ANI | 94 + CONTENT/BT/ANIMS/FIRRWL.ANI | 94 + CONTENT/BT/ANIMS/FIRRWLI.ANI | 100 + CONTENT/BT/ANIMS/FIRRWR.ANI | 94 + CONTENT/BT/ANIMS/FIRRWRI.ANI | 100 + CONTENT/BT/ANIMS/FIRSBL.ANI | 109 + CONTENT/BT/ANIMS/FIRSBLI.ANI | 118 + CONTENT/BT/ANIMS/FIRSBR.ANI | 109 + CONTENT/BT/ANIMS/FIRSBRI.ANI | 118 + CONTENT/BT/ANIMS/FIRSWL.ANI | 87 + CONTENT/BT/ANIMS/FIRSWLI.ANI | 94 + CONTENT/BT/ANIMS/FIRSWR.ANI | 87 + CONTENT/BT/ANIMS/FIRSWRI.ANI | 94 + CONTENT/BT/ANIMS/FIRTRN.ANI | 87 + CONTENT/BT/ANIMS/FIRTRNI.ANI | 94 + CONTENT/BT/ANIMS/FIRWGL.ANI | 98 + CONTENT/BT/ANIMS/FIRWGLI.ANI | 106 + CONTENT/BT/ANIMS/FIRWGR.ANI | 98 + CONTENT/BT/ANIMS/FIRWGRI.ANI | 106 + CONTENT/BT/ANIMS/FIRWRL.ANI | 154 + CONTENT/BT/ANIMS/FIRWRLI.ANI | 166 + CONTENT/BT/ANIMS/FIRWRR.ANI | 154 + CONTENT/BT/ANIMS/FIRWRRI.ANI | 166 + CONTENT/BT/ANIMS/FIRWSL.ANI | 87 + CONTENT/BT/ANIMS/FIRWSLI.ANI | 94 + CONTENT/BT/ANIMS/FIRWSR.ANI | 87 + CONTENT/BT/ANIMS/FIRWSRI.ANI | 94 + CONTENT/BT/ANIMS/FIRWWL.ANI | 120 + CONTENT/BT/ANIMS/FIRWWLI.ANI | 130 + CONTENT/BT/ANIMS/FIRWWR.ANI | 120 + CONTENT/BT/ANIMS/FIRWWRI.ANI | 130 + CONTENT/BT/ANIMS/JAKBBL.ANI | 120 + CONTENT/BT/ANIMS/JAKBBLI.ANI | 130 + CONTENT/BT/ANIMS/JAKBBR.ANI | 120 + CONTENT/BT/ANIMS/JAKBBRI.ANI | 131 + CONTENT/BT/ANIMS/JAKBMP.ANI | 70 + CONTENT/BT/ANIMS/JAKBMPI.ANI | 76 + CONTENT/BT/ANIMS/JAKBSL.ANI | 76 + CONTENT/BT/ANIMS/JAKBSLI.ANI | 83 + CONTENT/BT/ANIMS/JAKBSR.ANI | 76 + CONTENT/BT/ANIMS/JAKBSRI.ANI | 83 + CONTENT/BT/ANIMS/JAKFB.ANI | 760 ++ CONTENT/BT/ANIMS/JAKFF.ANI | 700 ++ CONTENT/BT/ANIMS/JAKFL.ANI | 535 ++ CONTENT/BT/ANIMS/JAKFR.ANI | 700 ++ CONTENT/BT/ANIMS/JAKGGL.ANI | 142 + CONTENT/BT/ANIMS/JAKGGLI.ANI | 154 + CONTENT/BT/ANIMS/JAKGGR.ANI | 142 + CONTENT/BT/ANIMS/JAKGGRI.ANI | 154 + CONTENT/BT/ANIMS/JAKGSLI.ANI | 106 + CONTENT/BT/ANIMS/JAKGSRI.ANI | 106 + CONTENT/BT/ANIMS/JAKRRL.ANI | 131 + CONTENT/BT/ANIMS/JAKRRLI.ANI | 143 + CONTENT/BT/ANIMS/JAKRRR.ANI | 131 + CONTENT/BT/ANIMS/JAKRRRI.ANI | 143 + CONTENT/BT/ANIMS/JAKRWL.ANI | 87 + CONTENT/BT/ANIMS/JAKRWLI.ANI | 95 + CONTENT/BT/ANIMS/JAKRWR.ANI | 87 + CONTENT/BT/ANIMS/JAKRWRI.ANI | 95 + CONTENT/BT/ANIMS/JAKSBL.ANI | 164 + CONTENT/BT/ANIMS/JAKSBR.ANI | 164 + CONTENT/BT/ANIMS/JAKSWL.ANI | 87 + CONTENT/BT/ANIMS/JAKSWLI.ANI | 94 + CONTENT/BT/ANIMS/JAKSWR.ANI | 87 + CONTENT/BT/ANIMS/JAKSWRI.ANI | 94 + CONTENT/BT/ANIMS/JAKTRN.ANI | 87 + CONTENT/BT/ANIMS/JAKTRNI.ANI | 94 + CONTENT/BT/ANIMS/JAKWGL.ANI | 98 + CONTENT/BT/ANIMS/JAKWGLI.ANI | 106 + CONTENT/BT/ANIMS/JAKWGR.ANI | 98 + CONTENT/BT/ANIMS/JAKWGRI.ANI | 106 + CONTENT/BT/ANIMS/JAKWRL.ANI | 142 + CONTENT/BT/ANIMS/JAKWRLI.ANI | 155 + CONTENT/BT/ANIMS/JAKWRR.ANI | 142 + CONTENT/BT/ANIMS/JAKWRRI.ANI | 155 + CONTENT/BT/ANIMS/JAKWSL.ANI | 131 + CONTENT/BT/ANIMS/JAKWSLI.ANI | 143 + CONTENT/BT/ANIMS/JAKWSR.ANI | 131 + CONTENT/BT/ANIMS/JAKWSRI.ANI | 143 + CONTENT/BT/ANIMS/JAKWWL.ANI | 98 + CONTENT/BT/ANIMS/JAKWWLI.ANI | 107 + CONTENT/BT/ANIMS/JAKWWR.ANI | 98 + CONTENT/BT/ANIMS/JAKWWRI.ANI | 107 + CONTENT/BT/ANIMS/LOKBBL.ANI | 142 + CONTENT/BT/ANIMS/LOKBBLI.ANI | 82 + CONTENT/BT/ANIMS/LOKBBR.ANI | 142 + CONTENT/BT/ANIMS/LOKBBRI.ANI | 82 + CONTENT/BT/ANIMS/LOKBMP.ANI | 80 + CONTENT/BT/ANIMS/LOKBMPI.ANI | 80 + CONTENT/BT/ANIMS/LOKBSLI.ANI | 82 + CONTENT/BT/ANIMS/LOKBSRI.ANI | 82 + CONTENT/BT/ANIMS/LOKGGL.ANI | 142 + CONTENT/BT/ANIMS/LOKGGLI.ANI | 154 + CONTENT/BT/ANIMS/LOKGGR.ANI | 142 + CONTENT/BT/ANIMS/LOKGGRI.ANI | 154 + CONTENT/BT/ANIMS/LOKGSLI.ANI | 106 + CONTENT/BT/ANIMS/LOKGSRI.ANI | 106 + CONTENT/BT/ANIMS/LOKRRL.ANI | 120 + CONTENT/BT/ANIMS/LOKRRLI.ANI | 130 + CONTENT/BT/ANIMS/LOKRRR.ANI | 120 + CONTENT/BT/ANIMS/LOKRRRI.ANI | 130 + CONTENT/BT/ANIMS/LOKRWL.ANI | 150 + CONTENT/BT/ANIMS/LOKRWLI.ANI | 130 + CONTENT/BT/ANIMS/LOKRWR.ANI | 150 + CONTENT/BT/ANIMS/LOKRWRI.ANI | 130 + CONTENT/BT/ANIMS/LOKSBLI.ANI | 118 + CONTENT/BT/ANIMS/LOKSBRI.ANI | 118 + CONTENT/BT/ANIMS/LOKSWLI.ANI | 166 + CONTENT/BT/ANIMS/LOKSWRI.ANI | 166 + CONTENT/BT/ANIMS/LOKTRN.ANI | 87 + CONTENT/BT/ANIMS/LOKTRNI.ANI | 94 + CONTENT/BT/ANIMS/LOKWGL.ANI | 98 + CONTENT/BT/ANIMS/LOKWGLI.ANI | 106 + CONTENT/BT/ANIMS/LOKWGR.ANI | 98 + CONTENT/BT/ANIMS/LOKWGRI.ANI | 106 + CONTENT/BT/ANIMS/LOKWRL.ANI | 108 + CONTENT/BT/ANIMS/LOKWRLI.ANI | 106 + CONTENT/BT/ANIMS/LOKWRR.ANI | 108 + CONTENT/BT/ANIMS/LOKWRRI.ANI | 106 + CONTENT/BT/ANIMS/LOKWSLI.ANI | 94 + CONTENT/BT/ANIMS/LOKWSRI.ANI | 94 + CONTENT/BT/ANIMS/LOKWWL.ANI | 76 + CONTENT/BT/ANIMS/LOKWWLI.ANI | 82 + CONTENT/BT/ANIMS/LOKWWR.ANI | 76 + CONTENT/BT/ANIMS/LOKWWRI.ANI | 82 + CONTENT/BT/ANIMS/MADBMP.ANI | 110 + CONTENT/BT/ANIMS/MADGSLI.ANI | 160 + CONTENT/BT/ANIMS/MADGSRI.ANI | 160 + CONTENT/BT/ANIMS/OWNBMP.ANI | 80 + CONTENT/BT/ANIMS/OWNBMPI.ANI | 80 + CONTENT/BT/ANIMS/OWNBSLI.ANI | 108 + CONTENT/BT/ANIMS/OWNBSRI.ANI | 108 + CONTENT/BT/ANIMS/OWNGSLI.ANI | 136 + CONTENT/BT/ANIMS/OWNGSRI.ANI | 136 + CONTENT/BT/ANIMS/OWNRRL.ANI | 153 + CONTENT/BT/ANIMS/OWNRRR.ANI | 153 + CONTENT/BT/ANIMS/OWNRRRI.ANI | 136 + CONTENT/BT/ANIMS/OWNRWLI.ANI | 94 + CONTENT/BT/ANIMS/OWNRWRI.ANI | 94 + CONTENT/BT/ANIMS/OWNSQI.ANI | 0 CONTENT/BT/ANIMS/OWNSQT.ANI | 0 CONTENT/BT/ANIMS/OWNSWLI.ANI | 108 + CONTENT/BT/ANIMS/OWNSWRI.ANI | 108 + CONTENT/BT/ANIMS/OWNWGL.ANI | 153 + CONTENT/BT/ANIMS/OWNWGR.ANI | 153 + CONTENT/BT/ANIMS/OWNWSL.ANI | 127 + CONTENT/BT/ANIMS/OWNWSLI.ANI | 150 + CONTENT/BT/ANIMS/OWNWSR.ANI | 140 + CONTENT/BT/ANIMS/OWNWWLI.ANI | 136 + CONTENT/BT/ANIMS/OWNWWRI.ANI | 136 + CONTENT/BT/ANIMS/RAPBBL.ANI | 164 + CONTENT/BT/ANIMS/RAPBBR.ANI | 164 + CONTENT/BT/ANIMS/RAPBMP.ANI | 70 + CONTENT/BT/ANIMS/RAPBMPI.ANI | 75 + CONTENT/BT/ANIMS/RAPGSLI.ANI | 118 + CONTENT/BT/ANIMS/RAPGSRI.ANI | 118 + CONTENT/BT/ANIMS/RAPRRL.ANI | 120 + CONTENT/BT/ANIMS/RAPRRLI.ANI | 130 + CONTENT/BT/ANIMS/RAPRRR.ANI | 120 + CONTENT/BT/ANIMS/RAPRRRI.ANI | 130 + CONTENT/BT/ANIMS/RAPRWL.ANI | 87 + CONTENT/BT/ANIMS/RAPRWLI.ANI | 94 + CONTENT/BT/ANIMS/RAPRWR.ANI | 87 + CONTENT/BT/ANIMS/RAPRWRI.ANI | 94 + CONTENT/BT/ANIMS/RAPSBL.ANI | 131 + CONTENT/BT/ANIMS/RAPSBLI.ANI | 142 + CONTENT/BT/ANIMS/RAPSBR.ANI | 131 + CONTENT/BT/ANIMS/RAPSBRI.ANI | 142 + CONTENT/BT/ANIMS/RAPSQDI.ANI | 263 + CONTENT/BT/ANIMS/RAPSQUI.ANI | 263 + CONTENT/BT/ANIMS/RAPSWL.ANI | 109 + CONTENT/BT/ANIMS/RAPSWLI.ANI | 118 + CONTENT/BT/ANIMS/RAPSWR.ANI | 109 + CONTENT/BT/ANIMS/RAPSWRI.ANI | 118 + CONTENT/BT/ANIMS/RAPWRL.ANI | 153 + CONTENT/BT/ANIMS/RAPWRLI.ANI | 166 + CONTENT/BT/ANIMS/RAPWRR.ANI | 153 + CONTENT/BT/ANIMS/RAPWRRI.ANI | 166 + CONTENT/BT/ANIMS/RAPWWL.ANI | 164 + CONTENT/BT/ANIMS/RAPWWR.ANI | 164 + CONTENT/BT/ANIMS/SNDBBL.ANI | 142 + CONTENT/BT/ANIMS/SNDBBLI.ANI | 82 + CONTENT/BT/ANIMS/SNDBBR.ANI | 142 + CONTENT/BT/ANIMS/SNDBBRI.ANI | 82 + CONTENT/BT/ANIMS/SNDBMP.ANI | 80 + CONTENT/BT/ANIMS/SNDBMPI.ANI | 80 + CONTENT/BT/ANIMS/SNDBSLI.ANI | 82 + CONTENT/BT/ANIMS/SNDBSRI.ANI | 82 + CONTENT/BT/ANIMS/SNDGGL.ANI | 142 + CONTENT/BT/ANIMS/SNDGGLI.ANI | 154 + CONTENT/BT/ANIMS/SNDGGR.ANI | 142 + CONTENT/BT/ANIMS/SNDGGRI.ANI | 154 + CONTENT/BT/ANIMS/SNDGSLI.ANI | 106 + CONTENT/BT/ANIMS/SNDGSRI.ANI | 106 + CONTENT/BT/ANIMS/SNDRRL.ANI | 120 + CONTENT/BT/ANIMS/SNDRRLI.ANI | 130 + CONTENT/BT/ANIMS/SNDRRR.ANI | 120 + CONTENT/BT/ANIMS/SNDRRRI.ANI | 130 + CONTENT/BT/ANIMS/SNDRWL.ANI | 150 + CONTENT/BT/ANIMS/SNDRWLI.ANI | 130 + CONTENT/BT/ANIMS/SNDRWR.ANI | 150 + CONTENT/BT/ANIMS/SNDRWRI.ANI | 130 + CONTENT/BT/ANIMS/SNDSBLI.ANI | 118 + CONTENT/BT/ANIMS/SNDSBRI.ANI | 118 + CONTENT/BT/ANIMS/SNDSWLI.ANI | 166 + CONTENT/BT/ANIMS/SNDSWRI.ANI | 166 + CONTENT/BT/ANIMS/SNDTRN.ANI | 87 + CONTENT/BT/ANIMS/SNDTRNI.ANI | 94 + CONTENT/BT/ANIMS/SNDWGL.ANI | 98 + CONTENT/BT/ANIMS/SNDWGLI.ANI | 106 + CONTENT/BT/ANIMS/SNDWGR.ANI | 98 + CONTENT/BT/ANIMS/SNDWGRI.ANI | 106 + CONTENT/BT/ANIMS/SNDWRL.ANI | 108 + CONTENT/BT/ANIMS/SNDWRLI.ANI | 106 + CONTENT/BT/ANIMS/SNDWRR.ANI | 108 + CONTENT/BT/ANIMS/SNDWRRI.ANI | 106 + CONTENT/BT/ANIMS/SNDWSLI.ANI | 94 + CONTENT/BT/ANIMS/SNDWSRI.ANI | 94 + CONTENT/BT/ANIMS/SNDWWL.ANI | 76 + CONTENT/BT/ANIMS/SNDWWLI.ANI | 82 + CONTENT/BT/ANIMS/SNDWWR.ANI | 76 + CONTENT/BT/ANIMS/SNDWWRI.ANI | 82 + CONTENT/BT/ANIMS/STIBBLI.ANI | 231 + CONTENT/BT/ANIMS/STIBBR.ANI | 231 + CONTENT/BT/ANIMS/STIBMPI.ANI | 100 + CONTENT/BT/ANIMS/STIBSLI.ANI | 129 + CONTENT/BT/ANIMS/STIBSRI.ANI | 129 + CONTENT/BT/ANIMS/STIRRLI.ANI | 214 + CONTENT/BT/ANIMS/STIRRRI.ANI | 214 + CONTENT/BT/ANIMS/STIRWLI.ANI | 180 + CONTENT/BT/ANIMS/STIRWRI.ANI | 180 + CONTENT/BT/ANIMS/STISBLI.ANI | 205 + CONTENT/BT/ANIMS/STISBRI.ANI | 205 + CONTENT/BT/ANIMS/STISQDI.ANI | 274 + CONTENT/BT/ANIMS/STISWLI.ANI | 248 + CONTENT/BT/ANIMS/STISWRI.ANI | 248 + CONTENT/BT/ANIMS/STIWRLI.ANI | 350 + CONTENT/BT/ANIMS/STIWRRI.ANI | 350 + CONTENT/BT/ANIMS/STIWSLI.ANI | 190 + CONTENT/BT/ANIMS/STIWSRI.ANI | 190 + CONTENT/BT/ANIMS/STIWWLI.ANI | 231 + CONTENT/BT/ANIMS/STIWWRI.ANI | 231 + CONTENT/BT/ANIMS/THR4JERR.ANI | 0 CONTENT/BT/ANIMS/THRBBL.ANI | 142 + CONTENT/BT/ANIMS/THRBBLI.ANI | 82 + CONTENT/BT/ANIMS/THRBBR.ANI | 142 + CONTENT/BT/ANIMS/THRBBRI.ANI | 82 + CONTENT/BT/ANIMS/THRBMP.ANI | 80 + CONTENT/BT/ANIMS/THRBMPI.ANI | 80 + CONTENT/BT/ANIMS/THRBSLI.ANI | 82 + CONTENT/BT/ANIMS/THRBSRI.ANI | 82 + CONTENT/BT/ANIMS/THRCLI.ANI | 0 CONTENT/BT/ANIMS/THRCLS.ANI | 148 + CONTENT/BT/ANIMS/THRGGL.ANI | 142 + CONTENT/BT/ANIMS/THRGGLI.ANI | 154 + CONTENT/BT/ANIMS/THRGGR.ANI | 142 + CONTENT/BT/ANIMS/THRGGRI.ANI | 154 + CONTENT/BT/ANIMS/THRGSLI.ANI | 106 + CONTENT/BT/ANIMS/THRGSRI.ANI | 106 + CONTENT/BT/ANIMS/THROPI.ANI | 0 CONTENT/BT/ANIMS/THRRRL.ANI | 120 + CONTENT/BT/ANIMS/THRRRLI.ANI | 130 + CONTENT/BT/ANIMS/THRRRR.ANI | 120 + CONTENT/BT/ANIMS/THRRRRI.ANI | 130 + CONTENT/BT/ANIMS/THRRWL.ANI | 150 + CONTENT/BT/ANIMS/THRRWLI.ANI | 130 + CONTENT/BT/ANIMS/THRRWR.ANI | 150 + CONTENT/BT/ANIMS/THRRWRI.ANI | 130 + CONTENT/BT/ANIMS/THRSBLI.ANI | 118 + CONTENT/BT/ANIMS/THRSBRI.ANI | 118 + CONTENT/BT/ANIMS/THRSQT.ANI | 0 CONTENT/BT/ANIMS/THRSWLI.ANI | 166 + CONTENT/BT/ANIMS/THRSWRI.ANI | 166 + CONTENT/BT/ANIMS/THRTRI.ANI | 0 CONTENT/BT/ANIMS/THRTRN.ANI | 87 + CONTENT/BT/ANIMS/THRTRNI.ANI | 94 + CONTENT/BT/ANIMS/THRTSI.ANI | 0 CONTENT/BT/ANIMS/THRTST.ANI | 0 CONTENT/BT/ANIMS/THRWGL.ANI | 98 + CONTENT/BT/ANIMS/THRWGLI.ANI | 106 + CONTENT/BT/ANIMS/THRWGR.ANI | 98 + CONTENT/BT/ANIMS/THRWGRI.ANI | 106 + CONTENT/BT/ANIMS/THRWRL.ANI | 108 + CONTENT/BT/ANIMS/THRWRLI.ANI | 106 + CONTENT/BT/ANIMS/THRWRR.ANI | 108 + CONTENT/BT/ANIMS/THRWRRI.ANI | 106 + CONTENT/BT/ANIMS/THRWSLI.ANI | 94 + CONTENT/BT/ANIMS/THRWSRI.ANI | 94 + CONTENT/BT/ANIMS/THRWWL.ANI | 76 + CONTENT/BT/ANIMS/THRWWLI.ANI | 82 + CONTENT/BT/ANIMS/THRWWR.ANI | 76 + CONTENT/BT/ANIMS/THRWWRI.ANI | 82 + CONTENT/BT/ARCBT.BAT | 58 + CONTENT/BT/ARCFILES.LST | 37 + CONTENT/BT/AUDIO/ABFWRN01.MID | Bin 0 -> 100 bytes CONTENT/BT/AUDIO/ABNCMP.SCP | 103 + CONTENT/BT/AUDIO/ABNTRG.SCP | 96 + CONTENT/BT/AUDIO/ACNCMP.SCP | 34 + CONTENT/BT/AUDIO/ACNCMPE.SCP | 13 + CONTENT/BT/AUDIO/ACNTRG.SCP | 12 + CONTENT/BT/AUDIO/ACNTRGE.SCP | 8 + CONTENT/BT/AUDIO/ALMINT.SCP | 78 + CONTENT/BT/AUDIO/AUDIO.INI | 53 + CONTENT/BT/AUDIO/AUDIOMR.INI | 53 + CONTENT/BT/AUDIO/AVA1EXT.SCP | 43 + CONTENT/BT/AUDIO/AVA1INT.SCP | 97 + CONTENT/BT/AUDIO/AVA2.SCP | 55 + CONTENT/BT/AUDIO/AVAEXT.SCP | 61 + CONTENT/BT/AUDIO/AVAINT.SCP | 109 + CONTENT/BT/AUDIO/BATEXT.SCP | 25 + CONTENT/BT/AUDIO/BATINT.SCP | 85 + CONTENT/BT/AUDIO/BBNEXP.SCP | 118 + CONTENT/BT/AUDIO/BHK1EXT.SCP | 43 + CONTENT/BT/AUDIO/BHK1INT.SCP | 85 + CONTENT/BT/AUDIO/BIGEXP.SCP | 91 + CONTENT/BT/AUDIO/BIGEXP01.MID | Bin 0 -> 91 bytes CONTENT/BT/AUDIO/BLKEXT.SCP | 61 + CONTENT/BT/AUDIO/BLKINT.SCP | 109 + CONTENT/BT/AUDIO/BRNEXT.SCP | 105 + CONTENT/BT/AUDIO/BRNINT.SCP | 117 + CONTENT/BT/AUDIO/BUTCMP.SCP | 103 + CONTENT/BT/AUDIO/BUTTRG.SCP | 90 + CONTENT/BT/AUDIO/CALEXT.SCP | 49 + CONTENT/BT/AUDIO/CALINT.SCP | 91 + CONTENT/BT/AUDIO/CLKWRN01.MID | Bin 0 -> 100 bytes CONTENT/BT/AUDIO/CLTCMP.SCP | 74 + CONTENT/BT/AUDIO/CLTTRG.SCP | 63 + CONTENT/BT/AUDIO/CNDCMP.SCP | 49 + CONTENT/BT/AUDIO/CNDTRG.SCP | 46 + CONTENT/BT/AUDIO/COLEXT.SCP | 102 + CONTENT/BT/AUDIO/COLINT.SCP | 135 + CONTENT/BT/AUDIO/CRNEXP.SCP | 84 + CONTENT/BT/AUDIO/CTMIX.CFG | 15 + CONTENT/BT/AUDIO/DGAEXP.SCP | 47 + CONTENT/BT/AUDIO/DGBEXP.SCP | 47 + CONTENT/BT/AUDIO/DGCEXP.SCP | 48 + CONTENT/BT/AUDIO/DSTCMP.SCP | 38 + CONTENT/BT/AUDIO/DSTRD01.MID | Bin 0 -> 96 bytes CONTENT/BT/AUDIO/DSTRD02.MID | Bin 0 -> 79 bytes CONTENT/BT/AUDIO/DSTTRG.SCP | 22 + CONTENT/BT/AUDIO/EPCCMP.SCP | 57 + CONTENT/BT/AUDIO/EPPCMP.SCP | 48 + CONTENT/BT/AUDIO/EPPCMPE.SCP | 14 + CONTENT/BT/AUDIO/EPPTRG.SCP | 12 + CONTENT/BT/AUDIO/EPPTRGE.SCP | 9 + CONTENT/BT/AUDIO/ERLCMP.SCP | 48 + CONTENT/BT/AUDIO/ERLCMPE.SCP | 14 + CONTENT/BT/AUDIO/ERLTRG.SCP | 12 + CONTENT/BT/AUDIO/ERLTRGE.SCP | 8 + CONTENT/BT/AUDIO/ERMCMP.SCP | 49 + CONTENT/BT/AUDIO/ERMCMPE.SCP | 14 + CONTENT/BT/AUDIO/ERMTRG.SCP | 12 + CONTENT/BT/AUDIO/ERMTRGE.SCP | 8 + CONTENT/BT/AUDIO/ERSCMP.SCP | 48 + CONTENT/BT/AUDIO/ERSCMPE.SCP | 14 + CONTENT/BT/AUDIO/ERSTRG.SCP | 12 + CONTENT/BT/AUDIO/ERSTRGE.SCP | 8 + CONTENT/BT/AUDIO/FIND.TXT | 0 CONTENT/BT/AUDIO/FIREXT.SCP | 43 + CONTENT/BT/AUDIO/FIRINT.SCP | 79 + CONTENT/BT/AUDIO/FOTEXT.SCP | 126 + CONTENT/BT/AUDIO/FOTINT.SCP | 131 + CONTENT/BT/AUDIO/GENCMP.SCP | 61 + CONTENT/BT/AUDIO/GENTRG.SCP | 65 + CONTENT/BT/AUDIO/GENWRN01.MID | Bin 0 -> 86 bytes CONTENT/BT/AUDIO/GENWRN02.MID | Bin 0 -> 86 bytes CONTENT/BT/AUDIO/GLRCMPE.SCP | 14 + CONTENT/BT/AUDIO/GLRTRGE.SCP | 8 + CONTENT/BT/AUDIO/HETEXT.SCP | 39 + CONTENT/BT/AUDIO/HETINT.SCP | 85 + CONTENT/BT/AUDIO/ICOM.CFG | 15 + CONTENT/BT/AUDIO/INCARM01.MID | Bin 0 -> 107 bytes CONTENT/BT/AUDIO/JAKEXT.SCP | 49 + CONTENT/BT/AUDIO/JAKINT.SCP | 97 + CONTENT/BT/AUDIO/LACCMP.SCP | 38 + CONTENT/BT/AUDIO/LACTRG.SCP | 12 + CONTENT/BT/AUDIO/LEGWRN01.MID | Bin 0 -> 86 bytes CONTENT/BT/AUDIO/LLRCMP.SCP | 49 + CONTENT/BT/AUDIO/LLRCMPE.SCP | 14 + CONTENT/BT/AUDIO/LLRTRG.SCP | 12 + CONTENT/BT/AUDIO/LLRTRGE.SCP | 9 + CONTENT/BT/AUDIO/LO1EXT.SCP | 67 + CONTENT/BT/AUDIO/LO1INT.SCP | 121 + CONTENT/BT/AUDIO/LOK1EXT.SCP | 61 + CONTENT/BT/AUDIO/LOK1INT.SCP | 103 + CONTENT/BT/AUDIO/LOK2EXT.SCP | 67 + CONTENT/BT/AUDIO/LOK2INT.SCP | 115 + CONTENT/BT/AUDIO/LOKEXT.SCP | 55 + CONTENT/BT/AUDIO/LOKINT.SCP | 97 + CONTENT/BT/AUDIO/LRMCMP.SCP | 32 + CONTENT/BT/AUDIO/LRMTRG.SCP | 12 + CONTENT/BT/AUDIO/LSRCMPE.SCP | 26 + CONTENT/BT/AUDIO/LSREXP.SCP | 109 + CONTENT/BT/AUDIO/LSREXPI.SCP | 109 + CONTENT/BT/AUDIO/LSRLDD01.MID | Bin 0 -> 77 bytes CONTENT/BT/AUDIO/LSRTRG.SCP | 171 + CONTENT/BT/AUDIO/LSRTRGE.SCP | 40 + CONTENT/BT/AUDIO/MACCMP.SCP | 38 + CONTENT/BT/AUDIO/MACROS.SCP | 174 + CONTENT/BT/AUDIO/MACTRG.SCP | 12 + CONTENT/BT/AUDIO/MAD1EXT.SCP | 55 + CONTENT/BT/AUDIO/MAD1INT.SCP | 103 + CONTENT/BT/AUDIO/MAD2EXT.SCP | 43 + CONTENT/BT/AUDIO/MAD2INT.SCP | 109 + CONTENT/BT/AUDIO/MADEXT.SCP | 43 + CONTENT/BT/AUDIO/MADINT.SCP | 91 + CONTENT/BT/AUDIO/MBNEXP.SCP | 119 + CONTENT/BT/AUDIO/MCHEXP03.MID | Bin 0 -> 155 bytes CONTENT/BT/AUDIO/MCHEXP04.MID | Bin 0 -> 155 bytes CONTENT/BT/AUDIO/MCHEXP05.MID | Bin 0 -> 155 bytes CONTENT/BT/AUDIO/MCHEXP06.MID | Bin 0 -> 123 bytes CONTENT/BT/AUDIO/MCHEXP07.MID | Bin 0 -> 108 bytes CONTENT/BT/AUDIO/MCHEXPI1.MID | Bin 0 -> 78 bytes CONTENT/BT/AUDIO/MCHEXPI2.MID | Bin 0 -> 80 bytes CONTENT/BT/AUDIO/MCHEXPI3.MID | Bin 0 -> 73 bytes CONTENT/BT/AUDIO/MCHEXT.SCP | 29 + CONTENT/BT/AUDIO/MCHFRE01.MID | Bin 0 -> 80 bytes CONTENT/BT/AUDIO/MCHINT.SCP | 124 + CONTENT/BT/AUDIO/MCTINT.SCP | 15 + CONTENT/BT/AUDIO/MEDEXP.SCP | 92 + CONTENT/BT/AUDIO/MEDEXP01.MID | Bin 0 -> 78 bytes CONTENT/BT/AUDIO/MGNCMP.SCP | 109 + CONTENT/BT/AUDIO/MGNEXP.SCP | 108 + CONTENT/BT/AUDIO/MGNEXPC.SCP | 108 + CONTENT/BT/AUDIO/MGNTRG.SCP | 74 + CONTENT/BT/AUDIO/MLRCMP.SCP | 49 + CONTENT/BT/AUDIO/MLRCMPE.SCP | 14 + CONTENT/BT/AUDIO/MLRTRG.SCP | 12 + CONTENT/BT/AUDIO/MLRTRGE.SCP | 9 + CONTENT/BT/AUDIO/MSLCMP.SCP | 171 + CONTENT/BT/AUDIO/MSLEXP.SCP | 108 + CONTENT/BT/AUDIO/MSLEXPI.SCP | 109 + CONTENT/BT/AUDIO/MSLJAM01.MID | Bin 0 -> 77 bytes CONTENT/BT/AUDIO/MSLLDD01.MID | Bin 0 -> 77 bytes CONTENT/BT/AUDIO/MSLMFR01.MID | Bin 0 -> 78 bytes CONTENT/BT/AUDIO/MSLTRG.SCP | 111 + CONTENT/BT/AUDIO/MSLTVL.SCP | 46 + CONTENT/BT/AUDIO/MYRCMP.SCP | 27 + CONTENT/BT/AUDIO/MYRTRG.SCP | 31 + CONTENT/BT/AUDIO/OWN1EXT.SCP | 37 + CONTENT/BT/AUDIO/OWN1INT.SCP | 85 + CONTENT/BT/AUDIO/OWNEXT.SCP | 49 + CONTENT/BT/AUDIO/OWNINT.SCP | 91 + CONTENT/BT/AUDIO/PLYINT.SCP | 88 + CONTENT/BT/AUDIO/PPCCMP.SCP | 48 + CONTENT/BT/AUDIO/PPCCMPE.SCP | 14 + CONTENT/BT/AUDIO/PPCEXP.SCP | 108 + CONTENT/BT/AUDIO/PPCEXPI.SCP | 109 + CONTENT/BT/AUDIO/PPCTRG.SCP | 12 + CONTENT/BT/AUDIO/PPCTRGE.SCP | 9 + CONTENT/BT/AUDIO/PRGBUT01.MID | Bin 0 -> 77 bytes CONTENT/BT/AUDIO/PRJCMP.SCP | 192 + CONTENT/BT/AUDIO/PRJCMPE.SCP | 26 + CONTENT/BT/AUDIO/PRJEXP.SCP | 108 + CONTENT/BT/AUDIO/PRJEXPI.SCP | 109 + CONTENT/BT/AUDIO/PRJJAM01.MID | Bin 0 -> 77 bytes CONTENT/BT/AUDIO/PRJLDD01.MID | Bin 0 -> 77 bytes CONTENT/BT/AUDIO/PRJMFR01.MID | Bin 0 -> 78 bytes CONTENT/BT/AUDIO/PRJTRG.SCP | 128 + CONTENT/BT/AUDIO/PRJTRGE.SCP | 23 + CONTENT/BT/AUDIO/PRJTVL.SCP | 46 + CONTENT/BT/AUDIO/RAPEXT.SCP | 37 + CONTENT/BT/AUDIO/RAPINT.SCP | 91 + CONTENT/BT/AUDIO/SACCMP.SCP | 38 + CONTENT/BT/AUDIO/SACTRG.SCP | 12 + CONTENT/BT/AUDIO/SBNEXP.SCP | 136 + CONTENT/BT/AUDIO/SHFEXT.SCP | 140 + CONTENT/BT/AUDIO/SLRCMP.SCP | 49 + CONTENT/BT/AUDIO/SLRCMPE.SCP | 14 + CONTENT/BT/AUDIO/SLRTRG.SCP | 12 + CONTENT/BT/AUDIO/SLRTRGE.SCP | 9 + CONTENT/BT/AUDIO/SMLEXP.SCP | 108 + CONTENT/BT/AUDIO/SND1EXT.SCP | 49 + CONTENT/BT/AUDIO/SND1INT.SCP | 85 + CONTENT/BT/AUDIO/SND2EXT.SCP | 73 + CONTENT/BT/AUDIO/SND2INT.SCP | 115 + CONTENT/BT/AUDIO/SNDEXT.SCP | 67 + CONTENT/BT/AUDIO/SNDINT.SCP | 121 + CONTENT/BT/AUDIO/SNRTRG.SCP | 12 + CONTENT/BT/AUDIO/SRMCMP.SCP | 33 + CONTENT/BT/AUDIO/SRMTRG.SCP | 12 + CONTENT/BT/AUDIO/STATIC.SCP | 14 + CONTENT/BT/AUDIO/STIEXT.SCP | 37 + CONTENT/BT/AUDIO/STIINT.SCP | 79 + CONTENT/BT/AUDIO/SYMBOLS.SCP | 127 + CONTENT/BT/AUDIO/THR1EXT.SCP | 67 + CONTENT/BT/AUDIO/THR1INT.SCP | 109 + CONTENT/BT/AUDIO/THR6EXT.SCP | 73 + CONTENT/BT/AUDIO/THR6INT.SCP | 139 + CONTENT/BT/AUDIO/THREXT.SCP | 49 + CONTENT/BT/AUDIO/THRINT.SCP | 91 + CONTENT/BT/AUDIO/TRSEXT.SCP | 52 + CONTENT/BT/AUDIO/TRSINT.SCP | 85 + CONTENT/BT/AUDIO/VUL1EXT.SCP | 49 + CONTENT/BT/AUDIO/VUL1INT.SCP | 91 + CONTENT/BT/AUDIO/VUL2EXT.SCP | 37 + CONTENT/BT/AUDIO/VUL2INT.SCP | 121 + CONTENT/BT/AUDIO/VULEXT.SCP | 49 + CONTENT/BT/AUDIO/VULINT.SCP | 97 + CONTENT/BT/AUDIO/WNDEXT01.SCP | 80 + CONTENT/BT/AUDIO/WPNINT.SCP | 113 + CONTENT/BT/AUTOEXEC.BAT | 22 + CONTENT/BT/BLDTEST.SCN | 88 + CONTENT/BT/BT.BAT | 24 + CONTENT/BT/BTCAM.BAT | 43 + CONTENT/BT/BTCAM/BTCAM01.BAT | 43 + CONTENT/BT/BTCAM/BTCAM02.BAT | 43 + CONTENT/BT/BTCAM/BTCAM03.BAT | 43 + CONTENT/BT/BTCAM/BTCAM04.BAT | 43 + CONTENT/BT/BTCAM/BTCAM05.BAT | 43 + CONTENT/BT/BTCAM/BTCAM06.BAT | 43 + CONTENT/BT/BTCAM/BTCAM07.BAT | 43 + CONTENT/BT/BTCAM/BTCAM08.BAT | 43 + CONTENT/BT/BTCAM/BTCAM09.BAT | 43 + CONTENT/BT/BTCAM/BTCAM10.BAT | 43 + CONTENT/BT/BTCAM/BTCAM11.BAT | 43 + CONTENT/BT/BTCAM/BTCAM12.BAT | 43 + CONTENT/BT/BTCAM/BTCAM13.BAT | 43 + CONTENT/BT/BTCAM/BTCAM14.BAT | 43 + CONTENT/BT/BTCAM/BTCAM15.BAT | 43 + CONTENT/BT/BTCAM/BTCAM16.BAT | 43 + CONTENT/BT/BTCAM/BTCAM17.BAT | 43 + CONTENT/BT/BTCAM/BTCAM18.BAT | 43 + CONTENT/BT/BTCAM/BTCAM19.BAT | 43 + CONTENT/BT/BTCAM/BTCAM20.BAT | 43 + CONTENT/BT/BTCAM/BTCAM21.BAT | 43 + CONTENT/BT/BTCAM/BTCAM22.BAT | 43 + CONTENT/BT/BTCAM/BTCAM23.BAT | 43 + CONTENT/BT/BTCAM/BTCAM24.BAT | 43 + CONTENT/BT/BTCAM/BTCAM25.BAT | 43 + CONTENT/BT/BTCAM/BTCAM26.BAT | 43 + CONTENT/BT/BTCAM/BTCAM27.BAT | 43 + CONTENT/BT/BTCAM/BTCAM28.BAT | 43 + CONTENT/BT/BTCAM/BTCAM29.BAT | 43 + CONTENT/BT/BTCAM/BTCAM30.BAT | 43 + CONTENT/BT/BTCAM/BTCAM31.BAT | 43 + CONTENT/BT/BTCAM/BTCAM32.BAT | 43 + CONTENT/BT/BTGO.BAT | 9 + CONTENT/BT/BTL4.BLD | 230 + CONTENT/BT/BTL4.OPS | 154 + CONTENT/BT/BTL4.ORG | 230 + CONTENT/BT/BTL4BU.BLD | 203 + CONTENT/BT/BTLOOK.BAT | 12 + CONTENT/BT/BTNET.BAT | 22 + CONTENT/BT/BTPREP.BAT | 44 + CONTENT/BT/BUILD.BAT | 6 + CONTENT/BT/BUILD1.BAT | 82 + CONTENT/BT/BUILDRES.BAT | 82 + CONTENT/BT/DEARCBT.BAT | 19 + CONTENT/BT/EXCLUDE.LST | 7 + CONTENT/BT/FAILURE.LOG | 12 + CONTENT/BT/FILELIST | 68 + CONTENT/BT/GAUGE/AB01_GA.GIM | 15 + CONTENT/BT/GAUGE/AB02_GA.GIM | 15 + CONTENT/BT/GAUGE/AB03_GA.GIM | 15 + CONTENT/BT/GAUGE/AB04_GA.GIM | 15 + CONTENT/BT/GAUGE/AB05_GA.GIM | 15 + CONTENT/BT/GAUGE/AB06_GA.GIM | 29 + CONTENT/BT/GAUGE/AB07_GA.GIM | 20 + CONTENT/BT/GAUGE/AB08_GA.GIM | 16 + CONTENT/BT/GAUGE/AB09_GA.GIM | 25 + CONTENT/BT/GAUGE/AB10_GA.GIM | 29 + CONTENT/BT/GAUGE/AD01_GA.GIM | 40 + CONTENT/BT/GAUGE/ADPAL.PCC | Bin 0 -> 907 bytes CONTENT/BT/GAUGE/ADPAL2.PCC | Bin 0 -> 907 bytes CONTENT/BT/GAUGE/APC.GIM | 15 + CONTENT/BT/GAUGE/AR01_GA.GIM | 15 + CONTENT/BT/GAUGE/AR02_GA.GIM | 24 + CONTENT/BT/GAUGE/AR03_GA.GIM | 15 + CONTENT/BT/GAUGE/AR04_GA.GIM | 15 + CONTENT/BT/GAUGE/AR05_GA.GIM | 15 + CONTENT/BT/GAUGE/ARENA_GA.GIM | 70 + CONTENT/BT/GAUGE/ARMRMOVR.GIM | 15 + CONTENT/BT/GAUGE/AVA2DAMA.PCC | Bin 0 -> 8562 bytes CONTENT/BT/GAUGE/AVA_MR.PCC | Bin 0 -> 7591 bytes CONTENT/BT/GAUGE/AW01_GA.GIM | 15 + CONTENT/BT/GAUGE/AW02_GA.GIM | 15 + CONTENT/BT/GAUGE/AW03_GA.GIM | 15 + CONTENT/BT/GAUGE/AW04_GA.GIM | 15 + CONTENT/BT/GAUGE/AW05_GA.GIM | 19 + CONTENT/BT/GAUGE/BDUCK.PCC | Bin 0 -> 2466 bytes CONTENT/BT/GAUGE/BLAMP.PCC | Bin 0 -> 3557 bytes CONTENT/BT/GAUGE/BLD03_GA.GIM | 26 + CONTENT/BT/GAUGE/BLD04_GA.GIM | 24 + CONTENT/BT/GAUGE/BLD06_GA.GIM | 50 + CONTENT/BT/GAUGE/BLD08_GA.GIM | 146 + CONTENT/BT/GAUGE/BLD08_GA.ORG | 146 + CONTENT/BT/GAUGE/BLD20_GA.GIM | 33 + CONTENT/BT/GAUGE/BLD24_GA.GIM | 20 + CONTENT/BT/GAUGE/BLD26_GA.GIM | 15 + CONTENT/BT/GAUGE/BLD27_GA.GIM | 45 + CONTENT/BT/GAUGE/BLHHT.PCC | Bin 0 -> 6421 bytes CONTENT/BT/GAUGE/BLH_GA.GIM | 21 + CONTENT/BT/GAUGE/BNK_GA.GIM | 24 + CONTENT/BT/GAUGE/BTEBUS.PCC | Bin 0 -> 2028 bytes CONTENT/BT/GAUGE/BTECMODE.PCC | Bin 0 -> 1630 bytes CONTENT/BT/GAUGE/BTEEJTM.PCC | Bin 0 -> 2915 bytes CONTENT/BT/GAUGE/BTEFIRE.PCC | Bin 0 -> 1773 bytes CONTENT/BT/GAUGE/BTEHFAIL.PCC | Bin 0 -> 1952 bytes CONTENT/BT/GAUGE/BTEJAM.PCC | Bin 0 -> 1820 bytes CONTENT/BT/GAUGE/BTELOOP.PCC | Bin 0 -> 2210 bytes CONTENT/BT/GAUGE/BTEMODE.PCC | Bin 0 -> 2989 bytes CONTENT/BT/GAUGE/BTEPFAIL.PCC | Bin 0 -> 2192 bytes CONTENT/BT/GAUGE/BTESFAIL.PCC | Bin 0 -> 2185 bytes CONTENT/BT/GAUGE/BTESLEV.PCC | Bin 0 -> 1312 bytes CONTENT/BT/GAUGE/BTESRNGE.PCC | Bin 0 -> 1711 bytes CONTENT/BT/GAUGE/BTEUNJM.PCC | Bin 0 -> 1485 bytes CONTENT/BT/GAUGE/BTJOY.PCC | Bin 0 -> 2740 bytes CONTENT/BT/GAUGE/BTOPAL.PCC | Bin 0 -> 913 bytes CONTENT/BT/GAUGE/BTPBUS.PCC | Bin 0 -> 1499 bytes CONTENT/BT/GAUGE/BTPLOOP.PCC | Bin 0 -> 1579 bytes CONTENT/BT/GAUGE/BTSPAL.PCC | Bin 0 -> 916 bytes CONTENT/BT/GAUGE/BTWARN.PCC | Bin 0 -> 1441 bytes CONTENT/BT/GAUGE/BULLDOG.GIM | 15 + CONTENT/BT/GAUGE/BUTTEA_G.GIM | 27 + CONTENT/BT/GAUGE/BUTTEB_G.GIM | 27 + CONTENT/BT/GAUGE/BUTTEC_G.GIM | 27 + CONTENT/BT/GAUGE/BUTTED_G.GIM | 27 + CONTENT/BT/GAUGE/BUTTEE_G.GIM | 27 + CONTENT/BT/GAUGE/CALPB_GA.GIM | 15 + CONTENT/BT/GAUGE/CALP_GA.GIM | 15 + CONTENT/BT/GAUGE/CM_BOTH.PCC | Bin 0 -> 1058 bytes CONTENT/BT/GAUGE/CM_OFF.PCC | Bin 0 -> 1005 bytes CONTENT/BT/GAUGE/CM_ONLY.PCC | Bin 0 -> 995 bytes CONTENT/BT/GAUGE/CM_OTHER.PCC | Bin 0 -> 1141 bytes CONTENT/BT/GAUGE/COMTRUCK.GIM | 15 + CONTENT/BT/GAUGE/COOLANT.GIM | 15 + CONTENT/BT/GAUGE/DISH_GA.GIM | 15 + CONTENT/BT/GAUGE/DOZER.GIM | 15 + CONTENT/BT/GAUGE/EAFC10.PCC | Bin 0 -> 2193 bytes CONTENT/BT/GAUGE/EAFC100.PCC | Bin 0 -> 2372 bytes CONTENT/BT/GAUGE/EAFC25.PCC | Bin 0 -> 2243 bytes CONTENT/BT/GAUGE/EAFC5.PCC | Bin 0 -> 2212 bytes CONTENT/BT/GAUGE/EAFC50.PCC | Bin 0 -> 2240 bytes CONTENT/BT/GAUGE/EDESTRYD.PCC | Bin 0 -> 1795 bytes CONTENT/BT/GAUGE/EDMG.PCC | Bin 0 -> 2840 bytes CONTENT/BT/GAUGE/EERLLAS.PCC | Bin 0 -> 2558 bytes CONTENT/BT/GAUGE/EERPPC.PCC | Bin 0 -> 2234 bytes CONTENT/BT/GAUGE/EERSLAS.PCC | Bin 0 -> 2461 bytes CONTENT/BT/GAUGE/ELBX10.PCC | Bin 0 -> 2193 bytes CONTENT/BT/GAUGE/ELBX100.PCC | Bin 0 -> 2372 bytes CONTENT/BT/GAUGE/ELBX25.PCC | Bin 0 -> 2243 bytes CONTENT/BT/GAUGE/ELBX5.PCC | Bin 0 -> 2212 bytes CONTENT/BT/GAUGE/ELEAK.PCC | Bin 0 -> 1191 bytes CONTENT/BT/GAUGE/ELLAS.PCC | Bin 0 -> 2420 bytes CONTENT/BT/GAUGE/ELRM10.PCC | Bin 0 -> 2475 bytes CONTENT/BT/GAUGE/ELRM15.PCC | Bin 0 -> 2442 bytes CONTENT/BT/GAUGE/ELRM20.PCC | Bin 0 -> 2487 bytes CONTENT/BT/GAUGE/ELRM5.PCC | Bin 0 -> 2370 bytes CONTENT/BT/GAUGE/EMG.PCC | Bin 0 -> 2125 bytes CONTENT/BT/GAUGE/ENRK10.PCC | Bin 0 -> 2563 bytes CONTENT/BT/GAUGE/ENRK15.PCC | Bin 0 -> 2530 bytes CONTENT/BT/GAUGE/ENRK20.PCC | Bin 0 -> 2575 bytes CONTENT/BT/GAUGE/ENRK5.PCC | Bin 0 -> 2458 bytes CONTENT/BT/GAUGE/EPPC.PCC | Bin 0 -> 2093 bytes CONTENT/BT/GAUGE/ESCND.PCC | Bin 0 -> 1102 bytes CONTENT/BT/GAUGE/ESENSORS.PCC | Bin 0 -> 2378 bytes CONTENT/BT/GAUGE/ESPEED.PCC | Bin 0 -> 2596 bytes CONTENT/BT/GAUGE/ESRM2.PCC | Bin 0 -> 2348 bytes CONTENT/BT/GAUGE/ESRM4.PCC | Bin 0 -> 2359 bytes CONTENT/BT/GAUGE/ESRM6.PCC | Bin 0 -> 2371 bytes CONTENT/BT/GAUGE/ESTRK2.PCC | Bin 0 -> 2476 bytes CONTENT/BT/GAUGE/ESTRK4.PCC | Bin 0 -> 2480 bytes CONTENT/BT/GAUGE/ESTRK6.PCC | Bin 0 -> 2494 bytes CONTENT/BT/GAUGE/EVOLT.PCC | Bin 0 -> 1269 bytes CONTENT/BT/GAUGE/FP1_GA.GIM | 78 + CONTENT/BT/GAUGE/FP2_GA.GIM | 25 + CONTENT/BT/GAUGE/FT1_GA.GIM | 29 + CONTENT/BT/GAUGE/FT2_GA.GIM | 24 + CONTENT/BT/GAUGE/GAUGE.GAT | 75 + CONTENT/BT/GAUGE/GNR_GA.GIM | 15 + CONTENT/BT/GAUGE/HARASSER.GIM | 15 + CONTENT/BT/GAUGE/HEATPAL.PCC | Bin 0 -> 905 bytes CONTENT/BT/GAUGE/HEATPAL2.PCC | Bin 0 -> 915 bytes CONTENT/BT/GAUGE/HELV15.PCC | Bin 0 -> 1546 bytes CONTENT/BT/GAUGE/HELV18.PCC | Bin 0 -> 1660 bytes CONTENT/BT/GAUGE/HELV42.PCC | Bin 0 -> 2769 bytes CONTENT/BT/GAUGE/HILLG1_G.GIM | 50 + CONTENT/BT/GAUGE/HILLG2_G.GIM | 36 + CONTENT/BT/GAUGE/HILLG3_G.GIM | 36 + CONTENT/BT/GAUGE/HL1_GA.GIM | 31 + CONTENT/BT/GAUGE/HL2_GA.GIM | 26 + CONTENT/BT/GAUGE/HN1_GA.GIM | 26 + CONTENT/BT/GAUGE/HUMMER.GIM | 15 + CONTENT/BT/GAUGE/HUT_GA.GIM | 24 + CONTENT/BT/GAUGE/HWZ_GA.GIM | 25 + CONTENT/BT/GAUGE/JAKCRIT.PCC | Bin 0 -> 11095 bytes CONTENT/BT/GAUGE/JAKHEAT.PCC | Bin 0 -> 10862 bytes CONTENT/BT/GAUGE/JAK_GA.GIM | 21 + CONTENT/BT/GAUGE/L4GAUGE.INI | 36 + CONTENT/BT/GAUGE/LOKIHT.PCC | Bin 0 -> 6340 bytes CONTENT/BT/GAUGE/LOKI_MR.PCC | Bin 0 -> 7777 bytes CONTENT/BT/GAUGE/LRMCARRY.GIM | 15 + CONTENT/BT/GAUGE/MAD2HT.PCC | Bin 0 -> 5086 bytes CONTENT/BT/GAUGE/MADHT.PCC | Bin 0 -> 4999 bytes CONTENT/BT/GAUGE/MECHMOVR.GIM | 15 + CONTENT/BT/GAUGE/MRPAL.PCC | Bin 0 -> 907 bytes CONTENT/BT/GAUGE/MSLG_GA.GIM | 35 + CONTENT/BT/GAUGE/MSLR_GA.GIM | 63 + CONTENT/BT/GAUGE/PDSH_GA.GIM | 23 + CONTENT/BT/GAUGE/PGN_GA.GIM | 30 + CONTENT/BT/GAUGE/QAFC10.PCC | Bin 0 -> 2193 bytes CONTENT/BT/GAUGE/QAFC100.PCC | Bin 0 -> 2372 bytes CONTENT/BT/GAUGE/QAFC25.PCC | Bin 0 -> 2243 bytes CONTENT/BT/GAUGE/QAFC5.PCC | Bin 0 -> 2212 bytes CONTENT/BT/GAUGE/QAFC50.PCC | Bin 0 -> 2240 bytes CONTENT/BT/GAUGE/QAVA0.PCC | Bin 0 -> 2990 bytes CONTENT/BT/GAUGE/QAVA1.PCC | Bin 0 -> 3621 bytes CONTENT/BT/GAUGE/QAVA2.PCC | Bin 0 -> 3562 bytes CONTENT/BT/GAUGE/QAVA23.PCC | Bin 0 -> 3627 bytes CONTENT/BT/GAUGE/QAVA24.PCC | Bin 0 -> 3622 bytes CONTENT/BT/GAUGE/QAVA25.PCC | Bin 0 -> 4061 bytes CONTENT/BT/GAUGE/QAVA26.PCC | Bin 0 -> 3600 bytes CONTENT/BT/GAUGE/QAVA27.PCC | Bin 0 -> 3871 bytes CONTENT/BT/GAUGE/QBLH0.PCC | Bin 0 -> 2952 bytes CONTENT/BT/GAUGE/QBLH1.PCC | Bin 0 -> 2928 bytes CONTENT/BT/GAUGE/QBLH2.PCC | Bin 0 -> 2929 bytes CONTENT/BT/GAUGE/QBLH3.PCC | Bin 0 -> 2921 bytes CONTENT/BT/GAUGE/QBLH4.PCC | Bin 0 -> 2812 bytes CONTENT/BT/GAUGE/QBLH5.PCC | Bin 0 -> 2871 bytes CONTENT/BT/GAUGE/QBLH6.PCC | Bin 0 -> 2810 bytes CONTENT/BT/GAUGE/QBLH7.PCC | Bin 0 -> 2956 bytes CONTENT/BT/GAUGE/QCIRCLE.PCC | Bin 0 -> 1268 bytes CONTENT/BT/GAUGE/QCIRCR.PCC | Bin 0 -> 1556 bytes CONTENT/BT/GAUGE/QERLLAS.PCC | Bin 0 -> 2558 bytes CONTENT/BT/GAUGE/QERMLAS.PCC | Bin 0 -> 2811 bytes CONTENT/BT/GAUGE/QERPPC.PCC | Bin 0 -> 2234 bytes CONTENT/BT/GAUGE/QERSLAS.PCC | Bin 0 -> 2461 bytes CONTENT/BT/GAUGE/QFIR0.PCC | Bin 0 -> 2473 bytes CONTENT/BT/GAUGE/QFIR1.PCC | Bin 0 -> 2886 bytes CONTENT/BT/GAUGE/QFIR2.PCC | Bin 0 -> 2760 bytes CONTENT/BT/GAUGE/QFIR3.PCC | Bin 0 -> 2880 bytes CONTENT/BT/GAUGE/QFIR4.PCC | Bin 0 -> 2819 bytes CONTENT/BT/GAUGE/QFIR5.PCC | Bin 0 -> 2832 bytes CONTENT/BT/GAUGE/QFIR6.PCC | Bin 0 -> 2763 bytes CONTENT/BT/GAUGE/QFIR7.PCC | Bin 0 -> 3395 bytes CONTENT/BT/GAUGE/QFIRI.PCC | Bin 0 -> 2902 bytes CONTENT/BT/GAUGE/QGAUSS.PCC | Bin 0 -> 2707 bytes CONTENT/BT/GAUGE/QJAK0.PCC | Bin 0 -> 2599 bytes CONTENT/BT/GAUGE/QJAK1.PCC | Bin 0 -> 2984 bytes CONTENT/BT/GAUGE/QJAK2.PCC | Bin 0 -> 2725 bytes CONTENT/BT/GAUGE/QJAK3.PCC | Bin 0 -> 2986 bytes CONTENT/BT/GAUGE/QJAK4.PCC | Bin 0 -> 2944 bytes CONTENT/BT/GAUGE/QJAK5.PCC | Bin 0 -> 2816 bytes CONTENT/BT/GAUGE/QJAK6.PCC | Bin 0 -> 2944 bytes CONTENT/BT/GAUGE/QJAK7.PCC | Bin 0 -> 3361 bytes CONTENT/BT/GAUGE/QLBX10.PCC | Bin 0 -> 2193 bytes CONTENT/BT/GAUGE/QLBX100.PCC | Bin 0 -> 2372 bytes CONTENT/BT/GAUGE/QLBX25.PCC | Bin 0 -> 2243 bytes CONTENT/BT/GAUGE/QLBX5.PCC | Bin 0 -> 2212 bytes CONTENT/BT/GAUGE/QLBX50.PCC | Bin 0 -> 2240 bytes CONTENT/BT/GAUGE/QLLAS.PCC | Bin 0 -> 2420 bytes CONTENT/BT/GAUGE/QLOK10.PCC | Bin 0 -> 3820 bytes CONTENT/BT/GAUGE/QLOK11.PCC | Bin 0 -> 3748 bytes CONTENT/BT/GAUGE/QLOK12.PCC | Bin 0 -> 3808 bytes CONTENT/BT/GAUGE/QLOK13.PCC | Bin 0 -> 3755 bytes CONTENT/BT/GAUGE/QLOK14.PCC | Bin 0 -> 3847 bytes CONTENT/BT/GAUGE/QLOK15.PCC | Bin 0 -> 3748 bytes CONTENT/BT/GAUGE/QLOK16.PCC | Bin 0 -> 3838 bytes CONTENT/BT/GAUGE/QLOK17.PCC | Bin 0 -> 3750 bytes CONTENT/BT/GAUGE/QLOKI0.PCC | Bin 0 -> 3840 bytes CONTENT/BT/GAUGE/QLOKI1.PCC | Bin 0 -> 3771 bytes CONTENT/BT/GAUGE/QLOKI2.PCC | Bin 0 -> 3844 bytes CONTENT/BT/GAUGE/QLOKI3.PCC | Bin 0 -> 3776 bytes CONTENT/BT/GAUGE/QLOKI4.PCC | Bin 0 -> 3757 bytes CONTENT/BT/GAUGE/QLOKI5.PCC | Bin 0 -> 3764 bytes CONTENT/BT/GAUGE/QLOKI6.PCC | Bin 0 -> 3836 bytes CONTENT/BT/GAUGE/QLOKI7.PCC | Bin 0 -> 3770 bytes CONTENT/BT/GAUGE/QLRM10.PCC | Bin 0 -> 2475 bytes CONTENT/BT/GAUGE/QLRM15.PCC | Bin 0 -> 2442 bytes CONTENT/BT/GAUGE/QLRM20.PCC | Bin 0 -> 2487 bytes CONTENT/BT/GAUGE/QLRM5.PCC | Bin 0 -> 2370 bytes CONTENT/BT/GAUGE/QMAD0.PCC | Bin 0 -> 3935 bytes CONTENT/BT/GAUGE/QMAD1.PCC | Bin 0 -> 3974 bytes CONTENT/BT/GAUGE/QMAD10.PCC | Bin 0 -> 3951 bytes CONTENT/BT/GAUGE/QMAD11.PCC | Bin 0 -> 3990 bytes CONTENT/BT/GAUGE/QMAD12.PCC | Bin 0 -> 3771 bytes CONTENT/BT/GAUGE/QMAD13.PCC | Bin 0 -> 3970 bytes CONTENT/BT/GAUGE/QMAD14.PCC | Bin 0 -> 4051 bytes CONTENT/BT/GAUGE/QMAD15.PCC | Bin 0 -> 3984 bytes CONTENT/BT/GAUGE/QMAD16.PCC | Bin 0 -> 4050 bytes CONTENT/BT/GAUGE/QMAD17.PCC | Bin 0 -> 4139 bytes CONTENT/BT/GAUGE/QMAD2.PCC | Bin 0 -> 3755 bytes CONTENT/BT/GAUGE/QMAD20.PCC | Bin 0 -> 3941 bytes CONTENT/BT/GAUGE/QMAD21.PCC | Bin 0 -> 3980 bytes CONTENT/BT/GAUGE/QMAD22.PCC | Bin 0 -> 3761 bytes CONTENT/BT/GAUGE/QMAD23.PCC | Bin 0 -> 3960 bytes CONTENT/BT/GAUGE/QMAD24.PCC | Bin 0 -> 4057 bytes CONTENT/BT/GAUGE/QMAD25.PCC | Bin 0 -> 3974 bytes CONTENT/BT/GAUGE/QMAD26.PCC | Bin 0 -> 4009 bytes CONTENT/BT/GAUGE/QMAD27.PCC | Bin 0 -> 4129 bytes CONTENT/BT/GAUGE/QMAD3.PCC | Bin 0 -> 3954 bytes CONTENT/BT/GAUGE/QMAD4.PCC | Bin 0 -> 4012 bytes CONTENT/BT/GAUGE/QMAD5.PCC | Bin 0 -> 3968 bytes CONTENT/BT/GAUGE/QMAD6.PCC | Bin 0 -> 4051 bytes CONTENT/BT/GAUGE/QMAD7.PCC | Bin 0 -> 4123 bytes CONTENT/BT/GAUGE/QMG.PCC | Bin 0 -> 2125 bytes CONTENT/BT/GAUGE/QMLAS.PCC | Bin 0 -> 2608 bytes CONTENT/BT/GAUGE/QMYOMERS.PCC | Bin 0 -> 2767 bytes CONTENT/BT/GAUGE/QNRK15.PCC | Bin 0 -> 2530 bytes CONTENT/BT/GAUGE/QNRK5.PCC | Bin 0 -> 2458 bytes CONTENT/BT/GAUGE/QOWEN0.PCC | Bin 0 -> 2671 bytes CONTENT/BT/GAUGE/QOWEN1.PCC | Bin 0 -> 2687 bytes CONTENT/BT/GAUGE/QOWEN2.PCC | Bin 0 -> 2688 bytes CONTENT/BT/GAUGE/QOWEN3.PCC | Bin 0 -> 2684 bytes CONTENT/BT/GAUGE/QOWEN4.PCC | Bin 0 -> 2617 bytes CONTENT/BT/GAUGE/QOWEN5.PCC | Bin 0 -> 2651 bytes CONTENT/BT/GAUGE/QOWEN6.PCC | Bin 0 -> 2618 bytes CONTENT/BT/GAUGE/QOWEN7.PCC | Bin 0 -> 2743 bytes CONTENT/BT/GAUGE/QPPC.PCC | Bin 0 -> 2093 bytes CONTENT/BT/GAUGE/QRAP0.PCC | Bin 0 -> 2980 bytes CONTENT/BT/GAUGE/QRAP1.PCC | Bin 0 -> 3543 bytes CONTENT/BT/GAUGE/QRAP2.PCC | Bin 0 -> 3244 bytes CONTENT/BT/GAUGE/QRAP3.PCC | Bin 0 -> 3537 bytes CONTENT/BT/GAUGE/QRAP4.PCC | Bin 0 -> 3531 bytes CONTENT/BT/GAUGE/QRAP5.PCC | Bin 0 -> 3466 bytes CONTENT/BT/GAUGE/QRAP6.PCC | Bin 0 -> 3529 bytes CONTENT/BT/GAUGE/QRAP7.PCC | Bin 0 -> 3987 bytes CONTENT/BT/GAUGE/QRAPI.PCC | Bin 0 -> 3656 bytes CONTENT/BT/GAUGE/QSENSORS.PCC | Bin 0 -> 2378 bytes CONTENT/BT/GAUGE/QSLAS.PCC | Bin 0 -> 2641 bytes CONTENT/BT/GAUGE/QSLASER.PCC | Bin 0 -> 2510 bytes CONTENT/BT/GAUGE/QSRM2.PCC | Bin 0 -> 2348 bytes CONTENT/BT/GAUGE/QSRM4.PCC | Bin 0 -> 2359 bytes CONTENT/BT/GAUGE/QSRM6.PCC | Bin 0 -> 2371 bytes CONTENT/BT/GAUGE/QSTI0.PCC | Bin 0 -> 3169 bytes CONTENT/BT/GAUGE/QSTI1.PCC | Bin 0 -> 3574 bytes CONTENT/BT/GAUGE/QSTI2.PCC | Bin 0 -> 3320 bytes CONTENT/BT/GAUGE/QSTI3.PCC | Bin 0 -> 3566 bytes CONTENT/BT/GAUGE/QSTI4.PCC | Bin 0 -> 3482 bytes CONTENT/BT/GAUGE/QSTI5.PCC | Bin 0 -> 3417 bytes CONTENT/BT/GAUGE/QSTI6.PCC | Bin 0 -> 3481 bytes CONTENT/BT/GAUGE/QSTI7.PCC | Bin 0 -> 3991 bytes CONTENT/BT/GAUGE/QSTII.PCC | Bin 0 -> 3583 bytes CONTENT/BT/GAUGE/QSTRK2.PCC | Bin 0 -> 2476 bytes CONTENT/BT/GAUGE/QSTRK4.PCC | Bin 0 -> 2480 bytes CONTENT/BT/GAUGE/QSTRK6.PCC | Bin 0 -> 2494 bytes CONTENT/BT/GAUGE/QSUN0.PCC | Bin 0 -> 3247 bytes CONTENT/BT/GAUGE/QSUN1.PCC | Bin 0 -> 3851 bytes CONTENT/BT/GAUGE/QSUN2.PCC | Bin 0 -> 3824 bytes CONTENT/BT/GAUGE/QSUN3.PCC | Bin 0 -> 3887 bytes CONTENT/BT/GAUGE/QSUN4.PCC | Bin 0 -> 3823 bytes CONTENT/BT/GAUGE/QSUN5.PCC | Bin 0 -> 4321 bytes CONTENT/BT/GAUGE/QSUN6.PCC | Bin 0 -> 3821 bytes CONTENT/BT/GAUGE/QSUN7.PCC | Bin 0 -> 4090 bytes CONTENT/BT/GAUGE/QTHOR.PCC | Bin 0 -> 3730 bytes CONTENT/BT/GAUGE/QTHOR0.PCC | Bin 0 -> 3436 bytes CONTENT/BT/GAUGE/QTHOR1.PCC | Bin 0 -> 3733 bytes CONTENT/BT/GAUGE/QTHOR2.PCC | Bin 0 -> 3685 bytes CONTENT/BT/GAUGE/QTHOR3.PCC | Bin 0 -> 3692 bytes CONTENT/BT/GAUGE/QTHOR4.PCC | Bin 0 -> 3592 bytes CONTENT/BT/GAUGE/QTHOR5.PCC | Bin 0 -> 3537 bytes CONTENT/BT/GAUGE/QTHOR6.PCC | Bin 0 -> 3614 bytes CONTENT/BT/GAUGE/QTHOR7.PCC | Bin 0 -> 3625 bytes CONTENT/BT/GAUGE/QVUL10.PCC | Bin 0 -> 3335 bytes CONTENT/BT/GAUGE/QVUL11.PCC | Bin 0 -> 3452 bytes CONTENT/BT/GAUGE/QVUL12.PCC | Bin 0 -> 3399 bytes CONTENT/BT/GAUGE/QVUL13.PCC | Bin 0 -> 3450 bytes CONTENT/BT/GAUGE/QVUL14.PCC | Bin 0 -> 3425 bytes CONTENT/BT/GAUGE/QVUL15.PCC | Bin 0 -> 3363 bytes CONTENT/BT/GAUGE/QVUL16.PCC | Bin 0 -> 3426 bytes CONTENT/BT/GAUGE/QVUL17.PCC | Bin 0 -> 3493 bytes CONTENT/BT/GAUGE/QVUL20.PCC | Bin 0 -> 3323 bytes CONTENT/BT/GAUGE/QVUL21.PCC | Bin 0 -> 3443 bytes CONTENT/BT/GAUGE/QVUL22.PCC | Bin 0 -> 3387 bytes CONTENT/BT/GAUGE/QVUL23.PCC | Bin 0 -> 3441 bytes CONTENT/BT/GAUGE/QVUL24.PCC | Bin 0 -> 3384 bytes CONTENT/BT/GAUGE/QVUL25.PCC | Bin 0 -> 3351 bytes CONTENT/BT/GAUGE/QVUL26.PCC | Bin 0 -> 3384 bytes CONTENT/BT/GAUGE/QVUL27.PCC | Bin 0 -> 3481 bytes CONTENT/BT/GAUGE/QVULT0.PCC | Bin 0 -> 3061 bytes CONTENT/BT/GAUGE/QVULT1.PCC | Bin 0 -> 3178 bytes CONTENT/BT/GAUGE/QVULT2.PCC | Bin 0 -> 3125 bytes CONTENT/BT/GAUGE/QVULT3.PCC | Bin 0 -> 3176 bytes CONTENT/BT/GAUGE/QVULT4.PCC | Bin 0 -> 3153 bytes CONTENT/BT/GAUGE/QVULT5.PCC | Bin 0 -> 3089 bytes CONTENT/BT/GAUGE/QVULT6.PCC | Bin 0 -> 3157 bytes CONTENT/BT/GAUGE/QVULT7.PCC | Bin 0 -> 3219 bytes CONTENT/BT/GAUGE/RAP_GA.GIM | 21 + CONTENT/BT/GAUGE/RESULT2.TXT | 5 + CONTENT/BT/GAUGE/RIVET_GA.GIM | 18 + CONTENT/BT/GAUGE/RK1_GA.GIM | 38 + CONTENT/BT/GAUGE/RK2_GA.GIM | 22 + CONTENT/BT/GAUGE/RK3_GA.GIM | 23 + CONTENT/BT/GAUGE/RK4_GA.GIM | 22 + CONTENT/BT/GAUGE/RK5_GA.GIM | 25 + CONTENT/BT/GAUGE/RK6_GA.GIM | 26 + CONTENT/BT/GAUGE/RK7_GA.GIM | 24 + CONTENT/BT/GAUGE/ROMMEL.GIM | 15 + CONTENT/BT/GAUGE/SB1E_GA.GIM | 13 + CONTENT/BT/GAUGE/SB1N_GA.GIM | 13 + CONTENT/BT/GAUGE/SB1S_GA.GIM | 13 + CONTENT/BT/GAUGE/SB1W_GA.GIM | 13 + CONTENT/BT/GAUGE/SB3S_GA.GIM | 13 + CONTENT/BT/GAUGE/SDSPMOD.PCC | Bin 0 -> 3966 bytes CONTENT/BT/GAUGE/SEMI.GIM | 15 + CONTENT/BT/GAUGE/SEMIRIG.GIM | 15 + CONTENT/BT/GAUGE/SGEN1.PCC | Bin 0 -> 945 bytes CONTENT/BT/GAUGE/SGEN2.PCC | Bin 0 -> 937 bytes CONTENT/BT/GAUGE/SGEN3.PCC | Bin 0 -> 939 bytes CONTENT/BT/GAUGE/SGEN4.PCC | Bin 0 -> 945 bytes CONTENT/BT/GAUGE/SGEN5.PCC | Bin 0 -> 937 bytes CONTENT/BT/GAUGE/SGEN6.PCC | Bin 0 -> 948 bytes CONTENT/BT/GAUGE/SGENA.PCC | Bin 0 -> 1121 bytes CONTENT/BT/GAUGE/SGENB.PCC | Bin 0 -> 1131 bytes CONTENT/BT/GAUGE/SGENBG.PCC | Bin 0 -> 1230 bytes CONTENT/BT/GAUGE/SGENC.PCC | Bin 0 -> 1101 bytes CONTENT/BT/GAUGE/SGEND.PCC | Bin 0 -> 1115 bytes CONTENT/BT/GAUGE/SGENLEAK.PCC | Bin 0 -> 971 bytes CONTENT/BT/GAUGE/SGENTEMP.PCC | Bin 0 -> 1293 bytes CONTENT/BT/GAUGE/SGENVOLT.PCC | Bin 0 -> 1046 bytes CONTENT/BT/GAUGE/SIZUMIN.PCC | Bin 0 -> 1905 bytes CONTENT/BT/GAUGE/SIZUMOUT.PCC | Bin 0 -> 1833 bytes CONTENT/BT/GAUGE/SMLFONT.PCC | Bin 0 -> 1901 bytes CONTENT/BT/GAUGE/SND2DAMA.PCC | Bin 0 -> 8820 bytes CONTENT/BT/GAUGE/SND2_MR.PCC | Bin 0 -> 7693 bytes CONTENT/BT/GAUGE/SR1E_GA.GIM | 13 + CONTENT/BT/GAUGE/SR1N_GA.GIM | 13 + CONTENT/BT/GAUGE/SR1S_GA.GIM | 13 + CONTENT/BT/GAUGE/SR1W_GA.GIM | 13 + CONTENT/BT/GAUGE/SRMCARRY.GIM | 15 + CONTENT/BT/GAUGE/ST1_GA.GIM | 15 + CONTENT/BT/GAUGE/STB_GA.GIM | 18 + CONTENT/BT/GAUGE/STF_GA.GIM | 15 + CONTENT/BT/GAUGE/STH_GA.GIM | 27 + CONTENT/BT/GAUGE/STICRIT.PCC | Bin 0 -> 11095 bytes CONTENT/BT/GAUGE/STIHEAT.PCC | Bin 0 -> 10862 bytes CONTENT/BT/GAUGE/STIHT.PCC | Bin 0 -> 4853 bytes CONTENT/BT/GAUGE/STIMFD.PCC | Bin 0 -> 7930 bytes CONTENT/BT/GAUGE/STI_GA.GIM | 21 + CONTENT/BT/GAUGE/STRIKER.GIM | 15 + CONTENT/BT/GAUGE/STS_GA.GIM | 15 + CONTENT/BT/GAUGE/STT_GA.GIM | 27 + CONTENT/BT/GAUGE/SVISION.PCC | Bin 0 -> 1788 bytes CONTENT/BT/GAUGE/SW1_GA.GIM | 17 + CONTENT/BT/GAUGE/SW2_GA.GIM | 20 + CONTENT/BT/GAUGE/SW3_GA.GIM | 15 + CONTENT/BT/GAUGE/SW4_GA.GIM | 17 + CONTENT/BT/GAUGE/SW5_GA.GIM | 20 + CONTENT/BT/GAUGE/SW6_GA.GIM | 15 + CONTENT/BT/GAUGE/SWIFTWND.GIM | 15 + CONTENT/BT/GAUGE/THOR.PCX | Bin 0 -> 4333 bytes CONTENT/BT/GAUGE/THORHT.PCC | Bin 0 -> 5785 bytes CONTENT/BT/GAUGE/THOR_GA.GIM | 21 + CONTENT/BT/GAUGE/TINYFONT.PCC | Bin 0 -> 1191 bytes CONTENT/BT/GAUGE/TMC1_GA.GIM | 25 + CONTENT/BT/GAUGE/TMC2_GA.GIM | 17 + CONTENT/BT/GAUGE/TNT_GA.GIM | 27 + CONTENT/BT/GAUGE/TREE_GA.GIM | 19 + CONTENT/BT/GAUGE/TWR_GA.GIM | 28 + CONTENT/BT/GAUGE/VULTHT.PCC | Bin 0 -> 5119 bytes CONTENT/BT/GAUGE/WALL1_GA.GIM | 16 + CONTENT/BT/GAUGE/WALL2_GA.GIM | 16 + CONTENT/BT/GAUGE/WALL3_GA.GIM | 25 + CONTENT/BT/GAUGE/WST_GA.GIM | 27 + CONTENT/BT/GAUGE/X_GA.GIM | 18 + CONTENT/BT/GO.BAT | 1 + CONTENT/BT/JOYSTICK.INI | 587 ++ CONTENT/BT/LAST.EGG | 229 + CONTENT/BT/MAKEEGG.BAK | 97 + CONTENT/BT/MAKEEGG.BAT | 97 + CONTENT/BT/MAPS/ADROP.MAP | 32 + CONTENT/BT/MAPS/ALL.ZNE | 28 + CONTENT/BT/MAPS/ARENA1.MAP | 20 + CONTENT/BT/MAPS/ARENA2.MAP | 21 + CONTENT/BT/MAPS/ARTRUCBU.MAP | 76 + CONTENT/BT/MAPS/ARTRUCKS.MAP | 65 + CONTENT/BT/MAPS/BLANK.MAP | 21 + CONTENT/BT/MAPS/DES.MAP | 71 + CONTENT/BT/MAPS/PDROP.MAP | 27 + CONTENT/BT/MAPS/POL3SFX.MAP | 23 + CONTENT/BT/MAPS/POL4DROP.MAP | 33 + CONTENT/BT/MAPS/POL4SFX.MAP | 23 + CONTENT/BT/MAPS/RAVBU.MAP | 74 + CONTENT/BT/MAPS/RAVTEST.SCN | 70 + CONTENT/BT/MAPS/TEST.MAP | 59 + CONTENT/BT/MAPS/TEST1.MAP | 31 + CONTENT/BT/MAPS/TEST5.MAP | 21 + CONTENT/BT/MENU.BAT | 28 + CONTENT/BT/MODELS/AB01.MOD | 12 + CONTENT/BT/MODELS/AB02.MOD | 12 + CONTENT/BT/MODELS/AB03.MOD | 12 + CONTENT/BT/MODELS/AB04.MOD | 12 + CONTENT/BT/MODELS/AB05.MOD | 12 + CONTENT/BT/MODELS/AB06.MOD | 12 + CONTENT/BT/MODELS/AB06D.MOD | 12 + CONTENT/BT/MODELS/AB07.MOD | 17 + CONTENT/BT/MODELS/AB08.MOD | 8 + CONTENT/BT/MODELS/AB09.MOD | 13 + CONTENT/BT/MODELS/AB09D.MOD | 13 + CONTENT/BT/MODELS/AB10.MOD | 12 + CONTENT/BT/MODELS/AB10D.MOD | 12 + CONTENT/BT/MODELS/ACT01.MOD | 5 + CONTENT/BT/MODELS/ACT02.MOD | 5 + CONTENT/BT/MODELS/ACT03.MOD | 5 + CONTENT/BT/MODELS/ACT04.MOD | 5 + CONTENT/BT/MODELS/ACT05.MOD | 5 + CONTENT/BT/MODELS/AD01.MOD | 8 + CONTENT/BT/MODELS/ADSUP1.MOD | 5 + CONTENT/BT/MODELS/ADSUP2.MOD | 5 + CONTENT/BT/MODELS/ADWLK1.MOD | 12 + CONTENT/BT/MODELS/ADWLK2.MOD | 12 + CONTENT/BT/MODELS/ADWLK3.MOD | 12 + CONTENT/BT/MODELS/AFC100.SUB | 31 + CONTENT/BT/MODELS/AFC25.SUB | 31 + CONTENT/BT/MODELS/AFC5.SUB | 31 + CONTENT/BT/MODELS/AFC50.SUB | 31 + CONTENT/BT/MODELS/AFLOOR.MOD | 8 + CONTENT/BT/MODELS/AMAFC100.SUB | 14 + CONTENT/BT/MODELS/AMBSSDOR.MOD | 8 + CONTENT/BT/MODELS/AMLBX100.SUB | 16 + CONTENT/BT/MODELS/AMMAFC25.SUB | 14 + CONTENT/BT/MODELS/AMMAFC5.SUB | 14 + CONTENT/BT/MODELS/AMMAFC50.SUB | 14 + CONTENT/BT/MODELS/AMMLBX25.SUB | 16 + CONTENT/BT/MODELS/AMMLBX5.SUB | 16 + CONTENT/BT/MODELS/AMMLBX50.SUB | 16 + CONTENT/BT/MODELS/AMMLRM10.SUB | 16 + CONTENT/BT/MODELS/AMMLRM15.SUB | 16 + CONTENT/BT/MODELS/AMMLRM20.SUB | 16 + CONTENT/BT/MODELS/AMMLRM5.SUB | 16 + CONTENT/BT/MODELS/AMMNRK10.SUB | 16 + CONTENT/BT/MODELS/AMMNRK15.SUB | 16 + CONTENT/BT/MODELS/AMMNRK20.SUB | 16 + CONTENT/BT/MODELS/AMMNRK5.SUB | 16 + CONTENT/BT/MODELS/AMMOAC.SUB | 15 + CONTENT/BT/MODELS/AMMOAC10.SUB | 14 + CONTENT/BT/MODELS/AMMOGAUS.SUB | 14 + CONTENT/BT/MODELS/AMMOMG.SUB | 16 + CONTENT/BT/MODELS/AMMSRM2.SUB | 16 + CONTENT/BT/MODELS/AMMSRM25.SUB | 16 + CONTENT/BT/MODELS/AMMSRM30.SUB | 16 + CONTENT/BT/MODELS/AMMSRM4.SUB | 16 + CONTENT/BT/MODELS/AMMSRM6.SUB | 16 + CONTENT/BT/MODELS/AMMSTRK2.SUB | 16 + CONTENT/BT/MODELS/AMMSTRK4.SUB | 16 + CONTENT/BT/MODELS/AMMSTRK6.SUB | 16 + CONTENT/BT/MODELS/APC.MOD | 17 + CONTENT/BT/MODELS/AR01.MOD | 12 + CONTENT/BT/MODELS/AR02.MOD | 12 + CONTENT/BT/MODELS/AR03.MOD | 12 + CONTENT/BT/MODELS/AR04.MOD | 12 + CONTENT/BT/MODELS/AR05.MOD | 12 + CONTENT/BT/MODELS/ARBAN1.MOD | 12 + CONTENT/BT/MODELS/ARBAN2.MOD | 12 + CONTENT/BT/MODELS/ARBAN3.MOD | 12 + CONTENT/BT/MODELS/ARBAN4.MOD | 12 + CONTENT/BT/MODELS/ARBAN5.MOD | 12 + CONTENT/BT/MODELS/ARBAN6.MOD | 12 + CONTENT/BT/MODELS/ARCLD.MOD | 5 + CONTENT/BT/MODELS/ARENA.MOD | 11 + CONTENT/BT/MODELS/ARHORIZ.MOD | 5 + CONTENT/BT/MODELS/ARLID.MOD | 8 + CONTENT/BT/MODELS/ARMOR1.DMG | 4 + CONTENT/BT/MODELS/ARMRMOVR.MOD | 17 + CONTENT/BT/MODELS/ARWC.MOD | 5 + CONTENT/BT/MODELS/ATTACKER.MOD | 8 + CONTENT/BT/MODELS/AUDIO.BLD | 283 + CONTENT/BT/MODELS/AVA1.DMG | 192 + CONTENT/BT/MODELS/AVA1.MOD | 136 + CONTENT/BT/MODELS/AVA1.SUB | 203 + CONTENT/BT/MODELS/AVA1DEAD.MOD | 9 + CONTENT/BT/MODELS/AVA1DMG.EXP | 28 + CONTENT/BT/MODELS/AVA1DMG.TBL | 197 + CONTENT/BT/MODELS/AVA1L4.CTL | 817 ++ CONTENT/BT/MODELS/AVA1THR.CTL | 57 + CONTENT/BT/MODELS/AVA2.MOD | 136 + CONTENT/BT/MODELS/AVA2DEAD.MOD | 9 + CONTENT/BT/MODELS/AVA2DMG.EXP | 28 + CONTENT/BT/MODELS/AVA2THR.CTL | 81 + CONTENT/BT/MODELS/AVADEAD.MOD | 9 + CONTENT/BT/MODELS/AVADMG.EXP | 28 + CONTENT/BT/MODELS/AVAL4.CTL | 1061 +++ CONTENT/BT/MODELS/AVATAR.DMG | 195 + CONTENT/BT/MODELS/AVATAR.MOD | 136 + CONTENT/BT/MODELS/AVATAR.SUB | 230 + CONTENT/BT/MODELS/AVATHR.CTL | 75 + CONTENT/BT/MODELS/AW01.MOD | 8 + CONTENT/BT/MODELS/AW02.MOD | 8 + CONTENT/BT/MODELS/AW03.MOD | 11 + CONTENT/BT/MODELS/AW04.MOD | 8 + CONTENT/BT/MODELS/AW05.MOD | 12 + CONTENT/BT/MODELS/AWBOX1.MOD | 8 + CONTENT/BT/MODELS/AWWLK1.MOD | 9 + CONTENT/BT/MODELS/BAC1.MOD | 12 + CONTENT/BT/MODELS/BAT.MOD | 132 + CONTENT/BT/MODELS/BAT.SUB | 209 + CONTENT/BT/MODELS/BATDMG.EXP | 28 + CONTENT/BT/MODELS/BATDMG.TBL | 197 + CONTENT/BT/MODELS/BATTHR.CTL | 57 + CONTENT/BT/MODELS/BCOR1.MOD | 8 + CONTENT/BT/MODELS/BCOR2.MOD | 8 + CONTENT/BT/MODELS/BDET1.MOD | 5 + CONTENT/BT/MODELS/BDET2.MOD | 5 + CONTENT/BT/MODELS/BDET3.MOD | 5 + CONTENT/BT/MODELS/BDET4.MOD | 12 + CONTENT/BT/MODELS/BDET6.MOD | 5 + CONTENT/BT/MODELS/BHK1.DMG | 183 + CONTENT/BT/MODELS/BHK1.MOD | 136 + CONTENT/BT/MODELS/BHK1.SUB | 208 + CONTENT/BT/MODELS/BHK1DEAD.MOD | 9 + CONTENT/BT/MODELS/BHK1DMG.EXP | 28 + CONTENT/BT/MODELS/BHK1DMG.TBL | 181 + CONTENT/BT/MODELS/BHK1L4.CTL | 909 +++ CONTENT/BT/MODELS/BHK1THR.CTL | 63 + CONTENT/BT/MODELS/BIGDEAD.MOD | 11 + CONTENT/BT/MODELS/BLD.MOD | 20 + CONTENT/BT/MODELS/BLD01.MOD | 10 + CONTENT/BT/MODELS/BLD02.MOD | 10 + CONTENT/BT/MODELS/BLD03.MOD | 18 + CONTENT/BT/MODELS/BLD04.MOD | 20 + CONTENT/BT/MODELS/BLD05.MOD | 9 + CONTENT/BT/MODELS/BLD06.MOD | 15 + CONTENT/BT/MODELS/BLD08.MOD | 14 + CONTENT/BT/MODELS/BLD20.MOD | 20 + CONTENT/BT/MODELS/BLD24.MOD | 20 + CONTENT/BT/MODELS/BLD26.MOD | 21 + CONTENT/BT/MODELS/BLD27.MOD | 14 + CONTENT/BT/MODELS/BLHDEAD.MOD | 9 + CONTENT/BT/MODELS/BLHDMG.EXP | 28 + CONTENT/BT/MODELS/BLHL4.CTL | 1145 +++ CONTENT/BT/MODELS/BLHTHR.CTL | 81 + CONTENT/BT/MODELS/BLKHAWK.DMG | 184 + CONTENT/BT/MODELS/BLKHAWK.MOD | 136 + CONTENT/BT/MODELS/BLKHAWK.SUB | 235 + CONTENT/BT/MODELS/BLKJACK.MOD | 134 + CONTENT/BT/MODELS/BLKJACK.SUB | 212 + CONTENT/BT/MODELS/BNK.MOD | 20 + CONTENT/BT/MODELS/BPIP1.MOD | 12 + CONTENT/BT/MODELS/BULLDOG.MOD | 18 + CONTENT/BT/MODELS/BUTTEA.MOD | 11 + CONTENT/BT/MODELS/BUTTEB.MOD | 11 + CONTENT/BT/MODELS/BUTTEC.MOD | 11 + CONTENT/BT/MODELS/BUTTED.MOD | 11 + CONTENT/BT/MODELS/BUTTEE.MOD | 11 + CONTENT/BT/MODELS/BUTTEEU.MOD | 5 + CONTENT/BT/MODELS/BUTTEF.MOD | 9 + CONTENT/BT/MODELS/BWLK1.MOD | 12 + CONTENT/BT/MODELS/CAL.SUB | 215 + CONTENT/BT/MODELS/CALP.DMG | 34 + CONTENT/BT/MODELS/CALP.MOD | 20 + CONTENT/BT/MODELS/CALPB.MOD | 11 + CONTENT/BT/MODELS/CAMERA.MOD | 13 + CONTENT/BT/MODELS/CAMPOS.MOD | 8 + CONTENT/BT/MODELS/CANHIT.MOD | 11 + CONTENT/BT/MODELS/CANHITI.MOD | 10 + CONTENT/BT/MODELS/CB1.MOD | 8 + CONTENT/BT/MODELS/CLD.MOD | 5 + CONTENT/BT/MODELS/COMTRUCK.MOD | 17 + CONTENT/BT/MODELS/CONDENSR.SUB | 14 + CONTENT/BT/MODELS/CONVOY.MOD | 10 + CONTENT/BT/MODELS/COOLANT.MOD | 17 + CONTENT/BT/MODELS/CRT.MOD | 18 + CONTENT/BT/MODELS/CTARMAC.MOD | 6 + CONTENT/BT/MODELS/DAM1HIT.MOD | 7 + CONTENT/BT/MODELS/DAM1HITI.MOD | 6 + CONTENT/BT/MODELS/DAM2HIT.MOD | 7 + CONTENT/BT/MODELS/DAM2HITI.MOD | 6 + CONTENT/BT/MODELS/DAM3EXP.MOD | 6 + CONTENT/BT/MODELS/DAM3HIT.MOD | 10 + CONTENT/BT/MODELS/DAM3HITI.MOD | 6 + CONTENT/BT/MODELS/DAM4EXP.MOD | 6 + CONTENT/BT/MODELS/DAM4EXPI.MOD | 6 + CONTENT/BT/MODELS/DAM4HIT.MOD | 10 + CONTENT/BT/MODELS/DAM4HITI.MOD | 9 + CONTENT/BT/MODELS/DAVION.MOD | 2 + CONTENT/BT/MODELS/DECOY.MOD | 8 + CONTENT/BT/MODELS/DEFENDER.MOD | 8 + CONTENT/BT/MODELS/DESTHIT.MOD | 7 + CONTENT/BT/MODELS/DESTHITI.MOD | 6 + CONTENT/BT/MODELS/DFLTROLE.MOD | 10 + CONTENT/BT/MODELS/DG100.MOD | 9 + CONTENT/BT/MODELS/DG100A.MOD | 8 + CONTENT/BT/MODELS/DHILLG1.MOD | 11 + CONTENT/BT/MODELS/DHILLG2.MOD | 11 + CONTENT/BT/MODELS/DHILLG3.MOD | 11 + CONTENT/BT/MODELS/DISH.MOD | 17 + CONTENT/BT/MODELS/DMG.BLD | 1 + CONTENT/BT/MODELS/DOZER.MOD | 14 + CONTENT/BT/MODELS/DRESF.MOD | 8 + CONTENT/BT/MODELS/DSKY.MOD | 6 + CONTENT/BT/MODELS/DTARMAC.MOD | 6 + CONTENT/BT/MODELS/DUMB.MOD | 24 + CONTENT/BT/MODELS/DUMB2.SUB | 33 + CONTENT/BT/MODELS/DUMB4.SUB | 33 + CONTENT/BT/MODELS/DUMB6.SUB | 33 + CONTENT/BT/MODELS/ERLLASER.SUB | 36 + CONTENT/BT/MODELS/ERMLASER.SUB | 36 + CONTENT/BT/MODELS/ERPPC.SUB | 36 + CONTENT/BT/MODELS/ERSLASER.SUB | 35 + CONTENT/BT/MODELS/EXPLODE.MOD | 6 + CONTENT/BT/MODELS/EXPLODE.ONL | 58 + CONTENT/BT/MODELS/FD1.MOD | 5 + CONTENT/BT/MODELS/FD2.MOD | 5 + CONTENT/BT/MODELS/FD3.MOD | 5 + CONTENT/BT/MODELS/FD4.MOD | 8 + CONTENT/BT/MODELS/FIND.TXT | 11 + CONTENT/BT/MODELS/FIRDMG.EXP | 28 + CONTENT/BT/MODELS/FIRDMG.TBL | 189 + CONTENT/BT/MODELS/FIRSTRTR.MOD | 135 + CONTENT/BT/MODELS/FIRSTRTR.SUB | 191 + CONTENT/BT/MODELS/FIRTHR.CTL | 57 + CONTENT/BT/MODELS/FL1.MOD | 8 + CONTENT/BT/MODELS/FP0.MOD | 17 + CONTENT/BT/MODELS/FP0D.MOD | 5 + CONTENT/BT/MODELS/FP1.MOD | 20 + CONTENT/BT/MODELS/FP2.MOD | 20 + CONTENT/BT/MODELS/FP2D.MOD | 5 + CONTENT/BT/MODELS/FP3.MOD | 17 + CONTENT/BT/MODELS/FT1.MOD | 20 + CONTENT/BT/MODELS/FT2.MOD | 20 + CONTENT/BT/MODELS/GAUSSRFL.SUB | 33 + CONTENT/BT/MODELS/GD1.MOD | 8 + CONTENT/BT/MODELS/GD2.MOD | 8 + CONTENT/BT/MODELS/GD3.MOD | 8 + CONTENT/BT/MODELS/GD4.MOD | 8 + CONTENT/BT/MODELS/GD5.MOD | 10 + CONTENT/BT/MODELS/GENRATOR.SUB | 17 + CONTENT/BT/MODELS/GNDHIT.MOD | 9 + CONTENT/BT/MODELS/GNR.MOD | 20 + CONTENT/BT/MODELS/GRND100.MOD | 9 + CONTENT/BT/MODELS/GTARMAC.MOD | 6 + CONTENT/BT/MODELS/GYRO.SUB | 82 + CONTENT/BT/MODELS/HARASSER.MOD | 18 + CONTENT/BT/MODELS/HC1.MOD | 14 + CONTENT/BT/MODELS/HC2.MOD | 14 + CONTENT/BT/MODELS/HEATSNK.SUB | 15 + CONTENT/BT/MODELS/HILLA.MOD | 12 + CONTENT/BT/MODELS/HILLC.MOD | 12 + CONTENT/BT/MODELS/HILLG1.MOD | 11 + CONTENT/BT/MODELS/HILLG2.MOD | 11 + CONTENT/BT/MODELS/HILLG3.MOD | 11 + CONTENT/BT/MODELS/HL1.MOD | 12 + CONTENT/BT/MODELS/HL2.MOD | 12 + CONTENT/BT/MODELS/HN1.MOD | 20 + CONTENT/BT/MODELS/HOSTAGE.MOD | 8 + CONTENT/BT/MODELS/HUD.SUB | 14 + CONTENT/BT/MODELS/HUMMER.MOD | 17 + CONTENT/BT/MODELS/HUT.MOD | 20 + CONTENT/BT/MODELS/HWZ.MOD | 20 + CONTENT/BT/MODELS/ICONBLH.MOD | 16 + CONTENT/BT/MODELS/ICONJAK.MOD | 11 + CONTENT/BT/MODELS/ICONLOK.MOD | 16 + CONTENT/BT/MODELS/ICONOWN.MOD | 16 + CONTENT/BT/MODELS/ICONTHR.DMG | 3 + CONTENT/BT/MODELS/ICONTHR.MOD | 16 + CONTENT/BT/MODELS/ICONTHRD.MOD | 11 + CONTENT/BT/MODELS/ICONVUL.DMG | 3 + CONTENT/BT/MODELS/ICONVUL.MOD | 16 + CONTENT/BT/MODELS/JAKDMG.EXP | 28 + CONTENT/BT/MODELS/JAKDMG.TBL | 187 + CONTENT/BT/MODELS/JAKTHR.CTL | 63 + CONTENT/BT/MODELS/KURITA.MOD | 2 + CONTENT/BT/MODELS/LASER.MOD | 65 + CONTENT/BT/MODELS/LLASER.SUB | 36 + CONTENT/BT/MODELS/LNTRK1.MOD | 14 + CONTENT/BT/MODELS/LO1DMG.TBL | 160 + CONTENT/BT/MODELS/LOK1.DMG | 189 + CONTENT/BT/MODELS/LOK1.MOD | 136 + CONTENT/BT/MODELS/LOK1.SUB | 226 + CONTENT/BT/MODELS/LOK1DMG.EXP | 28 + CONTENT/BT/MODELS/LOK1DMG.TBL | 189 + CONTENT/BT/MODELS/LOK1L4.CTL | 1060 +++ CONTENT/BT/MODELS/LOK1THR.CTL | 75 + CONTENT/BT/MODELS/LOK2.DMG | 193 + CONTENT/BT/MODELS/LOK2.MOD | 136 + CONTENT/BT/MODELS/LOK2.SUB | 237 + CONTENT/BT/MODELS/LOK2DMG.EXP | 28 + CONTENT/BT/MODELS/LOK2L4.CTL | 1060 +++ CONTENT/BT/MODELS/LOK2THR.CTL | 75 + CONTENT/BT/MODELS/LOKDEAD.MOD | 9 + CONTENT/BT/MODELS/LOKDMG.EXP | 28 + CONTENT/BT/MODELS/LOKI.MOD | 136 + CONTENT/BT/MODELS/LOKI.SUB | 212 + CONTENT/BT/MODELS/LOKI1.MOD | 134 + CONTENT/BT/MODELS/LOKI1.SUB | 232 + CONTENT/BT/MODELS/LOKL4.CTL | 895 +++ CONTENT/BT/MODELS/LOKTHR.CTL | 63 + CONTENT/BT/MODELS/LRM.MOD | 24 + CONTENT/BT/MODELS/LRM10.SUB | 33 + CONTENT/BT/MODELS/LRM15.SUB | 33 + CONTENT/BT/MODELS/LRM20.SUB | 33 + CONTENT/BT/MODELS/LRM5.SUB | 33 + CONTENT/BT/MODELS/LRMCARRY.MOD | 18 + CONTENT/BT/MODELS/LRMLANCH.SUB | 28 + CONTENT/BT/MODELS/LZRHIT.MOD | 11 + CONTENT/BT/MODELS/LZRHITI.MOD | 10 + CONTENT/BT/MODELS/MACHGUN.SUB | 33 + CONTENT/BT/MODELS/MAD.DMG | 114 + CONTENT/BT/MODELS/MAD1.DMG | 195 + CONTENT/BT/MODELS/MAD1.MOD | 131 + CONTENT/BT/MODELS/MAD1.SUB | 227 + CONTENT/BT/MODELS/MAD1DMG.EXP | 28 + CONTENT/BT/MODELS/MAD1DMG.TBL | 200 + CONTENT/BT/MODELS/MAD1L4.CTL | 974 +++ CONTENT/BT/MODELS/MAD1THR.CTL | 69 + CONTENT/BT/MODELS/MAD2.DMG | 193 + CONTENT/BT/MODELS/MAD2.MOD | 131 + CONTENT/BT/MODELS/MAD2.SUB | 218 + CONTENT/BT/MODELS/MAD2DMG.EXP | 28 + CONTENT/BT/MODELS/MAD2L4.CTL | 896 +++ CONTENT/BT/MODELS/MAD2THR.CTL | 63 + CONTENT/BT/MODELS/MADCAT.DMG | 190 + CONTENT/BT/MODELS/MADCAT.MOD | 131 + CONTENT/BT/MODELS/MADCAT.SUB | 203 + CONTENT/BT/MODELS/MADDEAD.MOD | 9 + CONTENT/BT/MODELS/MADDMG.EXP | 28 + CONTENT/BT/MODELS/MADL4.CTL | 809 ++ CONTENT/BT/MODELS/MADTHR.CTL | 57 + CONTENT/BT/MODELS/MAJHIT.MOD | 9 + CONTENT/BT/MODELS/MECHALRM.MOD | 25 + CONTENT/BT/MODELS/MECHDEAD.MOD | 10 + CONTENT/BT/MODELS/MECHMOVR.MOD | 17 + CONTENT/BT/MODELS/MED.DMG | 3 + CONTENT/BT/MODELS/MEDDEAD.MOD | 10 + CONTENT/BT/MODELS/MGHIT.MOD | 10 + CONTENT/BT/MODELS/MGHITI.MOD | 9 + CONTENT/BT/MODELS/MINHIT.MOD | 9 + CONTENT/BT/MODELS/MLASER.SUB | 35 + CONTENT/BT/MODELS/MSL.DMG | 3 + CONTENT/BT/MODELS/MSL.MOD | 16 + CONTENT/BT/MODELS/MSLBASE.MOD | 8 + CONTENT/BT/MODELS/MSLDEAD.MOD | 11 + CONTENT/BT/MODELS/MSLG.MOD | 20 + CONTENT/BT/MODELS/MSLH.MOD | 11 + CONTENT/BT/MODELS/MSLHIT.MOD | 11 + CONTENT/BT/MODELS/MSLHITI.MOD | 10 + CONTENT/BT/MODELS/MSLR.DMG | 3 + CONTENT/BT/MODELS/MSLR.MOD | 20 + CONTENT/BT/MODELS/MSLRB.MOD | 11 + CONTENT/BT/MODELS/MSLROAD1.MOD | 5 + CONTENT/BT/MODELS/MYOMERS.SUB | 27 + CONTENT/BT/MODELS/NORETURN.MOD | 10 + CONTENT/BT/MODELS/NRK.MOD | 24 + CONTENT/BT/MODELS/NRK10.SUB | 33 + CONTENT/BT/MODELS/NRK15.SUB | 33 + CONTENT/BT/MODELS/NRK20.SUB | 33 + CONTENT/BT/MODELS/NRK5.SUB | 33 + CONTENT/BT/MODELS/NTR.MOD | 5 + CONTENT/BT/MODELS/OLDCON.SUB | 13 + CONTENT/BT/MODELS/OLDGEN.SUB | 17 + CONTENT/BT/MODELS/OLDLOKI.SUB | 132 + CONTENT/BT/MODELS/OWENS.DMG | 162 + CONTENT/BT/MODELS/OWENS.MOD | 138 + CONTENT/BT/MODELS/OWENS.SUB | 217 + CONTENT/BT/MODELS/OWN1.DMG | 157 + CONTENT/BT/MODELS/OWN1.MOD | 138 + CONTENT/BT/MODELS/OWN1.SUB | 192 + CONTENT/BT/MODELS/OWN1DMG.EXP | 28 + CONTENT/BT/MODELS/OWN1DMG.TBL | 182 + CONTENT/BT/MODELS/OWN1L4.CTL | 731 ++ CONTENT/BT/MODELS/OWN1THR.CTL | 51 + CONTENT/BT/MODELS/OWNDEAD.MOD | 9 + CONTENT/BT/MODELS/OWNDMG.EXP | 28 + CONTENT/BT/MODELS/OWNL4.CTL | 974 +++ CONTENT/BT/MODELS/OWNTHR.CTL | 69 + CONTENT/BT/MODELS/PDSH.MOD | 20 + CONTENT/BT/MODELS/PGN.DMG | 3 + CONTENT/BT/MODELS/PGN.MOD | 36 + CONTENT/BT/MODELS/PLAYER.MOD | 3 + CONTENT/BT/MODELS/PLIT.MOD | 17 + CONTENT/BT/MODELS/PPC.SUB | 36 + CONTENT/BT/MODELS/PPCHIT.MOD | 12 + CONTENT/BT/MODELS/PPCHITI.MOD | 10 + CONTENT/BT/MODELS/PROFILE1.MOD | 5 + CONTENT/BT/MODELS/PROFILE2.MOD | 5 + CONTENT/BT/MODELS/PROFILE3.MOD | 5 + CONTENT/BT/MODELS/PROFILE4.MOD | 5 + CONTENT/BT/MODELS/PROFILE5.MOD | 5 + CONTENT/BT/MODELS/PROFILE6.MOD | 5 + CONTENT/BT/MODELS/PROFILE7.MOD | 5 + CONTENT/BT/MODELS/PROFILE8.MOD | 5 + CONTENT/BT/MODELS/PROJTILE.MOD | 16 + CONTENT/BT/MODELS/PWIN1.MOD | 5 + CONTENT/BT/MODELS/PWIN2.MOD | 5 + CONTENT/BT/MODELS/PWIN3.MOD | 5 + CONTENT/BT/MODELS/PWIN4.MOD | 5 + CONTENT/BT/MODELS/PWIN5.MOD | 5 + CONTENT/BT/MODELS/PWIN6.MOD | 5 + CONTENT/BT/MODELS/PWIN7.MOD | 5 + CONTENT/BT/MODELS/PWIN8.MOD | 5 + CONTENT/BT/MODELS/RAPDEAD.MOD | 9 + CONTENT/BT/MODELS/RAPDMG.EXP | 28 + CONTENT/BT/MODELS/RAPDMG.TBL | 189 + CONTENT/BT/MODELS/RAPTHR.CTL | 63 + CONTENT/BT/MODELS/RAPTOR.MOD | 135 + CONTENT/BT/MODELS/RAPTOR.SUB | 212 + CONTENT/BT/MODELS/RAVFLOOR.MOD | 9 + CONTENT/BT/MODELS/RAVINET1.MOD | 6 + CONTENT/BT/MODELS/RAVINET2.MOD | 6 + CONTENT/BT/MODELS/RAVINET3.MOD | 6 + CONTENT/BT/MODELS/RAVINET4.MOD | 6 + CONTENT/BT/MODELS/RAVINET5.MOD | 6 + CONTENT/BT/MODELS/RAVINET6.MOD | 6 + CONTENT/BT/MODELS/RAVINET7.MOD | 6 + CONTENT/BT/MODELS/RAVINET8.MOD | 6 + CONTENT/BT/MODELS/RAVWIN.MOD | 6 + CONTENT/BT/MODELS/RB1.MOD | 5 + CONTENT/BT/MODELS/RB2.MOD | 5 + CONTENT/BT/MODELS/RB3.MOD | 5 + CONTENT/BT/MODELS/RB4.MOD | 5 + CONTENT/BT/MODELS/RB5.MOD | 5 + CONTENT/BT/MODELS/RB6.MOD | 5 + CONTENT/BT/MODELS/RD1.MOD | 5 + CONTENT/BT/MODELS/RD2.MOD | 5 + CONTENT/BT/MODELS/RESERVE.SUB | 14 + CONTENT/BT/MODELS/RESULT.TXT | 8 + CONTENT/BT/MODELS/RESULT2.TXT | 5 + CONTENT/BT/MODELS/RK1.MOD | 11 + CONTENT/BT/MODELS/RK2.MOD | 11 + CONTENT/BT/MODELS/RK3.MOD | 11 + CONTENT/BT/MODELS/RK4.MOD | 11 + CONTENT/BT/MODELS/RK5.MOD | 11 + CONTENT/BT/MODELS/RK6.MOD | 11 + CONTENT/BT/MODELS/RK7.MOD | 11 + CONTENT/BT/MODELS/ROMMEL.MOD | 17 + CONTENT/BT/MODELS/RWD.MOD | 8 + CONTENT/BT/MODELS/RWIN1.MOD | 6 + CONTENT/BT/MODELS/SAW.MOD | 8 + CONTENT/BT/MODELS/SB1.MOD | 8 + CONTENT/BT/MODELS/SB1B.MOD | 8 + CONTENT/BT/MODELS/SB1C.MOD | 8 + CONTENT/BT/MODELS/SB1D.MOD | 8 + CONTENT/BT/MODELS/SB1E.MOD | 11 + CONTENT/BT/MODELS/SB1N.MOD | 11 + CONTENT/BT/MODELS/SB1S.MOD | 11 + CONTENT/BT/MODELS/SB1W.MOD | 11 + CONTENT/BT/MODELS/SB2.MOD | 8 + CONTENT/BT/MODELS/SB2B.MOD | 8 + CONTENT/BT/MODELS/SB2C.MOD | 8 + CONTENT/BT/MODELS/SB2D.MOD | 8 + CONTENT/BT/MODELS/SB2E.MOD | 8 + CONTENT/BT/MODELS/SB2N.MOD | 8 + CONTENT/BT/MODELS/SB2S.MOD | 8 + CONTENT/BT/MODELS/SB2W.MOD | 8 + CONTENT/BT/MODELS/SB3E.MOD | 8 + CONTENT/BT/MODELS/SB3N.MOD | 8 + CONTENT/BT/MODELS/SB3S.MOD | 11 + CONTENT/BT/MODELS/SB3W.MOD | 8 + CONTENT/BT/MODELS/SB4E.MOD | 8 + CONTENT/BT/MODELS/SB4N.MOD | 8 + CONTENT/BT/MODELS/SB4S.MOD | 8 + CONTENT/BT/MODELS/SB4W.MOD | 8 + CONTENT/BT/MODELS/SEMI.MOD | 14 + CONTENT/BT/MODELS/SEMIRIG.MOD | 14 + CONTENT/BT/MODELS/SENSOR.SUB | 19 + CONTENT/BT/MODELS/SKY.MOD | 5 + CONTENT/BT/MODELS/SL2.MOD | 17 + CONTENT/BT/MODELS/SLASER.SUB | 35 + CONTENT/BT/MODELS/SLT.MOD | 8 + CONTENT/BT/MODELS/SML.DMG | 3 + CONTENT/BT/MODELS/SMLDEAD.MOD | 10 + CONTENT/BT/MODELS/SN1.MOD | 8 + CONTENT/BT/MODELS/SN2.MOD | 12 + CONTENT/BT/MODELS/SN4.MOD | 12 + CONTENT/BT/MODELS/SND1.DMG | 182 + CONTENT/BT/MODELS/SND1.MOD | 135 + CONTENT/BT/MODELS/SND1.SUB | 197 + CONTENT/BT/MODELS/SND1DMG.EXP | 28 + CONTENT/BT/MODELS/SND1DMG.TBL | 187 + CONTENT/BT/MODELS/SND1L4.CTL | 809 ++ CONTENT/BT/MODELS/SND1THR.CTL | 57 + CONTENT/BT/MODELS/SND2.MOD | 135 + CONTENT/BT/MODELS/SND2.SUB | 239 + CONTENT/BT/MODELS/SND2DMG.EXP | 28 + CONTENT/BT/MODELS/SND2THR.CTL | 81 + CONTENT/BT/MODELS/SNDDEAD.MOD | 9 + CONTENT/BT/MODELS/SNDDMG.EXP | 28 + CONTENT/BT/MODELS/SNDL4.CTL | 1060 +++ CONTENT/BT/MODELS/SNDTHR.CTL | 75 + CONTENT/BT/MODELS/SNH.MOD | 14 + CONTENT/BT/MODELS/SNTK1.MOD | 12 + CONTENT/BT/MODELS/SR1E.MOD | 11 + CONTENT/BT/MODELS/SR1N.MOD | 11 + CONTENT/BT/MODELS/SR1S.MOD | 11 + CONTENT/BT/MODELS/SR1W.MOD | 11 + CONTENT/BT/MODELS/SRC1NE.MOD | 8 + CONTENT/BT/MODELS/SRC1NW.MOD | 8 + CONTENT/BT/MODELS/SRC1SE.MOD | 8 + CONTENT/BT/MODELS/SRC1SW.MOD | 8 + CONTENT/BT/MODELS/SRCHLITE.SUB | 10 + CONTENT/BT/MODELS/SRM.MOD | 24 + CONTENT/BT/MODELS/SRM2.SUB | 33 + CONTENT/BT/MODELS/SRM4.SUB | 33 + CONTENT/BT/MODELS/SRM6.SUB | 33 + CONTENT/BT/MODELS/SRMCARRY.MOD | 18 + CONTENT/BT/MODELS/ST1.MOD | 11 + CONTENT/BT/MODELS/STATE.RST | 12 + CONTENT/BT/MODELS/STB.MOD | 11 + CONTENT/BT/MODELS/STEPHIT.MOD | 11 + CONTENT/BT/MODELS/STF.MOD | 11 + CONTENT/BT/MODELS/STH.MOD | 11 + CONTENT/BT/MODELS/STIDEAD.MOD | 9 + CONTENT/BT/MODELS/STIDMG.EXP | 28 + CONTENT/BT/MODELS/STIDMG.TBL | 192 + CONTENT/BT/MODELS/STITHR.CTL | 51 + CONTENT/BT/MODELS/STRIDER.MOD | 134 + CONTENT/BT/MODELS/STRIDER.SUB | 194 + CONTENT/BT/MODELS/STRIKER.MOD | 18 + CONTENT/BT/MODELS/STRK.MOD | 24 + CONTENT/BT/MODELS/STRK2.SUB | 33 + CONTENT/BT/MODELS/STRK4.SUB | 33 + CONTENT/BT/MODELS/STRK6.SUB | 33 + CONTENT/BT/MODELS/STS.MOD | 11 + CONTENT/BT/MODELS/STT.MOD | 11 + CONTENT/BT/MODELS/SUB.BLD | 116 + CONTENT/BT/MODELS/SUN1.SUB | 188 + CONTENT/BT/MODELS/SUNDER.DMG | 187 + CONTENT/BT/MODELS/SUNDER.MOD | 135 + CONTENT/BT/MODELS/SUNDER.SUB | 230 + CONTENT/BT/MODELS/SV2.MOD | 8 + CONTENT/BT/MODELS/SV2B.MOD | 8 + CONTENT/BT/MODELS/SV2C.MOD | 8 + CONTENT/BT/MODELS/SV2D.MOD | 8 + CONTENT/BT/MODELS/SV3.MOD | 8 + CONTENT/BT/MODELS/SV3B.MOD | 8 + CONTENT/BT/MODELS/SV3C.MOD | 8 + CONTENT/BT/MODELS/SV3D.MOD | 8 + CONTENT/BT/MODELS/SW1.MOD | 11 + CONTENT/BT/MODELS/SW2.MOD | 11 + CONTENT/BT/MODELS/SW3.MOD | 11 + CONTENT/BT/MODELS/SW4.MOD | 11 + CONTENT/BT/MODELS/SW5.MOD | 11 + CONTENT/BT/MODELS/SW6.MOD | 11 + CONTENT/BT/MODELS/SWIFTWND.MOD | 18 + CONTENT/BT/MODELS/TEST.TXT | 1 + CONTENT/BT/MODELS/TEXT.TXT | 20 + CONTENT/BT/MODELS/THERMAL.SUB | 10 + CONTENT/BT/MODELS/THOR.DMG | 191 + CONTENT/BT/MODELS/THOR.MOD | 144 + CONTENT/BT/MODELS/THOR.SUB | 204 + CONTENT/BT/MODELS/THR.DMG | 121 + CONTENT/BT/MODELS/THR1.DMG | 193 + CONTENT/BT/MODELS/THR1.MOD | 136 + CONTENT/BT/MODELS/THR1.SUB | 238 + CONTENT/BT/MODELS/THR1DEAD.MOD | 9 + CONTENT/BT/MODELS/THR1DMG.EXP | 28 + CONTENT/BT/MODELS/THR1DMG.TBL | 189 + CONTENT/BT/MODELS/THR1L4.CTL | 1053 +++ CONTENT/BT/MODELS/THR1THR.CTL | 75 + CONTENT/BT/MODELS/THR6.MOD | 136 + CONTENT/BT/MODELS/THR6DEAD.MOD | 9 + CONTENT/BT/MODELS/THR6DMG.EXP | 28 + CONTENT/BT/MODELS/THR6THR.CTL | 81 + CONTENT/BT/MODELS/THRCTL.BLD | 21 + CONTENT/BT/MODELS/THRDEAD.MOD | 9 + CONTENT/BT/MODELS/THRDMG.EXP | 28 + CONTENT/BT/MODELS/THRDMGRD.EXP | 9 + CONTENT/BT/MODELS/THRL4.CTL | 888 +++ CONTENT/BT/MODELS/THRTHR.CTL | 63 + CONTENT/BT/MODELS/TK1.MOD | 8 + CONTENT/BT/MODELS/TM1.MOD | 5 + CONTENT/BT/MODELS/TM2.MOD | 5 + CONTENT/BT/MODELS/TMC1.MOD | 11 + CONTENT/BT/MODELS/TMC2.MOD | 11 + CONTENT/BT/MODELS/TMC3.MOD | 8 + CONTENT/BT/MODELS/TMC4.MOD | 8 + CONTENT/BT/MODELS/TMC5.MOD | 8 + CONTENT/BT/MODELS/TMC6.MOD | 8 + CONTENT/BT/MODELS/TMC7.MOD | 8 + CONTENT/BT/MODELS/TMC8.MOD | 8 + CONTENT/BT/MODELS/TNT.MOD | 20 + CONTENT/BT/MODELS/TORSO.SUB | 21 + CONTENT/BT/MODELS/TORSOLMT.SUB | 20 + CONTENT/BT/MODELS/TREE.MOD | 17 + CONTENT/BT/MODELS/TRK.DMG | 3 + CONTENT/BT/MODELS/TRK1.MOD | 14 + CONTENT/BT/MODELS/TRK3.MOD | 14 + CONTENT/BT/MODELS/TRK4.MOD | 14 + CONTENT/BT/MODELS/TRKDEAD.MOD | 10 + CONTENT/BT/MODELS/TT1.MOD | 14 + CONTENT/BT/MODELS/TT2.MOD | 14 + CONTENT/BT/MODELS/TWR.DMG | 3 + CONTENT/BT/MODELS/TWR.MOD | 20 + CONTENT/BT/MODELS/TWRDEAD.MOD | 11 + CONTENT/BT/MODELS/VEHICLE.TBL | 46 + CONTENT/BT/MODELS/VUL1.DMG | 200 + CONTENT/BT/MODELS/VUL1.MOD | 132 + CONTENT/BT/MODELS/VUL1.SUB | 215 + CONTENT/BT/MODELS/VUL1DMG.EXP | 28 + CONTENT/BT/MODELS/VUL1L4.CTL | 974 +++ CONTENT/BT/MODELS/VUL1THR.CTL | 69 + CONTENT/BT/MODELS/VUL2.MOD | 132 + CONTENT/BT/MODELS/VUL2DMG.EXP | 28 + CONTENT/BT/MODELS/VUL2DMG.TBL | 195 + CONTENT/BT/MODELS/VUL2THR.CTL | 81 + CONTENT/BT/MODELS/VULDEAD.MOD | 9 + CONTENT/BT/MODELS/VULDMG.EXP | 28 + CONTENT/BT/MODELS/VULL4.CTL | 974 +++ CONTENT/BT/MODELS/VULTHR.CTL | 69 + CONTENT/BT/MODELS/VULTURE.DMG | 200 + CONTENT/BT/MODELS/VULTURE.MOD | 132 + CONTENT/BT/MODELS/VULTURE.SUB | 215 + CONTENT/BT/MODELS/WALL1.MOD | 11 + CONTENT/BT/MODELS/WALL10K.MOD | 7 + CONTENT/BT/MODELS/WALL2.MOD | 11 + CONTENT/BT/MODELS/WALL3.MOD | 11 + CONTENT/BT/MODELS/WL1.MOD | 8 + CONTENT/BT/MODELS/WL2.MOD | 8 + CONTENT/BT/MODELS/WL3.MOD | 8 + CONTENT/BT/MODELS/WL4.MOD | 8 + CONTENT/BT/MODELS/WL5.MOD | 8 + CONTENT/BT/MODELS/WL6.MOD | 8 + CONTENT/BT/MODELS/WL7.MOD | 8 + CONTENT/BT/MODELS/WL8.MOD | 8 + CONTENT/BT/MODELS/WL9.MOD | 8 + CONTENT/BT/MODELS/WNDSFX01.MOD | 5 + CONTENT/BT/MODELS/WNDSFX02.MOD | 5 + CONTENT/BT/MODELS/WNDSFX03.MOD | 5 + CONTENT/BT/MODELS/WOLF.MOD | 2 + CONTENT/BT/MODELS/WPN.BLD | 64 + CONTENT/BT/MODELS/WPNDMG.TBL | 47 + CONTENT/BT/MODELS/WPNMECH.MOD | 127 + CONTENT/BT/MODELS/WPNMECH.SUB | 186 + CONTENT/BT/MODELS/WST.MOD | 20 + CONTENT/BT/NEWSTUFF.BLD | 21 + CONTENT/BT/NULL | 24 + CONTENT/BT/OMECH.BLD | 180 + CONTENT/BT/RESULT2.TXT | 22 + CONTENT/BT/SHOWENV.BAT | 12 + CONTENT/BT/SOLIDS/AB01_CV.SLD | 113 + CONTENT/BT/SOLIDS/AB02_CV.SLD | 113 + CONTENT/BT/SOLIDS/AB03_CV.SLD | 155 + CONTENT/BT/SOLIDS/AB04_CV.SLD | 155 + CONTENT/BT/SOLIDS/AB05_CV.SLD | 113 + CONTENT/BT/SOLIDS/AB06_CV.SLD | 260 + CONTENT/BT/SOLIDS/AB07_CV.SLD | 218 + CONTENT/BT/SOLIDS/AB09_CV.SLD | 197 + CONTENT/BT/SOLIDS/AB10_CV.SLD | 302 + CONTENT/BT/SOLIDS/ADWLK1~1.SLD | 50 + CONTENT/BT/SOLIDS/ADWLK2~1.SLD | 50 + CONTENT/BT/SOLIDS/ADWLK3~1.SLD | 29 + CONTENT/BT/SOLIDS/APC.SLD | 50 + CONTENT/BT/SOLIDS/AR01_CV.SLD | 323 + CONTENT/BT/SOLIDS/AR02_CV.SLD | 29 + CONTENT/BT/SOLIDS/AR03_CV.SLD | 197 + CONTENT/BT/SOLIDS/AR04_CV.SLD | 197 + CONTENT/BT/SOLIDS/AR05_CV.SLD | 239 + CONTENT/BT/SOLIDS/ARBAN_CV.SLD | 29 + CONTENT/BT/SOLIDS/ARENA1.XST | 17 + CONTENT/BT/SOLIDS/ARENA2.XST | 17 + CONTENT/BT/SOLIDS/ARENA3.XST | 17 + CONTENT/BT/SOLIDS/ARLID_CV.SLD | 28 + CONTENT/BT/SOLIDS/ARMRMOVR.SLD | 29 + CONTENT/BT/SOLIDS/ARTRUCKS.XST | 17 + CONTENT/BT/SOLIDS/AVA_CV.SLD | 30 + CONTENT/BT/SOLIDS/AW03_CV.SLD | 29 + CONTENT/BT/SOLIDS/AW05_CV.SLD | 50 + CONTENT/BT/SOLIDS/AWBOX_CV.SLD | 71 + CONTENT/BT/SOLIDS/BAC1_CV.SLD | 50 + CONTENT/BT/SOLIDS/BCOR1_CV.SLD | 29 + CONTENT/BT/SOLIDS/BCOR2_CV.SLD | 29 + CONTENT/BT/SOLIDS/BDET4_CV.SLD | 50 + CONTENT/BT/SOLIDS/BLANK.XST | 17 + CONTENT/BT/SOLIDS/BLD03_CV.SLD | 71 + CONTENT/BT/SOLIDS/BLD04_CV.SLD | 71 + CONTENT/BT/SOLIDS/BLD06_CV.SLD | 155 + CONTENT/BT/SOLIDS/BLD20_CV.SLD | 92 + CONTENT/BT/SOLIDS/BLD24_CV.SLD | 50 + CONTENT/BT/SOLIDS/BLD26_CV.SLD | 29 + CONTENT/BT/SOLIDS/BLD27_CV.SLD | 155 + CONTENT/BT/SOLIDS/BLH_CV.SLD | 30 + CONTENT/BT/SOLIDS/BNK_CV.SLD | 29 + CONTENT/BT/SOLIDS/BPIP1_CV.SLD | 29 + CONTENT/BT/SOLIDS/BULLDOG.SLD | 29 + CONTENT/BT/SOLIDS/BUTTEA_C.SLD | 92 + CONTENT/BT/SOLIDS/BUTTEB_C.SLD | 113 + CONTENT/BT/SOLIDS/BUTTEC_C.SLD | 113 + CONTENT/BT/SOLIDS/BUTTED_C.SLD | 92 + CONTENT/BT/SOLIDS/BUTTEE_C.SLD | 113 + CONTENT/BT/SOLIDS/BWLK1_CV.SLD | 29 + CONTENT/BT/SOLIDS/CALPB_CV.SLD | 113 + CONTENT/BT/SOLIDS/CALP_CV.SLD | 155 + CONTENT/BT/SOLIDS/CAVERN.XST | 16 + CONTENT/BT/SOLIDS/CITY1.XST | 15 + CONTENT/BT/SOLIDS/COMTRUCK.SLD | 50 + CONTENT/BT/SOLIDS/COOLANT.SLD | 71 + CONTENT/BT/SOLIDS/CRT_CV.SLD | 29 + CONTENT/BT/SOLIDS/DBASE.XST | 18 + CONTENT/BT/SOLIDS/DES.XST | 17 + CONTENT/BT/SOLIDS/DISH_CV.SLD | 92 + CONTENT/BT/SOLIDS/DOZER.SLD | 50 + CONTENT/BT/SOLIDS/FIR_CV.SLD | 29 + CONTENT/BT/SOLIDS/FL1_CV.SLD | 29 + CONTENT/BT/SOLIDS/FP1_CV.SLD | 197 + CONTENT/BT/SOLIDS/FP2D_CV.SLD | 29 + CONTENT/BT/SOLIDS/FP2_CV.SLD | 29 + CONTENT/BT/SOLIDS/FP3_CV.SLD | 29 + CONTENT/BT/SOLIDS/FRSTRM.XST | 17 + CONTENT/BT/SOLIDS/FT1_CV.SLD | 29 + CONTENT/BT/SOLIDS/FT2_CV.SLD | 29 + CONTENT/BT/SOLIDS/GD1_CV.SLD | 71 + CONTENT/BT/SOLIDS/GD2_CV.SLD | 92 + CONTENT/BT/SOLIDS/GD3_CV.SLD | 29 + CONTENT/BT/SOLIDS/GD4_CV.SLD | 29 + CONTENT/BT/SOLIDS/GD5_CV.SLD | 29 + CONTENT/BT/SOLIDS/GNR_CV.SLD | 29 + CONTENT/BT/SOLIDS/GR100ACV.SLD | 29 + CONTENT/BT/SOLIDS/GR100COL.SLD | 29 + CONTENT/BT/SOLIDS/GR100_CV.SLD | 29 + CONTENT/BT/SOLIDS/GRASS.XST | 17 + CONTENT/BT/SOLIDS/HARASSER.SLD | 29 + CONTENT/BT/SOLIDS/HC1_CV.SLD | 92 + CONTENT/BT/SOLIDS/HC2_CV.SLD | 71 + CONTENT/BT/SOLIDS/HILLA_CV.SLD | 29 + CONTENT/BT/SOLIDS/HILLB_CV.SLD | 29 + CONTENT/BT/SOLIDS/HILLC_CV.SLD | 50 + CONTENT/BT/SOLIDS/HILLG1CO.SLD | 71 + CONTENT/BT/SOLIDS/HILLG1_C.SLD | 71 + CONTENT/BT/SOLIDS/HILLG2CO.SLD | 50 + CONTENT/BT/SOLIDS/HILLG2_C.SLD | 50 + CONTENT/BT/SOLIDS/HILLG3CO.SLD | 50 + CONTENT/BT/SOLIDS/HILLG3_C.SLD | 50 + CONTENT/BT/SOLIDS/HL1_CV.SLD | 113 + CONTENT/BT/SOLIDS/HL2_CV.SLD | 239 + CONTENT/BT/SOLIDS/HN1_CV.SLD | 29 + CONTENT/BT/SOLIDS/HUMMER.SLD | 50 + CONTENT/BT/SOLIDS/HUT_CV.SLD | 71 + CONTENT/BT/SOLIDS/HWZ_CV.SLD | 113 + CONTENT/BT/SOLIDS/JAK_CV.SLD | 29 + CONTENT/BT/SOLIDS/JAX1_CV.SLD | 29 + CONTENT/BT/SOLIDS/JAX2_CV.SLD | 29 + CONTENT/BT/SOLIDS/LOK_CV.SLD | 30 + CONTENT/BT/SOLIDS/LRMCARRY.SLD | 29 + CONTENT/BT/SOLIDS/MAD_CV.SLD | 30 + CONTENT/BT/SOLIDS/MECHMOVR.SLD | 71 + CONTENT/BT/SOLIDS/MSLBS_CV.SLD | 29 + CONTENT/BT/SOLIDS/MSLG_CV.SLD | 50 + CONTENT/BT/SOLIDS/MSLH_CV.SLD | 29 + CONTENT/BT/SOLIDS/MSLRB_CV.SLD | 29 + CONTENT/BT/SOLIDS/MSLR_CV.SLD | 29 + CONTENT/BT/SOLIDS/MSL_CV.SLD | 29 + CONTENT/BT/SOLIDS/OWN_CV.SLD | 30 + CONTENT/BT/SOLIDS/PDSH_CV.SLD | 29 + CONTENT/BT/SOLIDS/PGN_CV.SLD | 29 + CONTENT/BT/SOLIDS/PLIT_CV.SLD | 29 + CONTENT/BT/SOLIDS/POLAR1.XST | 17 + CONTENT/BT/SOLIDS/POLAR2.XST | 17 + CONTENT/BT/SOLIDS/POLAR3.XST | 17 + CONTENT/BT/SOLIDS/POLAR4.XST | 17 + CONTENT/BT/SOLIDS/RAP_CV.SLD | 29 + CONTENT/BT/SOLIDS/RAV.XST | 17 + CONTENT/BT/SOLIDS/RAV1.XST | 17 + CONTENT/BT/SOLIDS/RFLOOR.SLD | 30 + CONTENT/BT/SOLIDS/RFLOOR_C.SLD | 30 + CONTENT/BT/SOLIDS/RK2_CV.SLD | 281 + CONTENT/BT/SOLIDS/RK4_CV.SLD | 197 + CONTENT/BT/SOLIDS/RK5_CV.SLD | 92 + CONTENT/BT/SOLIDS/RK6_CV.SLD | 50 + CONTENT/BT/SOLIDS/RK7_CV.SLD | 113 + CONTENT/BT/SOLIDS/ROMMEL.SLD | 29 + CONTENT/BT/SOLIDS/SAW_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB1B_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB1C_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB1D_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB1E_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB1N_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB1S_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB1W_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB1_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB2B_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB2C_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB2D_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB2E_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB2N_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB2S_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB2W_CV.SLD | 50 + CONTENT/BT/SOLIDS/SB2_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB3E_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB3N_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB3S_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB3W_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB4E_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB4N_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB4S_CV.SLD | 29 + CONTENT/BT/SOLIDS/SB4W_CV.SLD | 29 + CONTENT/BT/SOLIDS/SEMI.SLD | 50 + CONTENT/BT/SOLIDS/SEMIRIG.SLD | 71 + CONTENT/BT/SOLIDS/SL2_CV.SLD | 29 + CONTENT/BT/SOLIDS/SN1_CV.SLD | 29 + CONTENT/BT/SOLIDS/SND_CV.SLD | 30 + CONTENT/BT/SOLIDS/SNH_CV.SLD | 29 + CONTENT/BT/SOLIDS/SR1E_CV.SLD | 50 + CONTENT/BT/SOLIDS/SR1N_CV.SLD | 50 + CONTENT/BT/SOLIDS/SR1S_CV.SLD | 50 + CONTENT/BT/SOLIDS/SR1W_CV.SLD | 50 + CONTENT/BT/SOLIDS/SRC1NE_C.SLD | 72 + CONTENT/BT/SOLIDS/SRC1NW_C.SLD | 72 + CONTENT/BT/SOLIDS/SRC1SE_C.SLD | 72 + CONTENT/BT/SOLIDS/SRC1SW_C.SLD | 72 + CONTENT/BT/SOLIDS/SRMCARRY.SLD | 50 + CONTENT/BT/SOLIDS/ST1_CV.SLD | 29 + CONTENT/BT/SOLIDS/STATE.RST | 12 + CONTENT/BT/SOLIDS/STB_CV.SLD | 50 + CONTENT/BT/SOLIDS/STF_CV.SLD | 113 + CONTENT/BT/SOLIDS/STH_CV.SLD | 344 + CONTENT/BT/SOLIDS/STI_CV.SLD | 29 + CONTENT/BT/SOLIDS/STRIKER.SLD | 71 + CONTENT/BT/SOLIDS/STS_CV.SLD | 71 + CONTENT/BT/SOLIDS/SV2B_CV.SLD | 113 + CONTENT/BT/SOLIDS/SV2C_CV.SLD | 92 + CONTENT/BT/SOLIDS/SV2D_CV.SLD | 92 + CONTENT/BT/SOLIDS/SV2_CV.SLD | 113 + CONTENT/BT/SOLIDS/SV3B_CV.SLD | 176 + CONTENT/BT/SOLIDS/SV3C_CV.SLD | 113 + CONTENT/BT/SOLIDS/SV3D_CV.SLD | 134 + CONTENT/BT/SOLIDS/SV3_CV.SLD | 155 + CONTENT/BT/SOLIDS/SW1_CV.SLD | 50 + CONTENT/BT/SOLIDS/SW2_CV.SLD | 50 + CONTENT/BT/SOLIDS/SW3_CV.SLD | 29 + CONTENT/BT/SOLIDS/SW4_CV.SLD | 50 + CONTENT/BT/SOLIDS/SW5_CV.SLD | 50 + CONTENT/BT/SOLIDS/SW6_CV.SLD | 29 + CONTENT/BT/SOLIDS/SWIFTWND.SLD | 50 + CONTENT/BT/SOLIDS/TEST.XST | 18 + CONTENT/BT/SOLIDS/THR_CV.SLD | 30 + CONTENT/BT/SOLIDS/TK1_CV.SLD | 29 + CONTENT/BT/SOLIDS/TNT_CV.SLD | 29 + CONTENT/BT/SOLIDS/TREE_CV.SLD | 29 + CONTENT/BT/SOLIDS/TRK1_CV.SLD | 50 + CONTENT/BT/SOLIDS/TRK3_CV.SLD | 50 + CONTENT/BT/SOLIDS/TRK4_CV.SLD | 50 + CONTENT/BT/SOLIDS/TT1_CV.SLD | 92 + CONTENT/BT/SOLIDS/TT2_CV.SLD | 92 + CONTENT/BT/SOLIDS/TWR_CV.SLD | 29 + CONTENT/BT/SOLIDS/VUL_CV.SLD | 30 + CONTENT/BT/SOLIDS/WALL10K.SLD | 93 + CONTENT/BT/SOLIDS/WALL1_CV.SLD | 218 + CONTENT/BT/SOLIDS/WALL2_CV.SLD | 218 + CONTENT/BT/SOLIDS/WL1_CV.SLD | 386 + CONTENT/BT/SOLIDS/WL2_CV.SLD | 92 + CONTENT/BT/SOLIDS/WL3_CV.SLD | 386 + CONTENT/BT/SOLIDS/WL4_CV.SLD | 113 + CONTENT/BT/SOLIDS/WL5_CV.SLD | 155 + CONTENT/BT/SOLIDS/WL6_CV.SLD | 155 + CONTENT/BT/SOLIDS/WL7_CV.SLD | 176 + CONTENT/BT/SOLIDS/WL8_CV.SLD | 302 + CONTENT/BT/SOLIDS/WL9_CV.SLD | 50 + CONTENT/BT/SOLIDS/WST_CV.SLD | 92 + CONTENT/BT/TEST.BAT | 48 + CONTENT/BT/VIDEO/AUTOARM.SKL | 116 + CONTENT/BT/VIDEO/AUTODARM.SKL | 116 + CONTENT/BT/VIDEO/AVA2SKIN.DZM | 85 + CONTENT/BT/VIDEO/AVASKIN.DZM | 88 + CONTENT/BT/VIDEO/AVX2SKIN.DZM | 5 + CONTENT/BT/VIDEO/AVXSKIN.DZM | 5 + CONTENT/BT/VIDEO/BATSKIN.DZM | 93 + CONTENT/BT/VIDEO/BAXSKIN.DZM | 2 + CONTENT/BT/VIDEO/BLHSKIN.DZM | 87 + CONTENT/BT/VIDEO/BLXSKIN.DZM | 6 + CONTENT/BT/VIDEO/BUILD/APCS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/APCS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/ARMRS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/ARMRS.VGF | 39 + CONTENT/BT/VIDEO/BUILD/BACKUP/GRASS.VMF | 82 + CONTENT/BT/VIDEO/BUILD/BASEV.BMF | Bin 0 -> 2942 bytes CONTENT/BT/VIDEO/BUILD/BASEV.BSL | Bin 0 -> 32886 bytes CONTENT/BT/VIDEO/BUILD/BLD03.BGF | Bin 0 -> 4813 bytes CONTENT/BT/VIDEO/BUILD/BLD03_L0.BGF | Bin 0 -> 2862 bytes CONTENT/BT/VIDEO/BUILD/BLD04.BGF | Bin 0 -> 4960 bytes CONTENT/BT/VIDEO/BUILD/BLD08_LP.VGF | 75 + CONTENT/BT/VIDEO/BUILD/BLD24.BGF | Bin 0 -> 3837 bytes CONTENT/BT/VIDEO/BUILD/BLD26.BGF | Bin 0 -> 3734 bytes CONTENT/BT/VIDEO/BUILD/BLD26D.BGF | Bin 0 -> 3961 bytes CONTENT/BT/VIDEO/BUILD/BUILDBAS.BAT | 18 + CONTENT/BT/VIDEO/BUILD/BUILDGEN.BAT | 18 + CONTENT/BT/VIDEO/BUILD/BUILDLGO.BAT | 18 + CONTENT/BT/VIDEO/BUILD/BUILDTEX.BAT | 20 + CONTENT/BT/VIDEO/BUILD/BULLS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/BULLS.VGF | 39 + CONTENT/BT/VIDEO/BUILD/CALIOPE.BMF | Bin 0 -> 2413 bytes CONTENT/BT/VIDEO/BUILD/CALP.BGF | Bin 0 -> 29580 bytes CONTENT/BT/VIDEO/BUILD/CALPD.BGF | Bin 0 -> 3424 bytes CONTENT/BT/VIDEO/BUILD/CALP_LP.VGF | 49 + CONTENT/BT/VIDEO/BUILD/COMS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/COMS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/COOLS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/COOLS.VGF | 39 + CONTENT/BT/VIDEO/BUILD/CTAR_LP.VGF | 114 + CONTENT/BT/VIDEO/BUILD/DBASE.BMF | Bin 0 -> 1574 bytes CONTENT/BT/VIDEO/BUILD/DBASE.VMF | 266 + CONTENT/BT/VIDEO/BUILD/DCLOUDS.BGF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/BUILD/DISH.BGF | Bin 0 -> 4736 bytes CONTENT/BT/VIDEO/BUILD/DISH.BMF | Bin 0 -> 2655 bytes CONTENT/BT/VIDEO/BUILD/DISH_LP.VGF | 36 + CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/APCS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/ARMRS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/BASEV.BMF | Bin 0 -> 2880 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/BTRAVWIN.BMF | Bin 0 -> 801 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/BULLS.BGF | Bin 0 -> 204 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/CALIOPE.BMF | Bin 0 -> 2413 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/COMS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/COOLS.BGF | Bin 0 -> 204 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/DCLOUDS.BGF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/DISH.BGF | Bin 0 -> 4736 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/DOZERS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/GRASS.BMF | Bin 0 -> 381 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/HARASS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/HUMMS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/LRMS.BGF | Bin 0 -> 344 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/MECHMOVS.BGF | Bin 0 -> 268 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/RAVFLOOR.BGF | Bin 0 -> 4349 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 230 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/ROMMELS.BGF | Bin 0 -> 268 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/SEMIRIGS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/SEMIS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/SRMS.BGF | Bin 0 -> 268 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/STRIKERS.BGF | Bin 0 -> 268 bytes .../BT/VIDEO/BUILD/DIVISION.SAV/SWIFTS.BGF | Bin 0 -> 395 bytes CONTENT/BT/VIDEO/BUILD/DOZERS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/DOZERS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/DTAR_LP.VGF | 93 + CONTENT/BT/VIDEO/BUILD/EDITBACK/BLD08_LP.VGF | 74 + CONTENT/BT/VIDEO/BUILD/EDITBACK/BTRAVWIN.VMF | 154 + CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDBAS.BAT | 18 + CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDGEN.BAT | 18 + CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDLGO.BAT | 19 + CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDTEX.BAT | 20 + CONTENT/BT/VIDEO/BUILD/EDITBACK/CALP_LP.VGF | 48 + CONTENT/BT/VIDEO/BUILD/EDITBACK/CTAR_LP.VGF | 113 + CONTENT/BT/VIDEO/BUILD/EDITBACK/DBASE.VMF | 266 + CONTENT/BT/VIDEO/BUILD/EDITBACK/DISH_LP.VGF | 35 + CONTENT/BT/VIDEO/BUILD/EDITBACK/DTAR_LP.VGF | 92 + CONTENT/BT/VIDEO/BUILD/EDITBACK/GRASS.VMF | 69 + CONTENT/BT/VIDEO/BUILD/EDITBACK/RAVINES.VMF | 62 + CONTENT/BT/VIDEO/BUILD/GEN5.TGA | Bin 0 -> 49488 bytes CONTENT/BT/VIDEO/BUILD/GEN6.TGA | Bin 0 -> 49488 bytes CONTENT/BT/VIDEO/BUILD/GRASS.BMF | Bin 0 -> 441 bytes CONTENT/BT/VIDEO/BUILD/GRASS.VMF | 69 + CONTENT/BT/VIDEO/BUILD/HARASS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/HARASS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/HUMMS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/HUMMS.VGF | 39 + CONTENT/BT/VIDEO/BUILD/LRMS.BGF | Bin 0 -> 344 bytes CONTENT/BT/VIDEO/BUILD/LRMS.VGF | 51 + CONTENT/BT/VIDEO/BUILD/MECHMOVS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/MECHMOVS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/BUILD/RAVINES.VMF | 62 + CONTENT/BT/VIDEO/BUILD/ROMMELS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/ROMMELS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/SEMIRIGS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/SEMIRIGS.VGF | 39 + CONTENT/BT/VIDEO/BUILD/SEMIS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/BUILD/SEMIS.VGF | 39 + CONTENT/BT/VIDEO/BUILD/SRMS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/SRMS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/STATE.RST | 64 + CONTENT/BT/VIDEO/BUILD/STRIKERS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/BUILD/STRIKERS.VGF | 44 + CONTENT/BT/VIDEO/BUILD/SWIFTS.BGF | Bin 0 -> 395 bytes CONTENT/BT/VIDEO/BUILD/SWIFTS.VGF | 55 + CONTENT/BT/VIDEO/DAFC.PFX | 32 + CONTENT/BT/VIDEO/DBIGBOOM.PFX | 33 + CONTENT/BT/VIDEO/DDAM1.PFX | 32 + CONTENT/BT/VIDEO/DDAM2.PFX | 32 + CONTENT/BT/VIDEO/DDAM3.PFX | 32 + CONTENT/BT/VIDEO/DDAM4.PFX | 32 + CONTENT/BT/VIDEO/DDAM5.PFX | 33 + CONTENT/BT/VIDEO/DDTHSMK.PFX | 32 + CONTENT/BT/VIDEO/DLRMTAIL.PFX | 33 + CONTENT/BT/VIDEO/DMEDBOOM.PFX | 33 + CONTENT/BT/VIDEO/DMISSING.PFX | 33 + CONTENT/BT/VIDEO/DNBOOM.PFX | 33 + CONTENT/BT/VIDEO/DSMLBOOM.PFX | 33 + CONTENT/BT/VIDEO/DSRM.PFX | 33 + CONTENT/BT/VIDEO/DTRKBOOM.PFX | 33 + CONTENT/BT/VIDEO/DTRKBURN.PFX | 32 + CONTENT/BT/VIDEO/FIRSKIN.DZM | 90 + CONTENT/BT/VIDEO/FIRXSKIN.DZM | 3 + CONTENT/BT/VIDEO/FLUSH.PFX | 33 + CONTENT/BT/VIDEO/GEO/AB01.BGF | Bin 0 -> 5000 bytes CONTENT/BT/VIDEO/GEO/AB02.BGF | Bin 0 -> 3079 bytes CONTENT/BT/VIDEO/GEO/AB04.BGF | Bin 0 -> 4677 bytes CONTENT/BT/VIDEO/GEO/AB05.BGF | Bin 0 -> 3912 bytes CONTENT/BT/VIDEO/GEO/AB06D_FR.BGF | Bin 0 -> 2780 bytes CONTENT/BT/VIDEO/GEO/AB07.BGF | Bin 0 -> 3693 bytes CONTENT/BT/VIDEO/GEO/AB07D_FR.BGF | Bin 0 -> 1636 bytes CONTENT/BT/VIDEO/GEO/AB08.BGF | Bin 0 -> 2476 bytes CONTENT/BT/VIDEO/GEO/AB09D_FR.BGF | Bin 0 -> 1896 bytes CONTENT/BT/VIDEO/GEO/AB10D_FR.BGF | Bin 0 -> 1645 bytes CONTENT/BT/VIDEO/GEO/ABG.BGF | Bin 0 -> 249 bytes CONTENT/BT/VIDEO/GEO/ACT01.BGF | Bin 0 -> 776 bytes CONTENT/BT/VIDEO/GEO/ACT02.BGF | Bin 0 -> 655 bytes CONTENT/BT/VIDEO/GEO/ACT03.BGF | Bin 0 -> 677 bytes CONTENT/BT/VIDEO/GEO/ACT04.BGF | Bin 0 -> 1243 bytes CONTENT/BT/VIDEO/GEO/ACT05.BGF | Bin 0 -> 839 bytes CONTENT/BT/VIDEO/GEO/ADSUP1.BGF | Bin 0 -> 571 bytes CONTENT/BT/VIDEO/GEO/ADSUP2.BGF | Bin 0 -> 327 bytes CONTENT/BT/VIDEO/GEO/ADWLK1.BGF | Bin 0 -> 948 bytes CONTENT/BT/VIDEO/GEO/ADWLK2.BGF | Bin 0 -> 974 bytes CONTENT/BT/VIDEO/GEO/ADWLK3.BGF | Bin 0 -> 562 bytes CONTENT/BT/VIDEO/GEO/AFLOOR.BGF | Bin 0 -> 3870 bytes CONTENT/BT/VIDEO/GEO/APCS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/AR01_FR.BGF | Bin 0 -> 993 bytes CONTENT/BT/VIDEO/GEO/AR02_FR.BGF | Bin 0 -> 4213 bytes CONTENT/BT/VIDEO/GEO/AR03_FR.BGF | Bin 0 -> 935 bytes CONTENT/BT/VIDEO/GEO/AR04_FR.BGF | Bin 0 -> 1162 bytes CONTENT/BT/VIDEO/GEO/AR05_FR.BGF | Bin 0 -> 2917 bytes CONTENT/BT/VIDEO/GEO/ARBAN1.BGF | Bin 0 -> 2282 bytes CONTENT/BT/VIDEO/GEO/ARBAN2.BGF | Bin 0 -> 2281 bytes CONTENT/BT/VIDEO/GEO/ARBAN3.BGF | Bin 0 -> 2285 bytes CONTENT/BT/VIDEO/GEO/ARBAN4.BGF | Bin 0 -> 2284 bytes CONTENT/BT/VIDEO/GEO/ARBAN5.BGF | Bin 0 -> 2284 bytes CONTENT/BT/VIDEO/GEO/ARBAN6.BGF | Bin 0 -> 2281 bytes CONTENT/BT/VIDEO/GEO/ARCLD.BGF | Bin 0 -> 526 bytes CONTENT/BT/VIDEO/GEO/ARENA/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT/VIDEO/GEO/ARENA/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT/VIDEO/GEO/ARENA/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/ARENA/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT/VIDEO/GEO/ARENA/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT/VIDEO/GEO/ARENA/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/ARENA/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/ARENA/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT/VIDEO/GEO/ARENA/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/ARENA/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/ARENA/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT/VIDEO/GEO/ARENA3/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT/VIDEO/GEO/ARENA3/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT/VIDEO/GEO/ARENA3/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/ARENA3/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT/VIDEO/GEO/ARENA3/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT/VIDEO/GEO/ARENA3/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/ARENA3/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/ARENA3/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT/VIDEO/GEO/ARENA3/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/ARENA3/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/ARENA3/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT/VIDEO/GEO/ARHORIZ.BGF | Bin 0 -> 604 bytes CONTENT/BT/VIDEO/GEO/ARLID.BGF | Bin 0 -> 529 bytes CONTENT/BT/VIDEO/GEO/ARMRS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/ARTCGRND.BGF | Bin 0 -> 2835 bytes CONTENT/BT/VIDEO/GEO/AVADLARM.BGF | Bin 0 -> 2914 bytes CONTENT/BT/VIDEO/GEO/AVADLGUN.BGF | Bin 0 -> 4340 bytes CONTENT/BT/VIDEO/GEO/AVADRARM.BGF | Bin 0 -> 3859 bytes CONTENT/BT/VIDEO/GEO/AVADRGUN.BGF | Bin 0 -> 3294 bytes CONTENT/BT/VIDEO/GEO/AVA_HIP.BGF | Bin 0 -> 2655 bytes CONTENT/BT/VIDEO/GEO/AVA_LARM.BGF | Bin 0 -> 4725 bytes CONTENT/BT/VIDEO/GEO/AVA_LBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/AVA_LDOO.BGF | Bin 0 -> 1383 bytes CONTENT/BT/VIDEO/GEO/AVA_LFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT/VIDEO/GEO/AVA_LGUN.BGF | Bin 0 -> 5053 bytes CONTENT/BT/VIDEO/GEO/AVA_LITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/AVA_LOTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/AVA_RARM.BGF | Bin 0 -> 5087 bytes CONTENT/BT/VIDEO/GEO/AVA_RBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/AVA_RDOO.BGF | Bin 0 -> 1383 bytes CONTENT/BT/VIDEO/GEO/AVA_RFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT/VIDEO/GEO/AVA_RITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/AVA_ROTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/AVX_COP.BGF | Bin 0 -> 4667 bytes CONTENT/BT/VIDEO/GEO/AVX_TOR.BGF | Bin 0 -> 1434 bytes CONTENT/BT/VIDEO/GEO/AW01.BGF | Bin 0 -> 863 bytes CONTENT/BT/VIDEO/GEO/AW02.BGF | Bin 0 -> 868 bytes CONTENT/BT/VIDEO/GEO/AW03.BGF | Bin 0 -> 371 bytes CONTENT/BT/VIDEO/GEO/AW05.BGF | Bin 0 -> 1160 bytes CONTENT/BT/VIDEO/GEO/AWBOX1.BGF | Bin 0 -> 567 bytes CONTENT/BT/VIDEO/GEO/AWWLK1.BGF | Bin 0 -> 618 bytes CONTENT/BT/VIDEO/GEO/BAC1.BGF | Bin 0 -> 868 bytes CONTENT/BT/VIDEO/GEO/BALL1.BGF | Bin 0 -> 1597 bytes CONTENT/BT/VIDEO/GEO/BALL2.BGF | Bin 0 -> 1316 bytes CONTENT/BT/VIDEO/GEO/BALL3.BGF | Bin 0 -> 1316 bytes CONTENT/BT/VIDEO/GEO/BALL4.BGF | Bin 0 -> 1316 bytes CONTENT/BT/VIDEO/GEO/BBG.BGF | Bin 0 -> 256 bytes CONTENT/BT/VIDEO/GEO/BCOR1.BGF | Bin 0 -> 1965 bytes CONTENT/BT/VIDEO/GEO/BCOR2.BGF | Bin 0 -> 2125 bytes CONTENT/BT/VIDEO/GEO/BDET1.BGF | Bin 0 -> 898 bytes CONTENT/BT/VIDEO/GEO/BDET2.BGF | Bin 0 -> 634 bytes CONTENT/BT/VIDEO/GEO/BDET3.BGF | Bin 0 -> 1191 bytes CONTENT/BT/VIDEO/GEO/BDET4.BGF | Bin 0 -> 838 bytes CONTENT/BT/VIDEO/GEO/BDET6.BGF | Bin 0 -> 571 bytes CONTENT/BT/VIDEO/GEO/BLD03.BGF | Bin 0 -> 4813 bytes CONTENT/BT/VIDEO/GEO/BLD04.BGF | Bin 0 -> 4960 bytes CONTENT/BT/VIDEO/GEO/BLD08_LP.BGF | Bin 0 -> 750 bytes CONTENT/BT/VIDEO/GEO/BLD24.BGF | Bin 0 -> 3837 bytes CONTENT/BT/VIDEO/GEO/BLD26.BGF | Bin 0 -> 3734 bytes CONTENT/BT/VIDEO/GEO/BLD26D.BGF | Bin 0 -> 3961 bytes CONTENT/BT/VIDEO/GEO/BLHDLARM.BGF | Bin 0 -> 2346 bytes CONTENT/BT/VIDEO/GEO/BLHDLGUN.BGF | Bin 0 -> 3834 bytes CONTENT/BT/VIDEO/GEO/BLHDRARM.BGF | Bin 0 -> 2346 bytes CONTENT/BT/VIDEO/GEO/BLHDRGUN.BGF | Bin 0 -> 3753 bytes CONTENT/BT/VIDEO/GEO/BLH_LARM.BGF | Bin 0 -> 4044 bytes CONTENT/BT/VIDEO/GEO/BLH_LFOT.BGF | Bin 0 -> 3641 bytes CONTENT/BT/VIDEO/GEO/BLH_LULE.BGF | Bin 0 -> 4726 bytes CONTENT/BT/VIDEO/GEO/BLH_RARM.BGF | Bin 0 -> 4044 bytes CONTENT/BT/VIDEO/GEO/BLH_RFOT.BGF | Bin 0 -> 3641 bytes CONTENT/BT/VIDEO/GEO/BLH_RULE.BGF | Bin 0 -> 4726 bytes CONTENT/BT/VIDEO/GEO/BLUEBEAM.BGF | Bin 0 -> 2300 bytes CONTENT/BT/VIDEO/GEO/BNKD_FR.BGF | Bin 0 -> 1665 bytes CONTENT/BT/VIDEO/GEO/BNK_FR.BGF | Bin 0 -> 735 bytes CONTENT/BT/VIDEO/GEO/BNK_LP.BGF | Bin 0 -> 252 bytes CONTENT/BT/VIDEO/GEO/BPIP1.BGF | Bin 0 -> 627 bytes CONTENT/BT/VIDEO/GEO/BPIP1D.BGF | Bin 0 -> 1983 bytes CONTENT/BT/VIDEO/GEO/BULLET.BGF | Bin 0 -> 285 bytes CONTENT/BT/VIDEO/GEO/BULLS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/BUTTEF.BGF | Bin 0 -> 4248 bytes CONTENT/BT/VIDEO/GEO/BWLK1.BGF | Bin 0 -> 634 bytes CONTENT/BT/VIDEO/GEO/CALPD.BGF | Bin 0 -> 3424 bytes CONTENT/BT/VIDEO/GEO/CALP_LP.BGF | Bin 0 -> 330 bytes CONTENT/BT/VIDEO/GEO/CAMPOS.BGF | Bin 0 -> 1224 bytes CONTENT/BT/VIDEO/GEO/CAVERN/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT/VIDEO/GEO/CAVERN/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT/VIDEO/GEO/CAVERN/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/CAVERN/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT/VIDEO/GEO/CAVERN/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT/VIDEO/GEO/CAVERN/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/CAVERN/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/CAVERN/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT/VIDEO/GEO/CAVERN/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/CAVERN/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/CAVERN/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT/VIDEO/GEO/CB1.BGF | Bin 0 -> 3301 bytes CONTENT/BT/VIDEO/GEO/CB2.BGF | Bin 0 -> 3739 bytes CONTENT/BT/VIDEO/GEO/CH1.BGF | Bin 0 -> 395 bytes CONTENT/BT/VIDEO/GEO/CH2.BGF | Bin 0 -> 327 bytes CONTENT/BT/VIDEO/GEO/COMS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/COOLS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/CRTD_FR.BGF | Bin 0 -> 954 bytes CONTENT/BT/VIDEO/GEO/CTAR_LP.BGF | Bin 0 -> 1379 bytes CONTENT/BT/VIDEO/GEO/D1DIRT.BGF | Bin 0 -> 2086 bytes .../BT/VIDEO/GEO/DAY/DIVISION.SAV/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/GEO/DAY/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/GEO/DAY/DSKY.BMF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/GEO/DAY/DSKY.VGF | 102 + CONTENT/BT/VIDEO/GEO/DAY/SKY.BGF | Bin 0 -> 4547 bytes CONTENT/BT/VIDEO/GEO/DAY/SKY.VGF | 267 + CONTENT/BT/VIDEO/GEO/DAY/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT/VIDEO/GEO/DECLOUDS.BGF | Bin 0 -> 797 bytes CONTENT/BT/VIDEO/GEO/DISHD.BGF | Bin 0 -> 13292 bytes CONTENT/BT/VIDEO/GEO/DISH_LP.BGF | Bin 0 -> 216 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/ARMRS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD03.BGF | Bin 0 -> 4813 bytes .../BT/VIDEO/GEO/DIVISION.SAV/BLD03_L0.BGF | Bin 0 -> 2862 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD04.BGF | Bin 0 -> 4960 bytes .../BT/VIDEO/GEO/DIVISION.SAV/BLD08_LP.BGF | Bin 0 -> 753 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD24.BGF | Bin 0 -> 3919 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD26.BGF | Bin 0 -> 3734 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD26D.BGF | Bin 0 -> 3961 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/CALPD.BGF | Bin 0 -> 3813 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/CALP_LP.BGF | Bin 0 -> 332 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/COMS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/CTAR_LP.BGF | Bin 0 -> 1380 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/D1DIRT.BGF | Bin 0 -> 2086 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/DISH_LP.BGF | Bin 0 -> 217 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/DTAR_LP.BGF | Bin 0 -> 1041 bytes .../BT/VIDEO/GEO/DIVISION.SAV/RAVFLOOR.BGF | Bin 0 -> 807 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/RAVINE0.BGF | Bin 0 -> 4563 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 322 bytes .../BT/VIDEO/GEO/DIVISION.SAV/SEMIRIGS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TREE.BGF | Bin 0 -> 2761 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TREESH.BGF | Bin 0 -> 291 bytes CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TRUNK.BGF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/GEO/DOZERS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/DTAR_LP.BGF | Bin 0 -> 1040 bytes CONTENT/BT/VIDEO/GEO/ERMLASER.BGF | Bin 0 -> 4176 bytes CONTENT/BT/VIDEO/GEO/EVENING/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/GEO/EVENING/SKY.BGF | Bin 0 -> 539 bytes CONTENT/BT/VIDEO/GEO/EVENING/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT/VIDEO/GEO/EVENING/SPOT.BU | Bin 0 -> 522 bytes CONTENT/BT/VIDEO/GEO/EXDISK_A.BGF | Bin 0 -> 2085 bytes CONTENT/BT/VIDEO/GEO/EXDISK_B.BGF | Bin 0 -> 2085 bytes CONTENT/BT/VIDEO/GEO/EXDISK_C.BGF | Bin 0 -> 2085 bytes CONTENT/BT/VIDEO/GEO/EXP.BGF | Bin 0 -> 297 bytes CONTENT/BT/VIDEO/GEO/FD1.BGF | Bin 0 -> 532 bytes CONTENT/BT/VIDEO/GEO/FD2.BGF | Bin 0 -> 800 bytes CONTENT/BT/VIDEO/GEO/FD3.BGF | Bin 0 -> 427 bytes CONTENT/BT/VIDEO/GEO/FD4.BGF | Bin 0 -> 438 bytes CONTENT/BT/VIDEO/GEO/FIRHIP.BGF | Bin 0 -> 4530 bytes CONTENT/BT/VIDEO/GEO/FL1.BGF | Bin 0 -> 254 bytes CONTENT/BT/VIDEO/GEO/FLAMEBIG.BGF | Bin 0 -> 917 bytes CONTENT/BT/VIDEO/GEO/FLAMEBIG.VGF | 71 + CONTENT/BT/VIDEO/GEO/FLAMESML.BGF | Bin 0 -> 153 bytes CONTENT/BT/VIDEO/GEO/FLAMESML.VGF | 30 + CONTENT/BT/VIDEO/GEO/FP0_LP.BGF | Bin 0 -> 300 bytes CONTENT/BT/VIDEO/GEO/FP1D.BGF | Bin 0 -> 1811 bytes CONTENT/BT/VIDEO/GEO/FP1D_FR.BGF | Bin 0 -> 3671 bytes CONTENT/BT/VIDEO/GEO/FP1_FR.BGF | Bin 0 -> 4095 bytes CONTENT/BT/VIDEO/GEO/FP2.BGF | Bin 0 -> 1171 bytes CONTENT/BT/VIDEO/GEO/FP2_LP.BGF | Bin 0 -> 152 bytes CONTENT/BT/VIDEO/GEO/FP3.BGF | Bin 0 -> 4187 bytes CONTENT/BT/VIDEO/GEO/FP3D.BGF | Bin 0 -> 4939 bytes CONTENT/BT/VIDEO/GEO/FT1D_FR.BGF | Bin 0 -> 1428 bytes CONTENT/BT/VIDEO/GEO/FT1_FR.BGF | Bin 0 -> 1625 bytes CONTENT/BT/VIDEO/GEO/FT1_LP.BGF | Bin 0 -> 334 bytes CONTENT/BT/VIDEO/GEO/FT2D.BGF | Bin 0 -> 4686 bytes CONTENT/BT/VIDEO/GEO/FT2D_FR.BGF | Bin 0 -> 1336 bytes CONTENT/BT/VIDEO/GEO/FT2_FR.BGF | Bin 0 -> 1209 bytes CONTENT/BT/VIDEO/GEO/FT2_LP.BGF | Bin 0 -> 413 bytes CONTENT/BT/VIDEO/GEO/GD1.BGF | Bin 0 -> 4725 bytes CONTENT/BT/VIDEO/GEO/GD2.BGF | Bin 0 -> 4670 bytes CONTENT/BT/VIDEO/GEO/GD4.BGF | Bin 0 -> 3223 bytes CONTENT/BT/VIDEO/GEO/GD5.BGF | Bin 0 -> 1778 bytes CONTENT/BT/VIDEO/GEO/GNR_LP.BGF | Bin 0 -> 218 bytes CONTENT/BT/VIDEO/GEO/GREEBEAM.BGF | Bin 0 -> 2301 bytes CONTENT/BT/VIDEO/GEO/HARASS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/HC1D_FR.BGF | Bin 0 -> 892 bytes CONTENT/BT/VIDEO/GEO/HC1_LP.BGF | Bin 0 -> 252 bytes CONTENT/BT/VIDEO/GEO/HC2D_FR.BGF | Bin 0 -> 1144 bytes CONTENT/BT/VIDEO/GEO/HC2_LP.BGF | Bin 0 -> 302 bytes CONTENT/BT/VIDEO/GEO/HILLA.BGF | Bin 0 -> 3374 bytes CONTENT/BT/VIDEO/GEO/HILLB.BGF | Bin 0 -> 3102 bytes CONTENT/BT/VIDEO/GEO/HILLC.BGF | Bin 0 -> 5267 bytes CONTENT/BT/VIDEO/GEO/HL1.BGF | Bin 0 -> 4049 bytes CONTENT/BT/VIDEO/GEO/HN1D_FR.BGF | Bin 0 -> 2716 bytes CONTENT/BT/VIDEO/GEO/HN1_FR.BGF | Bin 0 -> 2004 bytes CONTENT/BT/VIDEO/GEO/HN1_LP.BGF | Bin 0 -> 220 bytes CONTENT/BT/VIDEO/GEO/HND1_FR.BGF | Bin 0 -> 2738 bytes CONTENT/BT/VIDEO/GEO/HOTBOX.BGF | Bin 0 -> 284 bytes CONTENT/BT/VIDEO/GEO/HUMMS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/HUTD.BGF | Bin 0 -> 4893 bytes CONTENT/BT/VIDEO/GEO/HUT_FR.BGF | Bin 0 -> 1020 bytes CONTENT/BT/VIDEO/GEO/HUT_LP.BGF | Bin 0 -> 200 bytes CONTENT/BT/VIDEO/GEO/HWZD_FR.BGF | Bin 0 -> 3383 bytes CONTENT/BT/VIDEO/GEO/HWZ_FR.BGF | Bin 0 -> 2938 bytes CONTENT/BT/VIDEO/GEO/JAX1.BGF | Bin 0 -> 2554 bytes CONTENT/BT/VIDEO/GEO/JAX1D_FR.BGF | Bin 0 -> 2511 bytes CONTENT/BT/VIDEO/GEO/JAX1_FR.BGF | Bin 0 -> 575 bytes CONTENT/BT/VIDEO/GEO/JAX2.BGF | Bin 0 -> 2554 bytes CONTENT/BT/VIDEO/GEO/JAX2D_FR.BGF | Bin 0 -> 575 bytes CONTENT/BT/VIDEO/GEO/JAX2_FR.BGF | Bin 0 -> 575 bytes CONTENT/BT/VIDEO/GEO/LDBR.BGF | Bin 0 -> 1549 bytes CONTENT/BT/VIDEO/GEO/LLASER.BGF | Bin 0 -> 4177 bytes CONTENT/BT/VIDEO/GEO/LOKDLARM.BGF | Bin 0 -> 2830 bytes CONTENT/BT/VIDEO/GEO/LOKDLGUN.BGF | Bin 0 -> 2631 bytes CONTENT/BT/VIDEO/GEO/LOKDLIGH.BGF | Bin 0 -> 2110 bytes CONTENT/BT/VIDEO/GEO/LOKDMSL.BGF | Bin 0 -> 3116 bytes CONTENT/BT/VIDEO/GEO/LOKDRARM.BGF | Bin 0 -> 2504 bytes CONTENT/BT/VIDEO/GEO/LOKDRGUN.BGF | Bin 0 -> 2315 bytes CONTENT/BT/VIDEO/GEO/LOK_HIP.BGF | Bin 0 -> 4166 bytes CONTENT/BT/VIDEO/GEO/LOK_LDLE.BGF | Bin 0 -> 4821 bytes CONTENT/BT/VIDEO/GEO/LOK_LFOT.BGF | Bin 0 -> 3082 bytes CONTENT/BT/VIDEO/GEO/LOK_LGUN.BGF | Bin 0 -> 4020 bytes CONTENT/BT/VIDEO/GEO/LOK_LIGH.BGF | Bin 0 -> 1620 bytes CONTENT/BT/VIDEO/GEO/LOK_LULE.BGF | Bin 0 -> 4312 bytes CONTENT/BT/VIDEO/GEO/LOK_MSL.BGF | Bin 0 -> 2017 bytes CONTENT/BT/VIDEO/GEO/LOK_RDLE.BGF | Bin 0 -> 4821 bytes CONTENT/BT/VIDEO/GEO/LOK_RFOT.BGF | Bin 0 -> 3082 bytes CONTENT/BT/VIDEO/GEO/LOK_RULE.BGF | Bin 0 -> 4312 bytes CONTENT/BT/VIDEO/GEO/LOX_COP.BGF | Bin 0 -> 3104 bytes CONTENT/BT/VIDEO/GEO/LOX_TOR.BGF | Bin 0 -> 1131 bytes CONTENT/BT/VIDEO/GEO/LRMS.BGF | Bin 0 -> 344 bytes CONTENT/BT/VIDEO/GEO/MADDLARM.BGF | Bin 0 -> 2709 bytes CONTENT/BT/VIDEO/GEO/MADDLGUN.BGF | Bin 0 -> 3858 bytes CONTENT/BT/VIDEO/GEO/MADDRARM.BGF | Bin 0 -> 2717 bytes CONTENT/BT/VIDEO/GEO/MADDRGUN.BGF | Bin 0 -> 4082 bytes CONTENT/BT/VIDEO/GEO/MAD_HIP.BGF | Bin 0 -> 2655 bytes CONTENT/BT/VIDEO/GEO/MAD_LBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/MAD_LDOO.BGF | Bin 0 -> 1380 bytes CONTENT/BT/VIDEO/GEO/MAD_LFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT/VIDEO/GEO/MAD_LGUN.BGF | Bin 0 -> 5053 bytes CONTENT/BT/VIDEO/GEO/MAD_LITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/MAD_LOTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/MAD_RBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/MAD_RDOO.BGF | Bin 0 -> 1380 bytes CONTENT/BT/VIDEO/GEO/MAD_RFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT/VIDEO/GEO/MAD_RGUN.BGF | Bin 0 -> 5053 bytes CONTENT/BT/VIDEO/GEO/MAD_RITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/MAD_ROTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/MAX_LBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/MAX_LDLE.BGF | Bin 0 -> 2995 bytes CONTENT/BT/VIDEO/GEO/MAX_LFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT/VIDEO/GEO/MAX_LITO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/MAX_LOTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/MAX_RBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/MAX_RDLE.BGF | Bin 0 -> 2995 bytes CONTENT/BT/VIDEO/GEO/MAX_RFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT/VIDEO/GEO/MAX_RITO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/MAX_ROTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/MECHMOVS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/MISSILE.BGF | Bin 0 -> 1813 bytes CONTENT/BT/VIDEO/GEO/MLASER.BGF | Bin 0 -> 4177 bytes CONTENT/BT/VIDEO/GEO/MORNING/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/GEO/MORNING/RAVFLOOR.BGF | Bin 0 -> 807 bytes CONTENT/BT/VIDEO/GEO/MORNING/SEMIS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/MORNING/SKY.BGF | Bin 0 -> 539 bytes CONTENT/BT/VIDEO/GEO/MORNING/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT/VIDEO/GEO/MSLB_LP.BGF | Bin 0 -> 1102 bytes CONTENT/BT/VIDEO/GEO/MSLG_FR.BGF | Bin 0 -> 1746 bytes CONTENT/BT/VIDEO/GEO/MSLG_LP.BGF | Bin 0 -> 344 bytes CONTENT/BT/VIDEO/GEO/MSLH_FR.BGF | Bin 0 -> 1595 bytes CONTENT/BT/VIDEO/GEO/MSLH_LP.BGF | Bin 0 -> 205 bytes CONTENT/BT/VIDEO/GEO/MSLRD_FR.BGF | Bin 0 -> 1333 bytes CONTENT/BT/VIDEO/GEO/MSLROAD1.BGF | Bin 0 -> 2861 bytes CONTENT/BT/VIDEO/GEO/MSLR_FR.BGF | Bin 0 -> 1235 bytes CONTENT/BT/VIDEO/GEO/MSLR_LP.BGF | Bin 0 -> 443 bytes CONTENT/BT/VIDEO/GEO/MSL_FR.BGF | Bin 0 -> 707 bytes CONTENT/BT/VIDEO/GEO/MUZFLASH.BGF | Bin 0 -> 814 bytes CONTENT/BT/VIDEO/GEO/NBEAM.BGF | Bin 0 -> 4176 bytes CONTENT/BT/VIDEO/GEO/NIGHT/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT/VIDEO/GEO/NIGHT/SKY.BGF | Bin 0 -> 1660 bytes CONTENT/BT/VIDEO/GEO/NIGHT/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT/VIDEO/GEO/NTR.BGF | Bin 0 -> 254 bytes CONTENT/BT/VIDEO/GEO/OWNDCAM.BGF | Bin 0 -> 2132 bytes CONTENT/BT/VIDEO/GEO/OWNDLMSL.BGF | Bin 0 -> 2926 bytes CONTENT/BT/VIDEO/GEO/OWNDRMSL.BGF | Bin 0 -> 2926 bytes CONTENT/BT/VIDEO/GEO/OWN_CAM.BGF | Bin 0 -> 3647 bytes CONTENT/BT/VIDEO/GEO/OWN_LANT.BGF | Bin 0 -> 611 bytes CONTENT/BT/VIDEO/GEO/OWN_LBTO.BGF | Bin 0 -> 3116 bytes CONTENT/BT/VIDEO/GEO/OWN_LFTO.BGF | Bin 0 -> 3116 bytes CONTENT/BT/VIDEO/GEO/OWN_LMSL.BGF | Bin 0 -> 3235 bytes CONTENT/BT/VIDEO/GEO/OWN_RANT.BGF | Bin 0 -> 611 bytes CONTENT/BT/VIDEO/GEO/OWN_RBTO.BGF | Bin 0 -> 3116 bytes CONTENT/BT/VIDEO/GEO/OWN_RFTO.BGF | Bin 0 -> 3116 bytes CONTENT/BT/VIDEO/GEO/OWN_RMSL.BGF | Bin 0 -> 3235 bytes CONTENT/BT/VIDEO/GEO/OWX_LBTO.BGF | Bin 0 -> 842 bytes CONTENT/BT/VIDEO/GEO/OWX_LDLE.BGF | Bin 0 -> 2402 bytes CONTENT/BT/VIDEO/GEO/OWX_LFTO.BGF | Bin 0 -> 954 bytes CONTENT/BT/VIDEO/GEO/OWX_LULE.BGF | Bin 0 -> 3478 bytes CONTENT/BT/VIDEO/GEO/OWX_RBTO.BGF | Bin 0 -> 842 bytes CONTENT/BT/VIDEO/GEO/OWX_RDLE.BGF | Bin 0 -> 2402 bytes CONTENT/BT/VIDEO/GEO/OWX_RFTO.BGF | Bin 0 -> 954 bytes CONTENT/BT/VIDEO/GEO/OWX_RULE.BGF | Bin 0 -> 3478 bytes CONTENT/BT/VIDEO/GEO/PDSD_FR.BGF | Bin 0 -> 1049 bytes CONTENT/BT/VIDEO/GEO/PDSH_FR.BGF | Bin 0 -> 1297 bytes CONTENT/BT/VIDEO/GEO/PDSH_LP.BGF | Bin 0 -> 236 bytes CONTENT/BT/VIDEO/GEO/PGNDBASE.BGF | Bin 0 -> 1806 bytes CONTENT/BT/VIDEO/GEO/PGNDGUN.BGF | Bin 0 -> 4589 bytes CONTENT/BT/VIDEO/GEO/PGND_FR.BGF | Bin 0 -> 1480 bytes CONTENT/BT/VIDEO/GEO/PGN_BASE.BGF | Bin 0 -> 1820 bytes CONTENT/BT/VIDEO/GEO/PGN_FR.BGF | Bin 0 -> 1603 bytes CONTENT/BT/VIDEO/GEO/PLACE1.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLACE2.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLACE3.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLACE4.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLACE5.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLACE6.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLACE7.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLACE8.BGF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/GEO/PLIT_FR.BGF | Bin 0 -> 1249 bytes CONTENT/BT/VIDEO/GEO/PLTD_FR.BGF | Bin 0 -> 800 bytes CONTENT/BT/VIDEO/GEO/PNAME1.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/PNAME2.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/PNAME3.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/PNAME4.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/PNAME5.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/PNAME6.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/PNAME7.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/PNAME8.BGF | Bin 0 -> 235 bytes CONTENT/BT/VIDEO/GEO/POLAR/AVA_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/BLH_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/FIR_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/LOK_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/MAD_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/OWN_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/POLAR/SND_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/STI_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/THR_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/POLAR/VUL_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT/VIDEO/GEO/PPC.BGF | Bin 0 -> 2666 bytes CONTENT/BT/VIDEO/GEO/PROFILE1.BGF | Bin 0 -> 1506 bytes CONTENT/BT/VIDEO/GEO/PROFILE2.BGF | Bin 0 -> 1262 bytes CONTENT/BT/VIDEO/GEO/PROFILE3.BGF | Bin 0 -> 1230 bytes CONTENT/BT/VIDEO/GEO/PROFILE4.BGF | Bin 0 -> 1402 bytes CONTENT/BT/VIDEO/GEO/PROFILE5.BGF | Bin 0 -> 1398 bytes CONTENT/BT/VIDEO/GEO/PROFILE6.BGF | Bin 0 -> 1334 bytes CONTENT/BT/VIDEO/GEO/PROFILE7.BGF | Bin 0 -> 1366 bytes CONTENT/BT/VIDEO/GEO/PROFILE8.BGF | Bin 0 -> 1462 bytes CONTENT/BT/VIDEO/GEO/PWIN1.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/PWIN2.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/PWIN3.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/PWIN4.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/PWIN5.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/PWIN6.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/PWIN7.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/PWIN8.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/RAV/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT/VIDEO/GEO/RAV/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT/VIDEO/GEO/RAV/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/RAV/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT/VIDEO/GEO/RAV/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT/VIDEO/GEO/RAV/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/RAV/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/RAV/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT/VIDEO/GEO/RAV/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/RAV/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/RAV/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT/VIDEO/GEO/RAV1/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT/VIDEO/GEO/RAV1/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT/VIDEO/GEO/RAV1/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/RAV1/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT/VIDEO/GEO/RAV1/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT/VIDEO/GEO/RAV1/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/RAV1/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/RAV1/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT/VIDEO/GEO/RAV1/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT/VIDEO/GEO/RAV1/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT/VIDEO/GEO/RAV1/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT/VIDEO/GEO/RAVFLOOR.BGF | Bin 0 -> 807 bytes CONTENT/BT/VIDEO/GEO/RAVINE0.BGF | Bin 0 -> 4573 bytes CONTENT/BT/VIDEO/GEO/RAVINES.BMF | Bin 0 -> 322 bytes CONTENT/BT/VIDEO/GEO/RAVWIN.BGF | Bin 0 -> 3763 bytes CONTENT/BT/VIDEO/GEO/RB1.BGF | Bin 0 -> 4470 bytes CONTENT/BT/VIDEO/GEO/RB2.BGF | Bin 0 -> 3683 bytes CONTENT/BT/VIDEO/GEO/RB3.BGF | Bin 0 -> 4342 bytes CONTENT/BT/VIDEO/GEO/RB4.BGF | Bin 0 -> 2909 bytes CONTENT/BT/VIDEO/GEO/RB5.BGF | Bin 0 -> 3875 bytes CONTENT/BT/VIDEO/GEO/RB6.BGF | Bin 0 -> 1745 bytes CONTENT/BT/VIDEO/GEO/RD1.BGF | Bin 0 -> 251 bytes CONTENT/BT/VIDEO/GEO/RD2.BGF | Bin 0 -> 251 bytes CONTENT/BT/VIDEO/GEO/RED_BEAM.BGF | Bin 0 -> 2299 bytes CONTENT/BT/VIDEO/GEO/RK4.BGF | Bin 0 -> 3925 bytes CONTENT/BT/VIDEO/GEO/RK5.BGF | Bin 0 -> 4008 bytes CONTENT/BT/VIDEO/GEO/RK6.BGF | Bin 0 -> 3817 bytes CONTENT/BT/VIDEO/GEO/RK7.BGF | Bin 0 -> 3304 bytes CONTENT/BT/VIDEO/GEO/ROMMELS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/RWD.BGF | Bin 0 -> 488 bytes CONTENT/BT/VIDEO/GEO/RWIN1.BGF | Bin 0 -> 1528 bytes CONTENT/BT/VIDEO/GEO/SAW.BGF | Bin 0 -> 250 bytes CONTENT/BT/VIDEO/GEO/SB1.BGF | Bin 0 -> 2141 bytes CONTENT/BT/VIDEO/GEO/SB1B.BGF | Bin 0 -> 1314 bytes CONTENT/BT/VIDEO/GEO/SB1C.BGF | Bin 0 -> 1446 bytes CONTENT/BT/VIDEO/GEO/SB1D.BGF | Bin 0 -> 1386 bytes CONTENT/BT/VIDEO/GEO/SB1E.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB1N.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB1S.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB1W.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB2.BGF | Bin 0 -> 2069 bytes CONTENT/BT/VIDEO/GEO/SB2B.BGF | Bin 0 -> 1218 bytes CONTENT/BT/VIDEO/GEO/SB2C.BGF | Bin 0 -> 1422 bytes CONTENT/BT/VIDEO/GEO/SB2D.BGF | Bin 0 -> 1326 bytes CONTENT/BT/VIDEO/GEO/SB2E.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB2N.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB2S.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB2W.BGF | Bin 0 -> 1210 bytes CONTENT/BT/VIDEO/GEO/SB3E.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SB3N.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SB3S.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SB3W.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SB4E.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SB4N.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SB4S.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SB4W.BGF | Bin 0 -> 922 bytes CONTENT/BT/VIDEO/GEO/SEMIRIGS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/SEMIS.BGF | Bin 0 -> 204 bytes CONTENT/BT/VIDEO/GEO/SHOCK.BGF | Bin 0 -> 175 bytes CONTENT/BT/VIDEO/GEO/SL2.BGF | Bin 0 -> 2954 bytes CONTENT/BT/VIDEO/GEO/SL2D.BGF | Bin 0 -> 3392 bytes CONTENT/BT/VIDEO/GEO/SL2D_FR.BGF | Bin 0 -> 1261 bytes CONTENT/BT/VIDEO/GEO/SLASER.BGF | Bin 0 -> 4177 bytes CONTENT/BT/VIDEO/GEO/SLD2.BGF | Bin 0 -> 3392 bytes CONTENT/BT/VIDEO/GEO/SLD2_FR.BGF | Bin 0 -> 1283 bytes CONTENT/BT/VIDEO/GEO/SLT.BGF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/GEO/SMK_A.BGF | Bin 0 -> 779 bytes CONTENT/BT/VIDEO/GEO/SMK_B.BGF | Bin 0 -> 779 bytes CONTENT/BT/VIDEO/GEO/SMK_C.BGF | Bin 0 -> 779 bytes CONTENT/BT/VIDEO/GEO/SN1.BGF | Bin 0 -> 2141 bytes CONTENT/BT/VIDEO/GEO/SN2.BGF | Bin 0 -> 2267 bytes CONTENT/BT/VIDEO/GEO/SN4.BGF | Bin 0 -> 803 bytes CONTENT/BT/VIDEO/GEO/SNDDLARM.BGF | Bin 0 -> 3165 bytes CONTENT/BT/VIDEO/GEO/SNDDLGUN.BGF | Bin 0 -> 3830 bytes CONTENT/BT/VIDEO/GEO/SNDDRARM.BGF | Bin 0 -> 3868 bytes CONTENT/BT/VIDEO/GEO/SND_DOOR.BGF | Bin 0 -> 1371 bytes CONTENT/BT/VIDEO/GEO/SND_HIP.BGF | Bin 0 -> 4166 bytes CONTENT/BT/VIDEO/GEO/SND_LDLE.BGF | Bin 0 -> 4821 bytes CONTENT/BT/VIDEO/GEO/SND_LFOT.BGF | Bin 0 -> 3082 bytes CONTENT/BT/VIDEO/GEO/SND_LULE.BGF | Bin 0 -> 4312 bytes CONTENT/BT/VIDEO/GEO/SND_RARM.BGF | Bin 0 -> 2120 bytes CONTENT/BT/VIDEO/GEO/SND_RDLE.BGF | Bin 0 -> 4821 bytes CONTENT/BT/VIDEO/GEO/SND_RFOT.BGF | Bin 0 -> 3082 bytes CONTENT/BT/VIDEO/GEO/SND_RULE.BGF | Bin 0 -> 4312 bytes CONTENT/BT/VIDEO/GEO/SNHD_FR.BGF | Bin 0 -> 851 bytes CONTENT/BT/VIDEO/GEO/SNH_FR.BGF | Bin 0 -> 851 bytes CONTENT/BT/VIDEO/GEO/SNX_COP.BGF | Bin 0 -> 4383 bytes CONTENT/BT/VIDEO/GEO/SNX_TOR.BGF | Bin 0 -> 667 bytes CONTENT/BT/VIDEO/GEO/SPK1.BGF | Bin 0 -> 1165 bytes CONTENT/BT/VIDEO/GEO/SPK2.BGF | Bin 0 -> 1165 bytes CONTENT/BT/VIDEO/GEO/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT/VIDEO/GEO/SR1E.BGF | Bin 0 -> 2003 bytes CONTENT/BT/VIDEO/GEO/SR1N.BGF | Bin 0 -> 2003 bytes CONTENT/BT/VIDEO/GEO/SR1S.BGF | Bin 0 -> 2003 bytes CONTENT/BT/VIDEO/GEO/SR1W.BGF | Bin 0 -> 2003 bytes CONTENT/BT/VIDEO/GEO/SRC1NE.BGF | Bin 0 -> 2853 bytes CONTENT/BT/VIDEO/GEO/SRC1NW.BGF | Bin 0 -> 2896 bytes CONTENT/BT/VIDEO/GEO/SRC1SE.BGF | Bin 0 -> 2832 bytes CONTENT/BT/VIDEO/GEO/SRC1SW.BGF | Bin 0 -> 2570 bytes CONTENT/BT/VIDEO/GEO/SRMS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/ST1.BGF | Bin 0 -> 258 bytes CONTENT/BT/VIDEO/GEO/STF.BGF | Bin 0 -> 2074 bytes CONTENT/BT/VIDEO/GEO/STILITO.BGF | Bin 0 -> 2855 bytes CONTENT/BT/VIDEO/GEO/STILOTO.BGF | Bin 0 -> 2855 bytes CONTENT/BT/VIDEO/GEO/STIRITO.BGF | Bin 0 -> 2855 bytes CONTENT/BT/VIDEO/GEO/STIROTO.BGF | Bin 0 -> 2855 bytes CONTENT/BT/VIDEO/GEO/STRIKERS.BGF | Bin 0 -> 268 bytes CONTENT/BT/VIDEO/GEO/STX_COP.BGF | Bin 0 -> 4960 bytes CONTENT/BT/VIDEO/GEO/SV2BR.BGF | Bin 0 -> 2522 bytes CONTENT/BT/VIDEO/GEO/SV2BS.BGF | Bin 0 -> 1133 bytes CONTENT/BT/VIDEO/GEO/SV2CR.BGF | Bin 0 -> 3065 bytes CONTENT/BT/VIDEO/GEO/SV2DR.BGF | Bin 0 -> 2404 bytes CONTENT/BT/VIDEO/GEO/SV2DS.BGF | Bin 0 -> 1229 bytes CONTENT/BT/VIDEO/GEO/SV2R.BGF | Bin 0 -> 2066 bytes CONTENT/BT/VIDEO/GEO/SV2S.BGF | Bin 0 -> 1349 bytes CONTENT/BT/VIDEO/GEO/SV3BR.BGF | Bin 0 -> 2537 bytes CONTENT/BT/VIDEO/GEO/SV3BS.BGF | Bin 0 -> 1193 bytes CONTENT/BT/VIDEO/GEO/SV3CR.BGF | Bin 0 -> 1708 bytes CONTENT/BT/VIDEO/GEO/SV3CS.BGF | Bin 0 -> 1949 bytes CONTENT/BT/VIDEO/GEO/SV3DR.BGF | Bin 0 -> 1631 bytes CONTENT/BT/VIDEO/GEO/SV3DS.BGF | Bin 0 -> 2093 bytes CONTENT/BT/VIDEO/GEO/SV3R.BGF | Bin 0 -> 1907 bytes CONTENT/BT/VIDEO/GEO/SV3S.BGF | Bin 0 -> 1229 bytes CONTENT/BT/VIDEO/GEO/SW1.BGF | Bin 0 -> 610 bytes CONTENT/BT/VIDEO/GEO/SW2.BGF | Bin 0 -> 682 bytes CONTENT/BT/VIDEO/GEO/SW3.BGF | Bin 0 -> 457 bytes CONTENT/BT/VIDEO/GEO/SW4.BGF | Bin 0 -> 1327 bytes CONTENT/BT/VIDEO/GEO/SW5.BGF | Bin 0 -> 1423 bytes CONTENT/BT/VIDEO/GEO/SW6.BGF | Bin 0 -> 883 bytes CONTENT/BT/VIDEO/GEO/SWIFTS.BGF | Bin 0 -> 395 bytes CONTENT/BT/VIDEO/GEO/THRDBR.BGF | Bin 0 -> 153 bytes CONTENT/BT/VIDEO/GEO/THRDLGUN.BGF | Bin 0 -> 4947 bytes CONTENT/BT/VIDEO/GEO/THRDMSL.BGF | Bin 0 -> 4930 bytes CONTENT/BT/VIDEO/GEO/THRDRARM.BGF | Bin 0 -> 4745 bytes CONTENT/BT/VIDEO/GEO/THRDRGUN.BGF | Bin 0 -> 4648 bytes CONTENT/BT/VIDEO/GEO/THR_DOOR.BGF | Bin 0 -> 2943 bytes CONTENT/BT/VIDEO/GEO/THR_HIP.BGF | Bin 0 -> 4166 bytes CONTENT/BT/VIDEO/GEO/THR_LDLE.BGF | Bin 0 -> 4821 bytes CONTENT/BT/VIDEO/GEO/THR_LFOT.BGF | Bin 0 -> 3082 bytes CONTENT/BT/VIDEO/GEO/THR_LGUN.BGF | Bin 0 -> 3940 bytes CONTENT/BT/VIDEO/GEO/THR_LULE.BGF | Bin 0 -> 4312 bytes CONTENT/BT/VIDEO/GEO/THR_MSL.BGF | Bin 0 -> 4371 bytes CONTENT/BT/VIDEO/GEO/THR_RDLE.BGF | Bin 0 -> 4821 bytes CONTENT/BT/VIDEO/GEO/THR_RFOT.BGF | Bin 0 -> 3082 bytes CONTENT/BT/VIDEO/GEO/THR_RULE.BGF | Bin 0 -> 4312 bytes CONTENT/BT/VIDEO/GEO/THXDMSL.BGF | Bin 0 -> 1532 bytes CONTENT/BT/VIDEO/GEO/THX_DOOR.BGF | Bin 0 -> 1635 bytes CONTENT/BT/VIDEO/GEO/THX_MSL.BGF | Bin 0 -> 2783 bytes CONTENT/BT/VIDEO/GEO/THX_TOR.BGF | Bin 0 -> 342 bytes CONTENT/BT/VIDEO/GEO/TM1.BGF | Bin 0 -> 4118 bytes CONTENT/BT/VIDEO/GEO/TMC1.BGF | Bin 0 -> 547 bytes CONTENT/BT/VIDEO/GEO/TMC2.BGF | Bin 0 -> 350 bytes CONTENT/BT/VIDEO/GEO/TMC3.BGF | Bin 0 -> 680 bytes CONTENT/BT/VIDEO/GEO/TMC3_LP.BGF | Bin 0 -> 414 bytes CONTENT/BT/VIDEO/GEO/TMC4.BGF | Bin 0 -> 323 bytes CONTENT/BT/VIDEO/GEO/TMC4_LP.BGF | Bin 0 -> 250 bytes CONTENT/BT/VIDEO/GEO/TMC5.BGF | Bin 0 -> 264 bytes CONTENT/BT/VIDEO/GEO/TMC5_LP.BGF | Bin 0 -> 218 bytes CONTENT/BT/VIDEO/GEO/TMC6.BGF | Bin 0 -> 264 bytes CONTENT/BT/VIDEO/GEO/TMC6_LP.BGF | Bin 0 -> 218 bytes CONTENT/BT/VIDEO/GEO/TMC7.BGF | Bin 0 -> 288 bytes CONTENT/BT/VIDEO/GEO/TMC7_LP.BGF | Bin 0 -> 234 bytes CONTENT/BT/VIDEO/GEO/TMC8.BGF | Bin 0 -> 763 bytes CONTENT/BT/VIDEO/GEO/TMC8_LP.BGF | Bin 0 -> 414 bytes CONTENT/BT/VIDEO/GEO/TMSM_A.BGF | Bin 0 -> 2313 bytes CONTENT/BT/VIDEO/GEO/TMSM_B.BGF | Bin 0 -> 2313 bytes CONTENT/BT/VIDEO/GEO/TMSM_C.BGF | Bin 0 -> 2313 bytes CONTENT/BT/VIDEO/GEO/TMST_A.BGF | Bin 0 -> 4247 bytes CONTENT/BT/VIDEO/GEO/TMST_C.BGF | Bin 0 -> 4249 bytes CONTENT/BT/VIDEO/GEO/TMS_A.BGF | Bin 0 -> 1811 bytes CONTENT/BT/VIDEO/GEO/TMS_B.BGF | Bin 0 -> 1811 bytes CONTENT/BT/VIDEO/GEO/TMS_C.BGF | Bin 0 -> 1811 bytes CONTENT/BT/VIDEO/GEO/TREE.BGF | Bin 0 -> 2761 bytes CONTENT/BT/VIDEO/GEO/TREESH.BGF | Bin 0 -> 291 bytes CONTENT/BT/VIDEO/GEO/TRK1D_FR.BGF | Bin 0 -> 1230 bytes CONTENT/BT/VIDEO/GEO/TRK1_FR.BGF | Bin 0 -> 1615 bytes CONTENT/BT/VIDEO/GEO/TRK3D_FR.BGF | Bin 0 -> 1407 bytes CONTENT/BT/VIDEO/GEO/TRK3_FR.BGF | Bin 0 -> 1407 bytes CONTENT/BT/VIDEO/GEO/TRK4D_FR.BGF | Bin 0 -> 1138 bytes CONTENT/BT/VIDEO/GEO/TRK4_FR.BGF | Bin 0 -> 1218 bytes CONTENT/BT/VIDEO/GEO/TRUNK.BGF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/GEO/TSPHERE.BGF | Bin 0 -> 2085 bytes CONTENT/BT/VIDEO/GEO/TWRD_FR.BGF | Bin 0 -> 743 bytes CONTENT/BT/VIDEO/GEO/TWR_FR.BGF | Bin 0 -> 1364 bytes CONTENT/BT/VIDEO/GEO/TWR_LP.BGF | Bin 0 -> 282 bytes CONTENT/BT/VIDEO/GEO/VULDLARM.BGF | Bin 0 -> 2709 bytes CONTENT/BT/VIDEO/GEO/VULDLGUN.BGF | Bin 0 -> 3962 bytes CONTENT/BT/VIDEO/GEO/VULDRARM.BGF | Bin 0 -> 2717 bytes CONTENT/BT/VIDEO/GEO/VULDRGUN.BGF | Bin 0 -> 4082 bytes CONTENT/BT/VIDEO/GEO/VUL_HIP.BGF | Bin 0 -> 2655 bytes CONTENT/BT/VIDEO/GEO/VUL_LBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/VUL_LDDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT/VIDEO/GEO/VUL_LFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT/VIDEO/GEO/VUL_LGUN.BGF | Bin 0 -> 5053 bytes CONTENT/BT/VIDEO/GEO/VUL_LITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/VUL_LOTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/VUL_LUDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT/VIDEO/GEO/VUL_RBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/VUL_RDDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT/VIDEO/GEO/VUL_RFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT/VIDEO/GEO/VUL_RGUN.BGF | Bin 0 -> 5053 bytes CONTENT/BT/VIDEO/GEO/VUL_RITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/VUL_ROTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT/VIDEO/GEO/VUL_RUDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT/VIDEO/GEO/VUX_LBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/VUX_LDLE.BGF | Bin 0 -> 2995 bytes CONTENT/BT/VIDEO/GEO/VUX_LFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT/VIDEO/GEO/VUX_LITO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/VUX_LOTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/VUX_RBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/VUX_RDLE.BGF | Bin 0 -> 2995 bytes CONTENT/BT/VIDEO/GEO/VUX_RFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT/VIDEO/GEO/VUX_RITO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/VUX_ROTO.BGF | Bin 0 -> 578 bytes CONTENT/BT/VIDEO/GEO/WL7.BGF | Bin 0 -> 4992 bytes CONTENT/BT/VIDEO/GEO/WL9.BGF | Bin 0 -> 3130 bytes CONTENT/BT/VIDEO/GEO/WSTD_FR.BGF | Bin 0 -> 1755 bytes CONTENT/BT/VIDEO/GEO/WST_FR.BGF | Bin 0 -> 1497 bytes CONTENT/BT/VIDEO/GEO/WST_LP.BGF | Bin 0 -> 270 bytes CONTENT/BT/VIDEO/IDAM1.PFX | 32 + CONTENT/BT/VIDEO/IDAM2.PFX | 32 + CONTENT/BT/VIDEO/IDAM3.PFX | 32 + CONTENT/BT/VIDEO/IDAM4.PFX | 32 + CONTENT/BT/VIDEO/IDAM5.PFX | 33 + CONTENT/BT/VIDEO/JAKSKIN.DZM | 74 + CONTENT/BT/VIDEO/JAXSKIN.DZM | 3 + CONTENT/BT/VIDEO/LASARM.SKL | 86 + CONTENT/BT/VIDEO/LOK1SKIN.DZM | 88 + CONTENT/BT/VIDEO/LOKSKIN.DZM | 91 + CONTENT/BT/VIDEO/LOX1SKIN.DZM | 9 + CONTENT/BT/VIDEO/LOXSKIN.DZM | 9 + CONTENT/BT/VIDEO/MAD1SKIN.DZM | 94 + CONTENT/BT/VIDEO/MAD2SKIN.DZM | 93 + CONTENT/BT/VIDEO/MADSKIN.DZM | 91 + CONTENT/BT/VIDEO/MADSKIN.ORG | 92 + CONTENT/BT/VIDEO/MAT/ARENA/BTVEH.BMF | Bin 0 -> 3471 bytes CONTENT/BT/VIDEO/MAT/AVAFX.BMF | Bin 0 -> 898 bytes CONTENT/BT/VIDEO/MAT/AVASKIN.BMF | Bin 0 -> 4215 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN0.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN1.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN2.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN3.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN4.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN5.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN6.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVXSKIN7.BMF | Bin 0 -> 287 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK0.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK1.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK2.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK3.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK4.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK5.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK6.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BLK7.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN0.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN1.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN2.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN3.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN4.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN5.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN6.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_BRN7.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN0.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN1.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN2.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN3.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN4.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN5.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN6.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRN7.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY0.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY1.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY2.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY3.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY4.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY5.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY6.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_GRY7.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED0.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED1.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED2.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED3.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED4.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED5.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED6.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_RED7.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN0.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN1.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN2.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN3.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN4.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN5.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN6.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_TAN7.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT0.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT1.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT2.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT3.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT4.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT5.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT6.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/AVX_WHT7.BMF | Bin 0 -> 317 bytes CONTENT/BT/VIDEO/MAT/BASEV.BMF | Bin 0 -> 2942 bytes CONTENT/BT/VIDEO/MAT/BLHFX.BMF | Bin 0 -> 1388 bytes CONTENT/BT/VIDEO/MAT/BLHSKIN.BMF | Bin 0 -> 4590 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLXSKIN7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BLK7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_BRN7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRN7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_GRY7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_RED7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_TAN7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT0.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT1.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT2.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT3.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT4.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT5.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT6.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BLX_WHT7.BMF | Bin 0 -> 238 bytes CONTENT/BT/VIDEO/MAT/BMAP.BMF | Bin 0 -> 480 bytes CONTENT/BT/VIDEO/MAT/BTCULT.BMF | 1 + CONTENT/BT/VIDEO/MAT/BTPOLWIN.BMF | Bin 0 -> 1048 bytes CONTENT/BT/VIDEO/MAT/BTRAVWIN.BMF | Bin 0 -> 801 bytes CONTENT/BT/VIDEO/MAT/CALIOPE.BMF | Bin 0 -> 2413 bytes CONTENT/BT/VIDEO/MAT/CAVERN/BTVEH.BMF | Bin 0 -> 3111 bytes CONTENT/BT/VIDEO/MAT/DAY/BTARENA.BMF | Bin 0 -> 6308 bytes CONTENT/BT/VIDEO/MAT/DAY/BTFX.BMF | Bin 0 -> 4487 bytes CONTENT/BT/VIDEO/MAT/DAY/BTPOLAR.BMF | Bin 0 -> 4209 bytes .../BT/VIDEO/MAT/DAY/DIVISION.SAV/GRASS.BMF | Bin 0 -> 441 bytes .../BT/VIDEO/MAT/DAY/DIVISION.SAV/GRASSBU.BMF | Bin 0 -> 441 bytes .../BT/VIDEO/MAT/DAY/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/DAY/EBTFX.BMF | Bin 0 -> 4485 bytes CONTENT/BT/VIDEO/MAT/DAY/GRASS.BMF | Bin 0 -> 441 bytes CONTENT/BT/VIDEO/MAT/DAY/GRASS.VMF | 69 + CONTENT/BT/VIDEO/MAT/DAY/GRASSBU.BMF | Bin 0 -> 441 bytes CONTENT/BT/VIDEO/MAT/DAY/GRASSBU.VMF | 69 + CONTENT/BT/VIDEO/MAT/DAY/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/DAY/RAVINES.VMF | 62 + CONTENT/BT/VIDEO/MAT/DBASE.BMF | Bin 0 -> 1574 bytes CONTENT/BT/VIDEO/MAT/DISH.BGF | Bin 0 -> 4736 bytes CONTENT/BT/VIDEO/MAT/DISH.BMF | Bin 0 -> 2655 bytes CONTENT/BT/VIDEO/MAT/DIVISION.SAV/BASEV.BMF | Bin 0 -> 2942 bytes CONTENT/BT/VIDEO/MAT/DIVISION.SAV/CALIOPE.BMF | Bin 0 -> 2413 bytes CONTENT/BT/VIDEO/MAT/DIVISION.SAV/DBASE.BMF | Bin 0 -> 1574 bytes CONTENT/BT/VIDEO/MAT/DIVISION.SAV/DISH.BMF | Bin 0 -> 2655 bytes CONTENT/BT/VIDEO/MAT/DIVISION.SAV/GRASS.BMF | Bin 0 -> 441 bytes CONTENT/BT/VIDEO/MAT/DIVISION.SAV/GRASS.VMF | 61 + CONTENT/BT/VIDEO/MAT/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/DIVISION.SAV/RAVINES.VMF | 50 + CONTENT/BT/VIDEO/MAT/DUMMY.BMF | Bin 0 -> 128 bytes CONTENT/BT/VIDEO/MAT/EVENING/BTPOLAR.BMF | Bin 0 -> 4209 bytes .../VIDEO/MAT/EVENING/DIVISION.SAV/BTFX.BMF | Bin 0 -> 4478 bytes .../VIDEO/MAT/EVENING/DIVISION.SAV/GRASS.BMF | Bin 0 -> 471 bytes .../MAT/EVENING/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/EVENING/GRASS.BMF | Bin 0 -> 471 bytes CONTENT/BT/VIDEO/MAT/EVENING/GRASS.VMF | 71 + CONTENT/BT/VIDEO/MAT/EVENING/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/EVENING/RAVINES.VMF | 62 + CONTENT/BT/VIDEO/MAT/FIRFX.BMF | Bin 0 -> 798 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIRSKIN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BLK7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_BRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRY0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRY2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRY3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRY4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRY5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRY6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_GRY7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_RED7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_TAN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIR_WHT7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIXSKIN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BLK7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_BRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_GRY7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_RED7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_TAN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT0.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT1.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT2.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT3.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT4.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT5.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT6.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/FIX_WHT7.BMF | Bin 0 -> 1010 bytes CONTENT/BT/VIDEO/MAT/GRASS.BMF | Bin 0 -> 441 bytes CONTENT/BT/VIDEO/MAT/GRASS.VMF | 68 + CONTENT/BT/VIDEO/MAT/JAKSKIN.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAKSKIN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BLK7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_BRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_GRY7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_RED7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_TAN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAK_WHT7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAXSKIN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BLK7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_BRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_GRY7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_RED7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_TAN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT0.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT1.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT2.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT3.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT4.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT5.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT6.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/JAX_WHT7.BMF | Bin 0 -> 1001 bytes CONTENT/BT/VIDEO/MAT/LOKFX.BMF | Bin 0 -> 984 bytes CONTENT/BT/VIDEO/MAT/LOKSKIN.BMF | Bin 0 -> 4561 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN0.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN1.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN2.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN3.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN4.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN5.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN6.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOXSKIN7.BMF | Bin 0 -> 404 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK0.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK1.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK2.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK3.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK4.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK5.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK6.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BLK7.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN0.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN1.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN2.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN3.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN4.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN5.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN6.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_BRN7.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN0.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN1.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN2.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN3.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN4.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN5.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN6.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRN7.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY0.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY1.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY2.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY3.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY4.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY5.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY6.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_GRY7.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED0.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED1.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED2.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED3.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED4.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED5.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED6.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_RED7.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN0.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN1.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN2.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN3.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN4.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN5.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN6.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_TAN7.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT0.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT1.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT2.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT3.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT4.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT5.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT6.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/LOX_WHT7.BMF | Bin 0 -> 554 bytes CONTENT/BT/VIDEO/MAT/MADFX.BMF | Bin 0 -> 898 bytes CONTENT/BT/VIDEO/MAT/MADSKIN.BMF | Bin 0 -> 4289 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAXSKIN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BLK7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_BRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_GRY7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_RED7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_TAN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MAX_WHT7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/MECHFX.BMF | Bin 0 -> 984 bytes CONTENT/BT/VIDEO/MAT/MORNING/BTFX.BMF | Bin 0 -> 4491 bytes CONTENT/BT/VIDEO/MAT/MORNING/BTPOLAR.BMF | Bin 0 -> 4209 bytes .../VIDEO/MAT/MORNING/DIVISION.SAV/BTFX.BMF | Bin 0 -> 4491 bytes .../VIDEO/MAT/MORNING/DIVISION.SAV/GRASS.BMF | Bin 0 -> 471 bytes .../MAT/MORNING/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes .../MAT/MORNING/DIVISION.SAV/RAVINES.VMF | 61 + CONTENT/BT/VIDEO/MAT/MORNING/GRASS.BMF | Bin 0 -> 471 bytes CONTENT/BT/VIDEO/MAT/MORNING/GRASS.VMF | 71 + CONTENT/BT/VIDEO/MAT/MORNING/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/MORNING/RAVINES.VMF | 62 + CONTENT/BT/VIDEO/MAT/NIGHT/BTFX.BMF | Bin 0 -> 4492 bytes CONTENT/BT/VIDEO/MAT/NIGHT/BTPOLAR.BMF | Bin 0 -> 4209 bytes .../BT/VIDEO/MAT/NIGHT/DIVISION.SAV/BTFX.BMF | Bin 0 -> 4363 bytes .../BT/VIDEO/MAT/NIGHT/DIVISION.SAV/GRASS.BMF | Bin 0 -> 471 bytes .../VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes .../VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.VMF | 61 + CONTENT/BT/VIDEO/MAT/NIGHT/GRASS.BMF | Bin 0 -> 471 bytes CONTENT/BT/VIDEO/MAT/NIGHT/GRASS.VMF | 71 + CONTENT/BT/VIDEO/MAT/NIGHT/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/NIGHT/RAVINES.VMF | 62 + CONTENT/BT/VIDEO/MAT/OWNFX.BMF | Bin 0 -> 798 bytes CONTENT/BT/VIDEO/MAT/OWNSKIN.BMF | Bin 0 -> 4537 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN0.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN1.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN2.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN3.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN4.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN5.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN6.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWXSKIN7.BMF | Bin 0 -> 1720 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK0.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK1.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK2.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK3.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK4.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK5.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK6.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BLK7.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN0.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN1.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN2.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN3.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN4.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN5.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN6.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_BRN7.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN0.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN1.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN2.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN3.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN4.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN5.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN6.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRN7.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY0.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY1.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY2.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY3.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY4.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY5.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY6.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_GRY7.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED0.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED1.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED2.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED3.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED4.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED5.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED6.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_RED7.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN0.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN1.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN2.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN3.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN4.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN5.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN6.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_TAN7.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT0.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT1.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT2.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT3.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT4.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT5.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT6.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/OWX_WHT7.BMF | Bin 0 -> 2350 bytes CONTENT/BT/VIDEO/MAT/RAPFX.BMF | Bin 0 -> 798 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAPSKIN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BLK7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_BRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_GRY7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_RED7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_TAN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAP_WHT7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAVBU.VMF | 50 + CONTENT/BT/VIDEO/MAT/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT/VIDEO/MAT/RAXFX.BMF | Bin 0 -> 798 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAXSKIN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BLK7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_BRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_GRY7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_RED7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_TAN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT0.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT1.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT2.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT3.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT4.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT5.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT6.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/RAX_WHT7.BMF | Bin 0 -> 1110 bytes CONTENT/BT/VIDEO/MAT/SNDFX.BMF | Bin 0 -> 984 bytes CONTENT/BT/VIDEO/MAT/SNDSKIN.BMF | Bin 0 -> 4381 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN0.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN1.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN2.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN3.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN4.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN5.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN6.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNXSKIN7.BMF | Bin 0 -> 324 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK0.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK1.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK2.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK3.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK4.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK5.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK6.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BLK7.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN0.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN1.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN2.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN3.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN4.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN5.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN6.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_BRN7.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN0.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN1.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN2.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN3.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN4.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN5.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN6.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRN7.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY0.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY1.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY2.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY3.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY4.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY5.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY6.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_GRY7.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED0.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED1.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED2.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED3.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED4.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED5.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED6.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_RED7.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN0.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN1.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN2.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN3.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN4.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN5.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN6.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_TAN7.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT0.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT1.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT2.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT3.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT4.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT5.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT6.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/SNX_WHT7.BMF | Bin 0 -> 384 bytes CONTENT/BT/VIDEO/MAT/STIFX.BMF | Bin 0 -> 944 bytes CONTENT/BT/VIDEO/MAT/STISKIN.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STISKIN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BLK7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_BRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_GRY7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_RED7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_TAN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STI_WHT7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXFX.BMF | Bin 0 -> 944 bytes CONTENT/BT/VIDEO/MAT/STXSKIN.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STXSKIN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BLK7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_BRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_GRY7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_RED7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_TAN7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT0.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT1.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT2.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT3.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT4.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT5.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT6.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/STX_WHT7.BMF | Bin 0 -> 956 bytes CONTENT/BT/VIDEO/MAT/THRFX.BMF | Bin 0 -> 1494 bytes CONTENT/BT/VIDEO/MAT/THRSKIN.BMF | Bin 0 -> 4870 bytes CONTENT/BT/VIDEO/MAT/THXSKIN.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN0.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN1.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN2.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN3.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN4.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN5.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN6.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THXSKIN7.BMF | Bin 0 -> 534 bytes CONTENT/BT/VIDEO/MAT/THX_BLK0.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BLK1.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BLK2.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BLK3.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BLK4.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BLK5.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BLK6.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BLK7.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN0.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN1.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN2.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN3.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN4.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN5.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN6.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_BRN7.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN0.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN1.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN2.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN3.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN4.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN5.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN6.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRN7.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY0.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY1.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY2.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY3.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY4.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY5.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY6.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_GRY7.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED0.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED1.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED2.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED3.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED4.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED5.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED6.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_RED7.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN0.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN1.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN2.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN3.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN4.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN5.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN6.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_TAN7.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT0.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT1.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT2.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT3.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT4.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT5.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT6.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/THX_WHT7.BMF | Bin 0 -> 744 bytes CONTENT/BT/VIDEO/MAT/VULFX.BMF | Bin 0 -> 898 bytes CONTENT/BT/VIDEO/MAT/VULSKIN.BMF | Bin 0 -> 4324 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUXSKIN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BLK7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_BRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_GRY7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_RED7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_TAN7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT0.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT1.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT2.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT3.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT4.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT5.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT6.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAT/VUX_WHT7.BMF | Bin 0 -> 102 bytes CONTENT/BT/VIDEO/MAX.ORG | 658 ++ CONTENT/BT/VIDEO/MAX1SKIN.DZM | 2 + CONTENT/BT/VIDEO/MAX2SKIN.DZM | 2 + CONTENT/BT/VIDEO/MAXSKIN.DZM | 2 + CONTENT/BT/VIDEO/MAXSKIN.ORG | 2 + CONTENT/BT/VIDEO/NAFC.PFX | 32 + CONTENT/BT/VIDEO/NBIGBOOM.PFX | 33 + CONTENT/BT/VIDEO/NDAM1.PFX | 32 + CONTENT/BT/VIDEO/NDAM2.PFX | 32 + CONTENT/BT/VIDEO/NDAM3.PFX | 32 + CONTENT/BT/VIDEO/NDAM4.PFX | 33 + CONTENT/BT/VIDEO/NDAM5.PFX | 33 + CONTENT/BT/VIDEO/NDTHSMK.PFX | 32 + CONTENT/BT/VIDEO/NLRMTAIL.PFX | 33 + CONTENT/BT/VIDEO/NMEDBOOM.PFX | 33 + CONTENT/BT/VIDEO/NMISSING.PFX | 33 + CONTENT/BT/VIDEO/NNBOOM.PFX | 33 + CONTENT/BT/VIDEO/NSMLBOOM.PFX | 33 + CONTENT/BT/VIDEO/NSRM.PFX | 33 + CONTENT/BT/VIDEO/NTRKBOOM.PFX | 33 + CONTENT/BT/VIDEO/NTRKBURN.PFX | 32 + CONTENT/BT/VIDEO/OWNSKIN.DZM | 88 + CONTENT/BT/VIDEO/OWXSKIN.DZM | 35 + CONTENT/BT/VIDEO/PGN.SKL | 55 + CONTENT/BT/VIDEO/PGND.SKL | 55 + CONTENT/BT/VIDEO/RAPSKIN.DZM | 81 + CONTENT/BT/VIDEO/RAXSKIN.DZM | 81 + CONTENT/BT/VIDEO/RESULT2.TXT | 5 + CONTENT/BT/VIDEO/SHKWAVE.PFX | 33 + CONTENT/BT/VIDEO/SMLFLASH.PFX | 33 + CONTENT/BT/VIDEO/SMLSMOKE.PFX | 33 + CONTENT/BT/VIDEO/SND2SKIN.DZM | 90 + CONTENT/BT/VIDEO/SNX2SKIN.DZM | 8 + CONTENT/BT/VIDEO/SNXSKIN.DZM | 8 + CONTENT/BT/VIDEO/STISKIN.DZM | 99 + CONTENT/BT/VIDEO/STXSKIN.DZM | 11 + CONTENT/BT/VIDEO/TEX/BDINTA.VTX | Bin 0 -> 49209 bytes CONTENT/BT/VIDEO/TEX/BDINTB.VTX | Bin 0 -> 49209 bytes CONTENT/BT/VIDEO/TEX/BDINTC.VTX | Bin 0 -> 49209 bytes CONTENT/BT/VIDEO/TEX/BUILD/BDLGO128.BAT | 17 + CONTENT/BT/VIDEO/TEX/BUILD/BUILDLGO.BAT | 18 + CONTENT/BT/VIDEO/TEX/BUILD/LGO1.TGA | Bin 0 -> 49170 bytes CONTENT/BT/VIDEO/TEX/BUILD/LGO2.TGA | Bin 0 -> 49170 bytes CONTENT/BT/VIDEO/TEX/BUILD/LGO3.TGA | Bin 0 -> 49170 bytes CONTENT/BT/VIDEO/TEX/BUILD/LGO4.TGA | Bin 0 -> 49170 bytes CONTENT/BT/VIDEO/TEX/BUILD/LGO5.TGA | Bin 0 -> 49170 bytes CONTENT/BT/VIDEO/TEX/BUILD/LGO6.TGA | Bin 0 -> 49170 bytes CONTENT/BT/VIDEO/TEX/GRASSC.VTX | Bin 0 -> 49209 bytes CONTENT/BT/VIDEO/TEX/LGO.BSL | Bin 0 -> 32874 bytes CONTENT/BT/VIDEO/TEX/SAINTB.VTX | Bin 0 -> 24633 bytes CONTENT/BT/VIDEO/TEX/SBASE.BSL | Bin 0 -> 32886 bytes CONTENT/BT/VIDEO/THR1SKIN.DZM | 100 + CONTENT/BT/VIDEO/THRSKIN.DZM | 99 + CONTENT/BT/VIDEO/THX1SKIN.DZM | 11 + CONTENT/BT/VIDEO/THXSKIN.DZM | 11 + CONTENT/BT/VIDEO/VUL1SKIN.DZM | 91 + CONTENT/BT/VIDEO/VUL2SKIN.DZM | 79 + CONTENT/BT/VIDEO/VUX1SKIN.DZM | 2 + CONTENT/BT/VIDEO/VUX2SKIN.DZM | 2 + CONTENT/BT/VIDEO/VUXSKIN.DZM | 2 + CONTENT/BT/WATTCP.CFG | 4 + CONTENT/BT3025/32STUB.EXE | Bin 0 -> 2160 bytes CONTENT/BT3025/ANIM.BAT | 64 + CONTENT/BT3025/ANIM1.BAT | 2 + CONTENT/BT3025/ANIMCAM.BAT | 2 + CONTENT/BT3025/ANIMS/BLHBMP.ANI | 70 + CONTENT/BT3025/ANIMS/BLHBMPI.ANI | 70 + CONTENT/BT3025/ANIMS/BLHSQI.ANI | 0 CONTENT/BT3025/ANIMS/BLHSQT.ANI | 0 CONTENT/BT3025/ANIMS/FIRBMP.ANI | 80 + CONTENT/BT3025/ANIMS/FIRBMPI.ANI | 85 + CONTENT/BT3025/ANIMS/FIRRRL.ANI | 87 + CONTENT/BT3025/ANIMS/FIRRRLI.ANI | 94 + CONTENT/BT3025/ANIMS/FIRRRR.ANI | 87 + CONTENT/BT3025/ANIMS/FIRRRRI.ANI | 94 + CONTENT/BT3025/ANIMS/FIRRWL.ANI | 94 + CONTENT/BT3025/ANIMS/FIRRWR.ANI | 94 + CONTENT/BT3025/ANIMS/FIRSWL.ANI | 87 + CONTENT/BT3025/ANIMS/FIRSWLI.ANI | 94 + CONTENT/BT3025/ANIMS/FIRSWR.ANI | 87 + CONTENT/BT3025/ANIMS/FIRSWRI.ANI | 94 + CONTENT/BT3025/ANIMS/FIRTRN.ANI | 87 + CONTENT/BT3025/ANIMS/FIRTRNI.ANI | 94 + CONTENT/BT3025/ANIMS/FIRWSL.ANI | 87 + CONTENT/BT3025/ANIMS/FIRWSLI.ANI | 94 + CONTENT/BT3025/ANIMS/FIRWSR.ANI | 87 + CONTENT/BT3025/ANIMS/FIRWSRI.ANI | 94 + CONTENT/BT3025/ANIMS/JAKBMP.ANI | 70 + CONTENT/BT3025/ANIMS/JAKBMPI.ANI | 76 + CONTENT/BT3025/ANIMS/JAKBSL.ANI | 76 + CONTENT/BT3025/ANIMS/JAKBSLI.ANI | 83 + CONTENT/BT3025/ANIMS/JAKBSR.ANI | 76 + CONTENT/BT3025/ANIMS/JAKBSRI.ANI | 83 + CONTENT/BT3025/ANIMS/JAKRWL.ANI | 87 + CONTENT/BT3025/ANIMS/JAKRWLI.ANI | 95 + CONTENT/BT3025/ANIMS/JAKRWR.ANI | 87 + CONTENT/BT3025/ANIMS/JAKRWRI.ANI | 95 + CONTENT/BT3025/ANIMS/JAKSWL.ANI | 87 + CONTENT/BT3025/ANIMS/JAKSWLI.ANI | 94 + CONTENT/BT3025/ANIMS/JAKSWR.ANI | 87 + CONTENT/BT3025/ANIMS/JAKSWRI.ANI | 94 + CONTENT/BT3025/ANIMS/JAKTRN.ANI | 87 + CONTENT/BT3025/ANIMS/JAKTRNI.ANI | 94 + CONTENT/BT3025/ANIMS/LOKBBLI.ANI | 82 + CONTENT/BT3025/ANIMS/LOKBBRI.ANI | 82 + CONTENT/BT3025/ANIMS/LOKBMP.ANI | 80 + CONTENT/BT3025/ANIMS/LOKBMPI.ANI | 80 + CONTENT/BT3025/ANIMS/LOKBSLI.ANI | 82 + CONTENT/BT3025/ANIMS/LOKBSRI.ANI | 82 + CONTENT/BT3025/ANIMS/LOKTRN.ANI | 87 + CONTENT/BT3025/ANIMS/LOKTRNI.ANI | 94 + CONTENT/BT3025/ANIMS/LOKWSLI.ANI | 94 + CONTENT/BT3025/ANIMS/LOKWSRI.ANI | 94 + CONTENT/BT3025/ANIMS/LOKWWL.ANI | 76 + CONTENT/BT3025/ANIMS/LOKWWLI.ANI | 82 + CONTENT/BT3025/ANIMS/LOKWWR.ANI | 76 + CONTENT/BT3025/ANIMS/LOKWWRI.ANI | 82 + CONTENT/BT3025/ANIMS/OWNBMP.ANI | 80 + CONTENT/BT3025/ANIMS/OWNBMPI.ANI | 80 + CONTENT/BT3025/ANIMS/OWNSQI.ANI | 0 CONTENT/BT3025/ANIMS/OWNSQT.ANI | 0 CONTENT/BT3025/ANIMS/RAPBMP.ANI | 70 + CONTENT/BT3025/ANIMS/RAPBMPI.ANI | 75 + CONTENT/BT3025/ANIMS/RAPRWL.ANI | 87 + CONTENT/BT3025/ANIMS/RAPRWLI.ANI | 94 + CONTENT/BT3025/ANIMS/RAPRWR.ANI | 87 + CONTENT/BT3025/ANIMS/RAPRWRI.ANI | 94 + CONTENT/BT3025/ANIMS/SNDBBLI.ANI | 82 + CONTENT/BT3025/ANIMS/SNDBBRI.ANI | 82 + CONTENT/BT3025/ANIMS/SNDBMP.ANI | 80 + CONTENT/BT3025/ANIMS/SNDBMPI.ANI | 80 + CONTENT/BT3025/ANIMS/SNDBSLI.ANI | 82 + CONTENT/BT3025/ANIMS/SNDBSRI.ANI | 82 + CONTENT/BT3025/ANIMS/SNDTRN.ANI | 87 + CONTENT/BT3025/ANIMS/SNDTRNI.ANI | 94 + CONTENT/BT3025/ANIMS/SNDWSLI.ANI | 94 + CONTENT/BT3025/ANIMS/SNDWSRI.ANI | 94 + CONTENT/BT3025/ANIMS/SNDWWL.ANI | 76 + CONTENT/BT3025/ANIMS/SNDWWLI.ANI | 82 + CONTENT/BT3025/ANIMS/SNDWWR.ANI | 76 + CONTENT/BT3025/ANIMS/SNDWWRI.ANI | 82 + CONTENT/BT3025/ANIMS/THR4JERR.ANI | 0 CONTENT/BT3025/ANIMS/THRBBLI.ANI | 82 + CONTENT/BT3025/ANIMS/THRBBRI.ANI | 82 + CONTENT/BT3025/ANIMS/THRBMP.ANI | 80 + CONTENT/BT3025/ANIMS/THRBMPI.ANI | 80 + CONTENT/BT3025/ANIMS/THRBSLI.ANI | 82 + CONTENT/BT3025/ANIMS/THRBSRI.ANI | 82 + CONTENT/BT3025/ANIMS/THRCLI.ANI | 0 CONTENT/BT3025/ANIMS/THROPI.ANI | 0 CONTENT/BT3025/ANIMS/THRSQT.ANI | 0 CONTENT/BT3025/ANIMS/THRTRI.ANI | 0 CONTENT/BT3025/ANIMS/THRTRN.ANI | 87 + CONTENT/BT3025/ANIMS/THRTRNI.ANI | 94 + CONTENT/BT3025/ANIMS/THRTSI.ANI | 0 CONTENT/BT3025/ANIMS/THRTST.ANI | 0 CONTENT/BT3025/ANIMS/THRWSLI.ANI | 94 + CONTENT/BT3025/ANIMS/THRWSRI.ANI | 94 + CONTENT/BT3025/ANIMS/THRWWL.ANI | 76 + CONTENT/BT3025/ANIMS/THRWWLI.ANI | 82 + CONTENT/BT3025/ANIMS/THRWWR.ANI | 76 + CONTENT/BT3025/ANIMS/THRWWRI.ANI | 82 + CONTENT/BT3025/ARCBT.BAT | 58 + CONTENT/BT3025/ARCFILES.LST | 37 + CONTENT/BT3025/AUDIO/ABFWRN01.MID | Bin 0 -> 100 bytes CONTENT/BT3025/AUDIO/ABNTRG.SCP | 96 + CONTENT/BT3025/AUDIO/ACNCMP.SCP | 34 + CONTENT/BT3025/AUDIO/ACNCMPE.SCP | 13 + CONTENT/BT3025/AUDIO/ACNTRG.SCP | 12 + CONTENT/BT3025/AUDIO/ACNTRGE.SCP | 8 + CONTENT/BT3025/AUDIO/ALMINT.SCP | 78 + CONTENT/BT3025/AUDIO/AUDIO.INI | 53 + CONTENT/BT3025/AUDIO/AUDIOMR.INI | 53 + CONTENT/BT3025/AUDIO/AVA1EXT.SCP | 43 + CONTENT/BT3025/AUDIO/AVA1INT.SCP | 97 + CONTENT/BT3025/AUDIO/AVA2.SCP | 55 + CONTENT/BT3025/AUDIO/AVAEXT.SCP | 61 + CONTENT/BT3025/AUDIO/AVAINT.SCP | 109 + CONTENT/BT3025/AUDIO/BATEXT.SCP | 25 + CONTENT/BT3025/AUDIO/BATINT.SCP | 85 + CONTENT/BT3025/AUDIO/BHK1EXT.SCP | 43 + CONTENT/BT3025/AUDIO/BHK1INT.SCP | 85 + CONTENT/BT3025/AUDIO/BIGEXP.SCP | 91 + CONTENT/BT3025/AUDIO/BIGEXP01.MID | Bin 0 -> 91 bytes CONTENT/BT3025/AUDIO/BLKEXT.SCP | 61 + CONTENT/BT3025/AUDIO/BLKINT.SCP | 109 + CONTENT/BT3025/AUDIO/CALEXT.SCP | 49 + CONTENT/BT3025/AUDIO/CALINT.SCP | 91 + CONTENT/BT3025/AUDIO/CLKWRN01.MID | Bin 0 -> 100 bytes CONTENT/BT3025/AUDIO/CLTCMP.SCP | 74 + CONTENT/BT3025/AUDIO/CLTTRG.SCP | 63 + CONTENT/BT3025/AUDIO/CNDCMP.SCP | 49 + CONTENT/BT3025/AUDIO/CNDTRG.SCP | 46 + CONTENT/BT3025/AUDIO/COLEXT.SCP | 102 + CONTENT/BT3025/AUDIO/CRNEXP.SCP | 84 + CONTENT/BT3025/AUDIO/CTMIX.CFG | 15 + CONTENT/BT3025/AUDIO/DGAEXP.SCP | 47 + CONTENT/BT3025/AUDIO/DGBEXP.SCP | 47 + CONTENT/BT3025/AUDIO/DGCEXP.SCP | 48 + CONTENT/BT3025/AUDIO/DSTCMP.SCP | 38 + CONTENT/BT3025/AUDIO/DSTRD01.MID | Bin 0 -> 96 bytes CONTENT/BT3025/AUDIO/DSTRD02.MID | Bin 0 -> 79 bytes CONTENT/BT3025/AUDIO/DSTTRG.SCP | 22 + CONTENT/BT3025/AUDIO/EPCCMP.SCP | 57 + CONTENT/BT3025/AUDIO/EPPCMP.SCP | 48 + CONTENT/BT3025/AUDIO/EPPCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/EPPTRG.SCP | 12 + CONTENT/BT3025/AUDIO/EPPTRGE.SCP | 9 + CONTENT/BT3025/AUDIO/ERLCMP.SCP | 48 + CONTENT/BT3025/AUDIO/ERLCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/ERLTRG.SCP | 12 + CONTENT/BT3025/AUDIO/ERLTRGE.SCP | 8 + CONTENT/BT3025/AUDIO/ERMCMP.SCP | 49 + CONTENT/BT3025/AUDIO/ERMCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/ERMTRG.SCP | 12 + CONTENT/BT3025/AUDIO/ERMTRGE.SCP | 8 + CONTENT/BT3025/AUDIO/ERSCMP.SCP | 48 + CONTENT/BT3025/AUDIO/ERSCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/ERSTRG.SCP | 12 + CONTENT/BT3025/AUDIO/ERSTRGE.SCP | 8 + CONTENT/BT3025/AUDIO/FIND.TXT | 0 CONTENT/BT3025/AUDIO/FIREXT.SCP | 43 + CONTENT/BT3025/AUDIO/FIRINT.SCP | 79 + CONTENT/BT3025/AUDIO/GENCMP.SCP | 61 + CONTENT/BT3025/AUDIO/GENTRG.SCP | 65 + CONTENT/BT3025/AUDIO/GENWRN01.MID | Bin 0 -> 86 bytes CONTENT/BT3025/AUDIO/GENWRN02.MID | Bin 0 -> 86 bytes CONTENT/BT3025/AUDIO/GLRCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/GLRTRGE.SCP | 8 + CONTENT/BT3025/AUDIO/HETEXT.SCP | 39 + CONTENT/BT3025/AUDIO/HETINT.SCP | 85 + CONTENT/BT3025/AUDIO/ICOM.CFG | 15 + CONTENT/BT3025/AUDIO/INCARM01.MID | Bin 0 -> 107 bytes CONTENT/BT3025/AUDIO/JAKEXT.SCP | 49 + CONTENT/BT3025/AUDIO/JAKINT.SCP | 97 + CONTENT/BT3025/AUDIO/LACCMP.SCP | 38 + CONTENT/BT3025/AUDIO/LACTRG.SCP | 12 + CONTENT/BT3025/AUDIO/LEGWRN01.MID | Bin 0 -> 86 bytes CONTENT/BT3025/AUDIO/LLRCMP.SCP | 49 + CONTENT/BT3025/AUDIO/LLRCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/LLRTRG.SCP | 12 + CONTENT/BT3025/AUDIO/LLRTRGE.SCP | 9 + CONTENT/BT3025/AUDIO/LO1EXT.SCP | 67 + CONTENT/BT3025/AUDIO/LO1INT.SCP | 121 + CONTENT/BT3025/AUDIO/LOK1EXT.SCP | 61 + CONTENT/BT3025/AUDIO/LOK1INT.SCP | 103 + CONTENT/BT3025/AUDIO/LOK2EXT.SCP | 67 + CONTENT/BT3025/AUDIO/LOK2INT.SCP | 115 + CONTENT/BT3025/AUDIO/LOKEXT.SCP | 55 + CONTENT/BT3025/AUDIO/LOKINT.SCP | 97 + CONTENT/BT3025/AUDIO/LRMCMP.SCP | 32 + CONTENT/BT3025/AUDIO/LRMTRG.SCP | 12 + CONTENT/BT3025/AUDIO/LSRCMPE.SCP | 26 + CONTENT/BT3025/AUDIO/LSREXP.SCP | 109 + CONTENT/BT3025/AUDIO/LSRLDD01.MID | Bin 0 -> 77 bytes CONTENT/BT3025/AUDIO/LSRTRGE.SCP | 40 + CONTENT/BT3025/AUDIO/MACCMP.SCP | 38 + CONTENT/BT3025/AUDIO/MACTRG.SCP | 12 + CONTENT/BT3025/AUDIO/MAD1EXT.SCP | 55 + CONTENT/BT3025/AUDIO/MAD1INT.SCP | 103 + CONTENT/BT3025/AUDIO/MAD2EXT.SCP | 43 + CONTENT/BT3025/AUDIO/MAD2INT.SCP | 109 + CONTENT/BT3025/AUDIO/MADEXT.SCP | 43 + CONTENT/BT3025/AUDIO/MADINT.SCP | 91 + CONTENT/BT3025/AUDIO/MCHEXP03.MID | Bin 0 -> 155 bytes CONTENT/BT3025/AUDIO/MCHEXP04.MID | Bin 0 -> 155 bytes CONTENT/BT3025/AUDIO/MCHEXP05.MID | Bin 0 -> 155 bytes CONTENT/BT3025/AUDIO/MCHEXP06.MID | Bin 0 -> 123 bytes CONTENT/BT3025/AUDIO/MCHEXP07.MID | Bin 0 -> 108 bytes CONTENT/BT3025/AUDIO/MCHEXPI1.MID | Bin 0 -> 78 bytes CONTENT/BT3025/AUDIO/MCHEXPI2.MID | Bin 0 -> 80 bytes CONTENT/BT3025/AUDIO/MCHEXPI3.MID | Bin 0 -> 73 bytes CONTENT/BT3025/AUDIO/MCHEXT.SCP | 29 + CONTENT/BT3025/AUDIO/MCHFRE01.MID | Bin 0 -> 80 bytes CONTENT/BT3025/AUDIO/MCTINT.SCP | 15 + CONTENT/BT3025/AUDIO/MEDEXP.SCP | 92 + CONTENT/BT3025/AUDIO/MEDEXP01.MID | Bin 0 -> 78 bytes CONTENT/BT3025/AUDIO/MGNTRG.SCP | 74 + CONTENT/BT3025/AUDIO/MLRCMP.SCP | 49 + CONTENT/BT3025/AUDIO/MLRCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/MLRTRG.SCP | 12 + CONTENT/BT3025/AUDIO/MLRTRGE.SCP | 9 + CONTENT/BT3025/AUDIO/MSLEXP.SCP | 108 + CONTENT/BT3025/AUDIO/MSLJAM01.MID | Bin 0 -> 77 bytes CONTENT/BT3025/AUDIO/MSLLDD01.MID | Bin 0 -> 77 bytes CONTENT/BT3025/AUDIO/MSLMFR01.MID | Bin 0 -> 78 bytes CONTENT/BT3025/AUDIO/MSLTVL.SCP | 46 + CONTENT/BT3025/AUDIO/MYRCMP.SCP | 27 + CONTENT/BT3025/AUDIO/MYRTRG.SCP | 31 + CONTENT/BT3025/AUDIO/OWN1EXT.SCP | 37 + CONTENT/BT3025/AUDIO/OWN1INT.SCP | 85 + CONTENT/BT3025/AUDIO/OWNEXT.SCP | 49 + CONTENT/BT3025/AUDIO/OWNINT.SCP | 91 + CONTENT/BT3025/AUDIO/PLYINT.SCP | 88 + CONTENT/BT3025/AUDIO/PPCCMP.SCP | 48 + CONTENT/BT3025/AUDIO/PPCCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/PPCEXP.SCP | 108 + CONTENT/BT3025/AUDIO/PPCEXPI.SCP | 109 + CONTENT/BT3025/AUDIO/PPCTRG.SCP | 12 + CONTENT/BT3025/AUDIO/PPCTRGE.SCP | 9 + CONTENT/BT3025/AUDIO/PRGBUT01.MID | Bin 0 -> 77 bytes CONTENT/BT3025/AUDIO/PRJCMPE.SCP | 26 + CONTENT/BT3025/AUDIO/PRJJAM01.MID | Bin 0 -> 77 bytes CONTENT/BT3025/AUDIO/PRJLDD01.MID | Bin 0 -> 77 bytes CONTENT/BT3025/AUDIO/PRJMFR01.MID | Bin 0 -> 78 bytes CONTENT/BT3025/AUDIO/PRJTRGE.SCP | 23 + CONTENT/BT3025/AUDIO/PRJTVL.SCP | 46 + CONTENT/BT3025/AUDIO/RAPEXT.SCP | 37 + CONTENT/BT3025/AUDIO/RAPINT.SCP | 91 + CONTENT/BT3025/AUDIO/SACCMP.SCP | 38 + CONTENT/BT3025/AUDIO/SACTRG.SCP | 12 + CONTENT/BT3025/AUDIO/SLRCMP.SCP | 49 + CONTENT/BT3025/AUDIO/SLRCMPE.SCP | 14 + CONTENT/BT3025/AUDIO/SLRTRG.SCP | 12 + CONTENT/BT3025/AUDIO/SLRTRGE.SCP | 9 + CONTENT/BT3025/AUDIO/SMLEXP.SCP | 108 + CONTENT/BT3025/AUDIO/SND1EXT.SCP | 49 + CONTENT/BT3025/AUDIO/SND1INT.SCP | 85 + CONTENT/BT3025/AUDIO/SND2EXT.SCP | 73 + CONTENT/BT3025/AUDIO/SND2INT.SCP | 115 + CONTENT/BT3025/AUDIO/SNDEXT.SCP | 67 + CONTENT/BT3025/AUDIO/SNDINT.SCP | 121 + CONTENT/BT3025/AUDIO/SNRTRG.SCP | 12 + CONTENT/BT3025/AUDIO/SRMCMP.SCP | 33 + CONTENT/BT3025/AUDIO/SRMTRG.SCP | 12 + CONTENT/BT3025/AUDIO/STATIC.SCP | 14 + CONTENT/BT3025/AUDIO/STIEXT.SCP | 37 + CONTENT/BT3025/AUDIO/STIINT.SCP | 79 + CONTENT/BT3025/AUDIO/THR1EXT.SCP | 67 + CONTENT/BT3025/AUDIO/THR1INT.SCP | 109 + CONTENT/BT3025/AUDIO/THR6EXT.SCP | 73 + CONTENT/BT3025/AUDIO/THR6INT.SCP | 139 + CONTENT/BT3025/AUDIO/THREXT.SCP | 49 + CONTENT/BT3025/AUDIO/THRINT.SCP | 91 + CONTENT/BT3025/AUDIO/TRSEXT.SCP | 52 + CONTENT/BT3025/AUDIO/TRSINT.SCP | 85 + CONTENT/BT3025/AUDIO/VUL1EXT.SCP | 49 + CONTENT/BT3025/AUDIO/VUL1INT.SCP | 91 + CONTENT/BT3025/AUDIO/VUL2EXT.SCP | 37 + CONTENT/BT3025/AUDIO/VUL2INT.SCP | 121 + CONTENT/BT3025/AUDIO/VULEXT.SCP | 49 + CONTENT/BT3025/AUDIO/VULINT.SCP | 97 + CONTENT/BT3025/AUDIO/WNDEXT01.SCP | 80 + CONTENT/BT3025/AUDIO/WPNINT.SCP | 113 + CONTENT/BT3025/AUTOEXEC.BAT | 22 + CONTENT/BT3025/BT.BAT | 24 + CONTENT/BT3025/BTCAM.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM01.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM02.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM03.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM04.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM05.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM06.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM07.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM08.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM09.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM10.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM11.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM12.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM13.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM14.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM15.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM16.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM17.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM18.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM19.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM20.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM21.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM22.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM23.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM24.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM25.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM26.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM27.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM28.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM29.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM30.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM31.BAT | 43 + CONTENT/BT3025/BTCAM/BTCAM32.BAT | 43 + CONTENT/BT3025/BTGO.BAT | 9 + CONTENT/BT3025/BTLOOK.BAT | 12 + CONTENT/BT3025/BTNET.BAT | 22 + CONTENT/BT3025/BTPREP.BAT | 44 + CONTENT/BT3025/BUILD.BAT | 6 + CONTENT/BT3025/BUILD1.BAT | 82 + CONTENT/BT3025/DEARCBT.BAT | 19 + CONTENT/BT3025/EXCLUDE.LST | 7 + CONTENT/BT3025/FAILURE.LOG | 12 + CONTENT/BT3025/GAUGE/AB01_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AB02_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AB03_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AB04_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AB05_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AB06_GA.GIM | 29 + CONTENT/BT3025/GAUGE/AB07_GA.GIM | 20 + CONTENT/BT3025/GAUGE/AB08_GA.GIM | 16 + CONTENT/BT3025/GAUGE/AB09_GA.GIM | 25 + CONTENT/BT3025/GAUGE/AB10_GA.GIM | 29 + CONTENT/BT3025/GAUGE/AD01_GA.GIM | 40 + CONTENT/BT3025/GAUGE/ADPAL.PCC | Bin 0 -> 907 bytes CONTENT/BT3025/GAUGE/ADPAL2.PCC | Bin 0 -> 907 bytes CONTENT/BT3025/GAUGE/APC.GIM | 15 + CONTENT/BT3025/GAUGE/AR01_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AR02_GA.GIM | 24 + CONTENT/BT3025/GAUGE/AR03_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AR04_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AR05_GA.GIM | 15 + CONTENT/BT3025/GAUGE/ARENA_GA.GIM | 70 + CONTENT/BT3025/GAUGE/ARMRMOVR.GIM | 15 + CONTENT/BT3025/GAUGE/AW01_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AW02_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AW03_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AW04_GA.GIM | 15 + CONTENT/BT3025/GAUGE/AW05_GA.GIM | 19 + CONTENT/BT3025/GAUGE/BDUCK.PCC | Bin 0 -> 2466 bytes CONTENT/BT3025/GAUGE/BLD03_GA.GIM | 26 + CONTENT/BT3025/GAUGE/BLD04_GA.GIM | 24 + CONTENT/BT3025/GAUGE/BLD06_GA.GIM | 50 + CONTENT/BT3025/GAUGE/BLD20_GA.GIM | 33 + CONTENT/BT3025/GAUGE/BLD24_GA.GIM | 20 + CONTENT/BT3025/GAUGE/BLD26_GA.GIM | 15 + CONTENT/BT3025/GAUGE/BLD27_GA.GIM | 45 + CONTENT/BT3025/GAUGE/BLH_GA.GIM | 21 + CONTENT/BT3025/GAUGE/BNK_GA.GIM | 24 + CONTENT/BT3025/GAUGE/BTEBUS.PCC | Bin 0 -> 2028 bytes CONTENT/BT3025/GAUGE/BTECMODE.PCC | Bin 0 -> 1630 bytes CONTENT/BT3025/GAUGE/BTEFIRE.PCC | Bin 0 -> 1773 bytes CONTENT/BT3025/GAUGE/BTEHFAIL.PCC | Bin 0 -> 1952 bytes CONTENT/BT3025/GAUGE/BTEJAM.PCC | Bin 0 -> 1820 bytes CONTENT/BT3025/GAUGE/BTELOOP.PCC | Bin 0 -> 2210 bytes CONTENT/BT3025/GAUGE/BTEPFAIL.PCC | Bin 0 -> 2192 bytes CONTENT/BT3025/GAUGE/BTESFAIL.PCC | Bin 0 -> 2185 bytes CONTENT/BT3025/GAUGE/BTESLEV.PCC | Bin 0 -> 1312 bytes CONTENT/BT3025/GAUGE/BTESRNGE.PCC | Bin 0 -> 1711 bytes CONTENT/BT3025/GAUGE/BTEUNJM.PCC | Bin 0 -> 1485 bytes CONTENT/BT3025/GAUGE/BTOPAL.PCC | Bin 0 -> 913 bytes CONTENT/BT3025/GAUGE/BTPBUS.PCC | Bin 0 -> 1499 bytes CONTENT/BT3025/GAUGE/BTPLOOP.PCC | Bin 0 -> 1579 bytes CONTENT/BT3025/GAUGE/BTSPAL.PCC | Bin 0 -> 916 bytes CONTENT/BT3025/GAUGE/BTWARN.PCC | Bin 0 -> 1441 bytes CONTENT/BT3025/GAUGE/BULLDOG.GIM | 15 + CONTENT/BT3025/GAUGE/BUTTEA_G.GIM | 27 + CONTENT/BT3025/GAUGE/BUTTEB_G.GIM | 27 + CONTENT/BT3025/GAUGE/BUTTEC_G.GIM | 27 + CONTENT/BT3025/GAUGE/BUTTED_G.GIM | 27 + CONTENT/BT3025/GAUGE/BUTTEE_G.GIM | 27 + CONTENT/BT3025/GAUGE/CALPB_GA.GIM | 15 + CONTENT/BT3025/GAUGE/CALP_GA.GIM | 15 + CONTENT/BT3025/GAUGE/CM_BOTH.PCC | Bin 0 -> 1058 bytes CONTENT/BT3025/GAUGE/CM_OFF.PCC | Bin 0 -> 1005 bytes CONTENT/BT3025/GAUGE/CM_ONLY.PCC | Bin 0 -> 995 bytes CONTENT/BT3025/GAUGE/CM_OTHER.PCC | Bin 0 -> 1141 bytes CONTENT/BT3025/GAUGE/COMTRUCK.GIM | 15 + CONTENT/BT3025/GAUGE/COOLANT.GIM | 15 + CONTENT/BT3025/GAUGE/DISH_GA.GIM | 15 + CONTENT/BT3025/GAUGE/DOZER.GIM | 15 + CONTENT/BT3025/GAUGE/EAFC10.PCC | Bin 0 -> 2193 bytes CONTENT/BT3025/GAUGE/EAFC100.PCC | Bin 0 -> 2372 bytes CONTENT/BT3025/GAUGE/EAFC25.PCC | Bin 0 -> 2243 bytes CONTENT/BT3025/GAUGE/EAFC5.PCC | Bin 0 -> 2212 bytes CONTENT/BT3025/GAUGE/EAFC50.PCC | Bin 0 -> 2240 bytes CONTENT/BT3025/GAUGE/EDESTRYD.PCC | Bin 0 -> 1795 bytes CONTENT/BT3025/GAUGE/EERLLAS.PCC | Bin 0 -> 2558 bytes CONTENT/BT3025/GAUGE/EERPPC.PCC | Bin 0 -> 2234 bytes CONTENT/BT3025/GAUGE/EERSLAS.PCC | Bin 0 -> 2461 bytes CONTENT/BT3025/GAUGE/ELBX10.PCC | Bin 0 -> 2193 bytes CONTENT/BT3025/GAUGE/ELBX100.PCC | Bin 0 -> 2372 bytes CONTENT/BT3025/GAUGE/ELBX25.PCC | Bin 0 -> 2243 bytes CONTENT/BT3025/GAUGE/ELBX5.PCC | Bin 0 -> 2212 bytes CONTENT/BT3025/GAUGE/ELEAK.PCC | Bin 0 -> 1191 bytes CONTENT/BT3025/GAUGE/ELLAS.PCC | Bin 0 -> 2420 bytes CONTENT/BT3025/GAUGE/ELRM10.PCC | Bin 0 -> 2475 bytes CONTENT/BT3025/GAUGE/ELRM15.PCC | Bin 0 -> 2442 bytes CONTENT/BT3025/GAUGE/ELRM20.PCC | Bin 0 -> 2487 bytes CONTENT/BT3025/GAUGE/ELRM5.PCC | Bin 0 -> 2370 bytes CONTENT/BT3025/GAUGE/EMG.PCC | Bin 0 -> 2125 bytes CONTENT/BT3025/GAUGE/ENRK15.PCC | Bin 0 -> 2530 bytes CONTENT/BT3025/GAUGE/ENRK5.PCC | Bin 0 -> 2458 bytes CONTENT/BT3025/GAUGE/EPPC.PCC | Bin 0 -> 2093 bytes CONTENT/BT3025/GAUGE/ESCND.PCC | Bin 0 -> 1102 bytes CONTENT/BT3025/GAUGE/ESENSORS.PCC | Bin 0 -> 2378 bytes CONTENT/BT3025/GAUGE/ESRM2.PCC | Bin 0 -> 2348 bytes CONTENT/BT3025/GAUGE/ESRM4.PCC | Bin 0 -> 2359 bytes CONTENT/BT3025/GAUGE/ESRM6.PCC | Bin 0 -> 2371 bytes CONTENT/BT3025/GAUGE/ESTRK2.PCC | Bin 0 -> 2476 bytes CONTENT/BT3025/GAUGE/ESTRK4.PCC | Bin 0 -> 2480 bytes CONTENT/BT3025/GAUGE/ESTRK6.PCC | Bin 0 -> 2494 bytes CONTENT/BT3025/GAUGE/EVOLT.PCC | Bin 0 -> 1269 bytes CONTENT/BT3025/GAUGE/FP1_GA.GIM | 78 + CONTENT/BT3025/GAUGE/FP2_GA.GIM | 25 + CONTENT/BT3025/GAUGE/FT1_GA.GIM | 29 + CONTENT/BT3025/GAUGE/FT2_GA.GIM | 24 + CONTENT/BT3025/GAUGE/GAUGE.GAT | 75 + CONTENT/BT3025/GAUGE/GNR_GA.GIM | 15 + CONTENT/BT3025/GAUGE/HARASSER.GIM | 15 + CONTENT/BT3025/GAUGE/HEATPAL.PCC | Bin 0 -> 905 bytes CONTENT/BT3025/GAUGE/HEATPAL2.PCC | Bin 0 -> 915 bytes CONTENT/BT3025/GAUGE/HELV15.PCC | Bin 0 -> 1546 bytes CONTENT/BT3025/GAUGE/HELV18.PCC | Bin 0 -> 1660 bytes CONTENT/BT3025/GAUGE/HILLG1_G.GIM | 50 + CONTENT/BT3025/GAUGE/HILLG2_G.GIM | 36 + CONTENT/BT3025/GAUGE/HILLG3_G.GIM | 36 + CONTENT/BT3025/GAUGE/HL1_GA.GIM | 31 + CONTENT/BT3025/GAUGE/HL2_GA.GIM | 26 + CONTENT/BT3025/GAUGE/HN1_GA.GIM | 26 + CONTENT/BT3025/GAUGE/HUMMER.GIM | 15 + CONTENT/BT3025/GAUGE/HUT_GA.GIM | 24 + CONTENT/BT3025/GAUGE/HWZ_GA.GIM | 25 + CONTENT/BT3025/GAUGE/JAK_GA.GIM | 21 + CONTENT/BT3025/GAUGE/L4GAUGE.INI | 36 + CONTENT/BT3025/GAUGE/LRMCARRY.GIM | 15 + CONTENT/BT3025/GAUGE/MECHMOVR.GIM | 15 + CONTENT/BT3025/GAUGE/MRPAL.PCC | Bin 0 -> 907 bytes CONTENT/BT3025/GAUGE/MSLG_GA.GIM | 35 + CONTENT/BT3025/GAUGE/MSLR_GA.GIM | 63 + CONTENT/BT3025/GAUGE/PDSH_GA.GIM | 23 + CONTENT/BT3025/GAUGE/PGN_GA.GIM | 30 + CONTENT/BT3025/GAUGE/QAFC10.PCC | Bin 0 -> 2193 bytes CONTENT/BT3025/GAUGE/QAFC100.PCC | Bin 0 -> 2372 bytes CONTENT/BT3025/GAUGE/QAFC25.PCC | Bin 0 -> 2243 bytes CONTENT/BT3025/GAUGE/QAFC5.PCC | Bin 0 -> 2212 bytes CONTENT/BT3025/GAUGE/QAFC50.PCC | Bin 0 -> 2240 bytes CONTENT/BT3025/GAUGE/QCIRCLE.PCC | Bin 0 -> 1268 bytes CONTENT/BT3025/GAUGE/QCIRCR.PCC | Bin 0 -> 1556 bytes CONTENT/BT3025/GAUGE/QERLLAS.PCC | Bin 0 -> 2558 bytes CONTENT/BT3025/GAUGE/QERPPC.PCC | Bin 0 -> 2234 bytes CONTENT/BT3025/GAUGE/QERSLAS.PCC | Bin 0 -> 2461 bytes CONTENT/BT3025/GAUGE/QFIR0.PCC | Bin 0 -> 2473 bytes CONTENT/BT3025/GAUGE/QLBX10.PCC | Bin 0 -> 2193 bytes CONTENT/BT3025/GAUGE/QLBX100.PCC | Bin 0 -> 2372 bytes CONTENT/BT3025/GAUGE/QLBX25.PCC | Bin 0 -> 2243 bytes CONTENT/BT3025/GAUGE/QLBX5.PCC | Bin 0 -> 2212 bytes CONTENT/BT3025/GAUGE/QLBX50.PCC | Bin 0 -> 2240 bytes CONTENT/BT3025/GAUGE/QLLAS.PCC | Bin 0 -> 2420 bytes CONTENT/BT3025/GAUGE/QLRM10.PCC | Bin 0 -> 2475 bytes CONTENT/BT3025/GAUGE/QLRM15.PCC | Bin 0 -> 2442 bytes CONTENT/BT3025/GAUGE/QLRM20.PCC | Bin 0 -> 2487 bytes CONTENT/BT3025/GAUGE/QLRM5.PCC | Bin 0 -> 2370 bytes CONTENT/BT3025/GAUGE/QMG.PCC | Bin 0 -> 2125 bytes CONTENT/BT3025/GAUGE/QNRK15.PCC | Bin 0 -> 2530 bytes CONTENT/BT3025/GAUGE/QNRK5.PCC | Bin 0 -> 2458 bytes CONTENT/BT3025/GAUGE/QPPC.PCC | Bin 0 -> 2093 bytes CONTENT/BT3025/GAUGE/QSENSORS.PCC | Bin 0 -> 2378 bytes CONTENT/BT3025/GAUGE/QSLASER.PCC | Bin 0 -> 2510 bytes CONTENT/BT3025/GAUGE/QSRM2.PCC | Bin 0 -> 2348 bytes CONTENT/BT3025/GAUGE/QSRM4.PCC | Bin 0 -> 2359 bytes CONTENT/BT3025/GAUGE/QSRM6.PCC | Bin 0 -> 2371 bytes CONTENT/BT3025/GAUGE/QSTRK2.PCC | Bin 0 -> 2476 bytes CONTENT/BT3025/GAUGE/QSTRK4.PCC | Bin 0 -> 2480 bytes CONTENT/BT3025/GAUGE/QSTRK6.PCC | Bin 0 -> 2494 bytes CONTENT/BT3025/GAUGE/RAP_GA.GIM | 21 + CONTENT/BT3025/GAUGE/RESULT2.TXT | 5 + CONTENT/BT3025/GAUGE/RIVET_GA.GIM | 18 + CONTENT/BT3025/GAUGE/RK1_GA.GIM | 38 + CONTENT/BT3025/GAUGE/RK2_GA.GIM | 22 + CONTENT/BT3025/GAUGE/RK3_GA.GIM | 23 + CONTENT/BT3025/GAUGE/RK4_GA.GIM | 22 + CONTENT/BT3025/GAUGE/RK5_GA.GIM | 25 + CONTENT/BT3025/GAUGE/RK6_GA.GIM | 26 + CONTENT/BT3025/GAUGE/RK7_GA.GIM | 24 + CONTENT/BT3025/GAUGE/ROMMEL.GIM | 15 + CONTENT/BT3025/GAUGE/SB1E_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SB1N_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SB1S_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SB1W_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SB3S_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SEMI.GIM | 15 + CONTENT/BT3025/GAUGE/SEMIRIG.GIM | 15 + CONTENT/BT3025/GAUGE/SGEN1.PCC | Bin 0 -> 945 bytes CONTENT/BT3025/GAUGE/SGEN2.PCC | Bin 0 -> 937 bytes CONTENT/BT3025/GAUGE/SGEN3.PCC | Bin 0 -> 939 bytes CONTENT/BT3025/GAUGE/SGEN4.PCC | Bin 0 -> 945 bytes CONTENT/BT3025/GAUGE/SGEN5.PCC | Bin 0 -> 937 bytes CONTENT/BT3025/GAUGE/SGEN6.PCC | Bin 0 -> 948 bytes CONTENT/BT3025/GAUGE/SGENA.PCC | Bin 0 -> 1121 bytes CONTENT/BT3025/GAUGE/SGENB.PCC | Bin 0 -> 1131 bytes CONTENT/BT3025/GAUGE/SGENBG.PCC | Bin 0 -> 1230 bytes CONTENT/BT3025/GAUGE/SGENC.PCC | Bin 0 -> 1101 bytes CONTENT/BT3025/GAUGE/SGEND.PCC | Bin 0 -> 1115 bytes CONTENT/BT3025/GAUGE/SGENLEAK.PCC | Bin 0 -> 971 bytes CONTENT/BT3025/GAUGE/SGENTEMP.PCC | Bin 0 -> 1293 bytes CONTENT/BT3025/GAUGE/SGENVOLT.PCC | Bin 0 -> 1046 bytes CONTENT/BT3025/GAUGE/SIZUMIN.PCC | Bin 0 -> 1905 bytes CONTENT/BT3025/GAUGE/SIZUMOUT.PCC | Bin 0 -> 1833 bytes CONTENT/BT3025/GAUGE/SMLFONT.PCC | Bin 0 -> 1901 bytes CONTENT/BT3025/GAUGE/SR1E_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SR1N_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SR1S_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SR1W_GA.GIM | 13 + CONTENT/BT3025/GAUGE/SRMCARRY.GIM | 15 + CONTENT/BT3025/GAUGE/ST1_GA.GIM | 15 + CONTENT/BT3025/GAUGE/STB_GA.GIM | 18 + CONTENT/BT3025/GAUGE/STF_GA.GIM | 15 + CONTENT/BT3025/GAUGE/STH_GA.GIM | 27 + CONTENT/BT3025/GAUGE/STI_GA.GIM | 21 + CONTENT/BT3025/GAUGE/STRIKER.GIM | 15 + CONTENT/BT3025/GAUGE/STS_GA.GIM | 15 + CONTENT/BT3025/GAUGE/STT_GA.GIM | 27 + CONTENT/BT3025/GAUGE/SVISION.PCC | Bin 0 -> 1788 bytes CONTENT/BT3025/GAUGE/SW1_GA.GIM | 17 + CONTENT/BT3025/GAUGE/SW2_GA.GIM | 20 + CONTENT/BT3025/GAUGE/SW3_GA.GIM | 15 + CONTENT/BT3025/GAUGE/SW4_GA.GIM | 17 + CONTENT/BT3025/GAUGE/SW5_GA.GIM | 20 + CONTENT/BT3025/GAUGE/SW6_GA.GIM | 15 + CONTENT/BT3025/GAUGE/SWIFTWND.GIM | 15 + CONTENT/BT3025/GAUGE/THOR_GA.GIM | 21 + CONTENT/BT3025/GAUGE/TINYFONT.PCC | Bin 0 -> 1191 bytes CONTENT/BT3025/GAUGE/TMC1_GA.GIM | 25 + CONTENT/BT3025/GAUGE/TMC2_GA.GIM | 17 + CONTENT/BT3025/GAUGE/TNT_GA.GIM | 27 + CONTENT/BT3025/GAUGE/TREE_GA.GIM | 19 + CONTENT/BT3025/GAUGE/TWR_GA.GIM | 28 + CONTENT/BT3025/GAUGE/WALL1_GA.GIM | 16 + CONTENT/BT3025/GAUGE/WALL2_GA.GIM | 16 + CONTENT/BT3025/GAUGE/WALL3_GA.GIM | 25 + CONTENT/BT3025/GAUGE/WST_GA.GIM | 27 + CONTENT/BT3025/GAUGE/X_GA.GIM | 18 + CONTENT/BT3025/GO.BAT | 1 + CONTENT/BT3025/JOYSTICK.INI | 587 ++ CONTENT/BT3025/LAST.EGG | 229 + CONTENT/BT3025/MAKEEGG.BAT | 97 + CONTENT/BT3025/MAPS/ADROP.MAP | 32 + CONTENT/BT3025/MAPS/ALL.ZNE | 28 + CONTENT/BT3025/MAPS/ARENA1.MAP | 20 + CONTENT/BT3025/MAPS/ARENA2.MAP | 21 + CONTENT/BT3025/MAPS/BLANK.MAP | 21 + CONTENT/BT3025/MAPS/PDROP.MAP | 27 + CONTENT/BT3025/MAPS/POL3SFX.MAP | 23 + CONTENT/BT3025/MAPS/POL4DROP.MAP | 33 + CONTENT/BT3025/MAPS/POL4SFX.MAP | 23 + CONTENT/BT3025/MAPS/TEST.MAP | 59 + CONTENT/BT3025/MAPS/TEST1.MAP | 31 + CONTENT/BT3025/MAPS/TEST5.MAP | 21 + CONTENT/BT3025/MENU.BAT | 28 + CONTENT/BT3025/MODELS/AB01.MOD | 12 + CONTENT/BT3025/MODELS/AB02.MOD | 12 + CONTENT/BT3025/MODELS/AB03.MOD | 12 + CONTENT/BT3025/MODELS/AB04.MOD | 12 + CONTENT/BT3025/MODELS/AB05.MOD | 12 + CONTENT/BT3025/MODELS/AB06.MOD | 12 + CONTENT/BT3025/MODELS/AB06D.MOD | 12 + CONTENT/BT3025/MODELS/AB07.MOD | 17 + CONTENT/BT3025/MODELS/AB08.MOD | 8 + CONTENT/BT3025/MODELS/AB09.MOD | 13 + CONTENT/BT3025/MODELS/AB09D.MOD | 13 + CONTENT/BT3025/MODELS/AB10.MOD | 12 + CONTENT/BT3025/MODELS/AB10D.MOD | 12 + CONTENT/BT3025/MODELS/ACT01.MOD | 5 + CONTENT/BT3025/MODELS/ACT02.MOD | 5 + CONTENT/BT3025/MODELS/ACT03.MOD | 5 + CONTENT/BT3025/MODELS/ACT04.MOD | 5 + CONTENT/BT3025/MODELS/ACT05.MOD | 5 + CONTENT/BT3025/MODELS/AD01.MOD | 8 + CONTENT/BT3025/MODELS/ADSUP1.MOD | 5 + CONTENT/BT3025/MODELS/ADSUP2.MOD | 5 + CONTENT/BT3025/MODELS/ADWLK1.MOD | 12 + CONTENT/BT3025/MODELS/ADWLK2.MOD | 12 + CONTENT/BT3025/MODELS/ADWLK3.MOD | 12 + CONTENT/BT3025/MODELS/AFC100.SUB | 31 + CONTENT/BT3025/MODELS/AFC25.SUB | 31 + CONTENT/BT3025/MODELS/AFC5.SUB | 31 + CONTENT/BT3025/MODELS/AFC50.SUB | 31 + CONTENT/BT3025/MODELS/AFLOOR.MOD | 8 + CONTENT/BT3025/MODELS/AMAFC100.SUB | 14 + CONTENT/BT3025/MODELS/AMBSSDOR.MOD | 8 + CONTENT/BT3025/MODELS/AMLBX100.SUB | 16 + CONTENT/BT3025/MODELS/AMMAFC25.SUB | 14 + CONTENT/BT3025/MODELS/AMMAFC5.SUB | 14 + CONTENT/BT3025/MODELS/AMMAFC50.SUB | 14 + CONTENT/BT3025/MODELS/AMMLBX25.SUB | 16 + CONTENT/BT3025/MODELS/AMMLBX5.SUB | 16 + CONTENT/BT3025/MODELS/AMMLBX50.SUB | 16 + CONTENT/BT3025/MODELS/AMMLRM10.SUB | 16 + CONTENT/BT3025/MODELS/AMMLRM15.SUB | 16 + CONTENT/BT3025/MODELS/AMMLRM20.SUB | 16 + CONTENT/BT3025/MODELS/AMMLRM5.SUB | 16 + CONTENT/BT3025/MODELS/AMMNRK10.SUB | 16 + CONTENT/BT3025/MODELS/AMMNRK15.SUB | 16 + CONTENT/BT3025/MODELS/AMMNRK20.SUB | 16 + CONTENT/BT3025/MODELS/AMMNRK5.SUB | 16 + CONTENT/BT3025/MODELS/AMMOAC.SUB | 15 + CONTENT/BT3025/MODELS/AMMOAC10.SUB | 14 + CONTENT/BT3025/MODELS/AMMOGAUS.SUB | 14 + CONTENT/BT3025/MODELS/AMMOMG.SUB | 16 + CONTENT/BT3025/MODELS/AMMSRM2.SUB | 16 + CONTENT/BT3025/MODELS/AMMSRM25.SUB | 16 + CONTENT/BT3025/MODELS/AMMSRM30.SUB | 16 + CONTENT/BT3025/MODELS/AMMSRM4.SUB | 16 + CONTENT/BT3025/MODELS/AMMSRM6.SUB | 16 + CONTENT/BT3025/MODELS/AMMSTRK2.SUB | 16 + CONTENT/BT3025/MODELS/AMMSTRK4.SUB | 16 + CONTENT/BT3025/MODELS/AMMSTRK6.SUB | 16 + CONTENT/BT3025/MODELS/APC.MOD | 17 + CONTENT/BT3025/MODELS/AR01.MOD | 12 + CONTENT/BT3025/MODELS/AR02.MOD | 12 + CONTENT/BT3025/MODELS/AR03.MOD | 12 + CONTENT/BT3025/MODELS/AR04.MOD | 12 + CONTENT/BT3025/MODELS/AR05.MOD | 12 + CONTENT/BT3025/MODELS/ARBAN1.MOD | 12 + CONTENT/BT3025/MODELS/ARBAN2.MOD | 12 + CONTENT/BT3025/MODELS/ARBAN3.MOD | 12 + CONTENT/BT3025/MODELS/ARBAN4.MOD | 12 + CONTENT/BT3025/MODELS/ARBAN5.MOD | 12 + CONTENT/BT3025/MODELS/ARBAN6.MOD | 12 + CONTENT/BT3025/MODELS/ARCLD.MOD | 5 + CONTENT/BT3025/MODELS/ARENA.MOD | 11 + CONTENT/BT3025/MODELS/ARHORIZ.MOD | 5 + CONTENT/BT3025/MODELS/ARLID.MOD | 8 + CONTENT/BT3025/MODELS/ARMOR1.DMG | 4 + CONTENT/BT3025/MODELS/ARMRMOVR.MOD | 17 + CONTENT/BT3025/MODELS/ARWC.MOD | 5 + CONTENT/BT3025/MODELS/ATTACKER.MOD | 8 + CONTENT/BT3025/MODELS/AVA1DEAD.MOD | 9 + CONTENT/BT3025/MODELS/AVA1DMG.EXP | 28 + CONTENT/BT3025/MODELS/AVA1THR.CTL | 57 + CONTENT/BT3025/MODELS/AVA2DEAD.MOD | 9 + CONTENT/BT3025/MODELS/AVA2DMG.EXP | 28 + CONTENT/BT3025/MODELS/AVA2THR.CTL | 81 + CONTENT/BT3025/MODELS/AVADEAD.MOD | 9 + CONTENT/BT3025/MODELS/AVADMG.EXP | 28 + CONTENT/BT3025/MODELS/AVATHR.CTL | 75 + CONTENT/BT3025/MODELS/AW01.MOD | 8 + CONTENT/BT3025/MODELS/AW02.MOD | 8 + CONTENT/BT3025/MODELS/AW03.MOD | 11 + CONTENT/BT3025/MODELS/AW04.MOD | 8 + CONTENT/BT3025/MODELS/AW05.MOD | 12 + CONTENT/BT3025/MODELS/AWBOX1.MOD | 8 + CONTENT/BT3025/MODELS/AWWLK1.MOD | 9 + CONTENT/BT3025/MODELS/BAC1.MOD | 12 + CONTENT/BT3025/MODELS/BATDMG.EXP | 28 + CONTENT/BT3025/MODELS/BATTHR.CTL | 57 + CONTENT/BT3025/MODELS/BCOR1.MOD | 8 + CONTENT/BT3025/MODELS/BCOR2.MOD | 8 + CONTENT/BT3025/MODELS/BDET1.MOD | 5 + CONTENT/BT3025/MODELS/BDET2.MOD | 5 + CONTENT/BT3025/MODELS/BDET3.MOD | 5 + CONTENT/BT3025/MODELS/BDET4.MOD | 12 + CONTENT/BT3025/MODELS/BDET6.MOD | 5 + CONTENT/BT3025/MODELS/BHK1DEAD.MOD | 9 + CONTENT/BT3025/MODELS/BHK1DMG.EXP | 28 + CONTENT/BT3025/MODELS/BHK1THR.CTL | 63 + CONTENT/BT3025/MODELS/BIGDEAD.MOD | 11 + CONTENT/BT3025/MODELS/BLD.MOD | 20 + CONTENT/BT3025/MODELS/BLD01.MOD | 10 + CONTENT/BT3025/MODELS/BLD02.MOD | 10 + CONTENT/BT3025/MODELS/BLD03.MOD | 18 + CONTENT/BT3025/MODELS/BLD04.MOD | 20 + CONTENT/BT3025/MODELS/BLD05.MOD | 9 + CONTENT/BT3025/MODELS/BLD06.MOD | 15 + CONTENT/BT3025/MODELS/BLD08.MOD | 14 + CONTENT/BT3025/MODELS/BLD20.MOD | 20 + CONTENT/BT3025/MODELS/BLD24.MOD | 20 + CONTENT/BT3025/MODELS/BLD26.MOD | 21 + CONTENT/BT3025/MODELS/BLD27.MOD | 14 + CONTENT/BT3025/MODELS/BLHDEAD.MOD | 9 + CONTENT/BT3025/MODELS/BLHDMG.EXP | 28 + CONTENT/BT3025/MODELS/BLHTHR.CTL | 81 + CONTENT/BT3025/MODELS/BNK.MOD | 20 + CONTENT/BT3025/MODELS/BPIP1.MOD | 12 + CONTENT/BT3025/MODELS/BULLDOG.MOD | 18 + CONTENT/BT3025/MODELS/BUTTEA.MOD | 11 + CONTENT/BT3025/MODELS/BUTTEB.MOD | 11 + CONTENT/BT3025/MODELS/BUTTEC.MOD | 11 + CONTENT/BT3025/MODELS/BUTTED.MOD | 11 + CONTENT/BT3025/MODELS/BUTTEE.MOD | 11 + CONTENT/BT3025/MODELS/BUTTEEU.MOD | 5 + CONTENT/BT3025/MODELS/BUTTEF.MOD | 9 + CONTENT/BT3025/MODELS/BWLK1.MOD | 12 + CONTENT/BT3025/MODELS/CALP.DMG | 34 + CONTENT/BT3025/MODELS/CALP.MOD | 20 + CONTENT/BT3025/MODELS/CALPB.MOD | 11 + CONTENT/BT3025/MODELS/CAMERA.MOD | 13 + CONTENT/BT3025/MODELS/CAMPOS.MOD | 8 + CONTENT/BT3025/MODELS/CANHIT.MOD | 11 + CONTENT/BT3025/MODELS/CANHITI.MOD | 10 + CONTENT/BT3025/MODELS/CB1.MOD | 8 + CONTENT/BT3025/MODELS/CLD.MOD | 5 + CONTENT/BT3025/MODELS/COMTRUCK.MOD | 17 + CONTENT/BT3025/MODELS/CONDENSR.SUB | 14 + CONTENT/BT3025/MODELS/CONVOY.MOD | 10 + CONTENT/BT3025/MODELS/COOLANT.MOD | 17 + CONTENT/BT3025/MODELS/CRT.MOD | 18 + CONTENT/BT3025/MODELS/CTARMAC.MOD | 6 + CONTENT/BT3025/MODELS/DAM1HIT.MOD | 7 + CONTENT/BT3025/MODELS/DAM1HITI.MOD | 6 + CONTENT/BT3025/MODELS/DAM2HIT.MOD | 7 + CONTENT/BT3025/MODELS/DAM2HITI.MOD | 6 + CONTENT/BT3025/MODELS/DAM3EXP.MOD | 6 + CONTENT/BT3025/MODELS/DAM3HIT.MOD | 10 + CONTENT/BT3025/MODELS/DAM3HITI.MOD | 6 + CONTENT/BT3025/MODELS/DAM4EXP.MOD | 6 + CONTENT/BT3025/MODELS/DAM4EXPI.MOD | 6 + CONTENT/BT3025/MODELS/DAM4HIT.MOD | 10 + CONTENT/BT3025/MODELS/DAM4HITI.MOD | 9 + CONTENT/BT3025/MODELS/DAVION.MOD | 2 + CONTENT/BT3025/MODELS/DECOY.MOD | 8 + CONTENT/BT3025/MODELS/DEFENDER.MOD | 8 + CONTENT/BT3025/MODELS/DESTHIT.MOD | 7 + CONTENT/BT3025/MODELS/DESTHITI.MOD | 6 + CONTENT/BT3025/MODELS/DFLTROLE.MOD | 10 + CONTENT/BT3025/MODELS/DG100.MOD | 9 + CONTENT/BT3025/MODELS/DG100A.MOD | 8 + CONTENT/BT3025/MODELS/DHILLG1.MOD | 11 + CONTENT/BT3025/MODELS/DHILLG2.MOD | 11 + CONTENT/BT3025/MODELS/DHILLG3.MOD | 11 + CONTENT/BT3025/MODELS/DISH.MOD | 17 + CONTENT/BT3025/MODELS/DMG.BLD | 1 + CONTENT/BT3025/MODELS/DOZER.MOD | 14 + CONTENT/BT3025/MODELS/DRESF.MOD | 8 + CONTENT/BT3025/MODELS/DSKY.MOD | 6 + CONTENT/BT3025/MODELS/DTARMAC.MOD | 6 + CONTENT/BT3025/MODELS/DUMB.MOD | 24 + CONTENT/BT3025/MODELS/DUMB2.SUB | 33 + CONTENT/BT3025/MODELS/DUMB4.SUB | 33 + CONTENT/BT3025/MODELS/DUMB6.SUB | 33 + CONTENT/BT3025/MODELS/ERLLASER.SUB | 36 + CONTENT/BT3025/MODELS/ERMLASER.SUB | 36 + CONTENT/BT3025/MODELS/ERPPC.SUB | 36 + CONTENT/BT3025/MODELS/ERSLASER.SUB | 35 + CONTENT/BT3025/MODELS/EXPLODE.MOD | 6 + CONTENT/BT3025/MODELS/EXPLODE.ONL | 58 + CONTENT/BT3025/MODELS/FD1.MOD | 5 + CONTENT/BT3025/MODELS/FD2.MOD | 5 + CONTENT/BT3025/MODELS/FD3.MOD | 5 + CONTENT/BT3025/MODELS/FD4.MOD | 8 + CONTENT/BT3025/MODELS/FIND.TXT | 11 + CONTENT/BT3025/MODELS/FIRDMG.EXP | 28 + CONTENT/BT3025/MODELS/FIRTHR.CTL | 57 + CONTENT/BT3025/MODELS/FL1.MOD | 8 + CONTENT/BT3025/MODELS/FP0.MOD | 17 + CONTENT/BT3025/MODELS/FP0D.MOD | 5 + CONTENT/BT3025/MODELS/FP1.MOD | 20 + CONTENT/BT3025/MODELS/FP2.MOD | 20 + CONTENT/BT3025/MODELS/FP2D.MOD | 5 + CONTENT/BT3025/MODELS/FP3.MOD | 17 + CONTENT/BT3025/MODELS/FT1.MOD | 20 + CONTENT/BT3025/MODELS/FT2.MOD | 20 + CONTENT/BT3025/MODELS/GAUSSRFL.SUB | 33 + CONTENT/BT3025/MODELS/GD1.MOD | 8 + CONTENT/BT3025/MODELS/GD2.MOD | 8 + CONTENT/BT3025/MODELS/GD3.MOD | 8 + CONTENT/BT3025/MODELS/GD4.MOD | 8 + CONTENT/BT3025/MODELS/GD5.MOD | 10 + CONTENT/BT3025/MODELS/GENRATOR.SUB | 17 + CONTENT/BT3025/MODELS/GNDHIT.MOD | 9 + CONTENT/BT3025/MODELS/GNR.MOD | 20 + CONTENT/BT3025/MODELS/GRND100.MOD | 9 + CONTENT/BT3025/MODELS/GTARMAC.MOD | 6 + CONTENT/BT3025/MODELS/GYRO.SUB | 82 + CONTENT/BT3025/MODELS/HARASSER.MOD | 18 + CONTENT/BT3025/MODELS/HC1.MOD | 14 + CONTENT/BT3025/MODELS/HC2.MOD | 14 + CONTENT/BT3025/MODELS/HEATSNK.SUB | 15 + CONTENT/BT3025/MODELS/HILLA.MOD | 12 + CONTENT/BT3025/MODELS/HILLC.MOD | 12 + CONTENT/BT3025/MODELS/HILLG1.MOD | 11 + CONTENT/BT3025/MODELS/HILLG2.MOD | 11 + CONTENT/BT3025/MODELS/HILLG3.MOD | 11 + CONTENT/BT3025/MODELS/HL1.MOD | 12 + CONTENT/BT3025/MODELS/HL2.MOD | 12 + CONTENT/BT3025/MODELS/HN1.MOD | 20 + CONTENT/BT3025/MODELS/HOSTAGE.MOD | 8 + CONTENT/BT3025/MODELS/HUD.SUB | 14 + CONTENT/BT3025/MODELS/HUMMER.MOD | 17 + CONTENT/BT3025/MODELS/HUT.MOD | 20 + CONTENT/BT3025/MODELS/HWZ.MOD | 20 + CONTENT/BT3025/MODELS/ICONBLH.MOD | 16 + CONTENT/BT3025/MODELS/ICONJAK.MOD | 11 + CONTENT/BT3025/MODELS/ICONLOK.MOD | 16 + CONTENT/BT3025/MODELS/ICONOWN.MOD | 16 + CONTENT/BT3025/MODELS/ICONTHR.DMG | 3 + CONTENT/BT3025/MODELS/ICONTHR.MOD | 16 + CONTENT/BT3025/MODELS/ICONTHRD.MOD | 11 + CONTENT/BT3025/MODELS/ICONVUL.DMG | 3 + CONTENT/BT3025/MODELS/ICONVUL.MOD | 16 + CONTENT/BT3025/MODELS/JAKDMG.EXP | 28 + CONTENT/BT3025/MODELS/JAKTHR.CTL | 63 + CONTENT/BT3025/MODELS/KURITA.MOD | 2 + CONTENT/BT3025/MODELS/LASER.MOD | 65 + CONTENT/BT3025/MODELS/LLASER.SUB | 36 + CONTENT/BT3025/MODELS/LNTRK1.MOD | 14 + CONTENT/BT3025/MODELS/LOK1DMG.EXP | 28 + CONTENT/BT3025/MODELS/LOK1THR.CTL | 75 + CONTENT/BT3025/MODELS/LOK2DMG.EXP | 28 + CONTENT/BT3025/MODELS/LOK2THR.CTL | 75 + CONTENT/BT3025/MODELS/LOKDEAD.MOD | 9 + CONTENT/BT3025/MODELS/LOKDMG.EXP | 28 + CONTENT/BT3025/MODELS/LOKI.SUB | 212 + CONTENT/BT3025/MODELS/LOKTHR.CTL | 63 + CONTENT/BT3025/MODELS/LRM.MOD | 24 + CONTENT/BT3025/MODELS/LRM10.SUB | 33 + CONTENT/BT3025/MODELS/LRM15.SUB | 33 + CONTENT/BT3025/MODELS/LRM20.SUB | 33 + CONTENT/BT3025/MODELS/LRM5.SUB | 33 + CONTENT/BT3025/MODELS/LRMCARRY.MOD | 18 + CONTENT/BT3025/MODELS/LRMLANCH.SUB | 28 + CONTENT/BT3025/MODELS/LZRHIT.MOD | 11 + CONTENT/BT3025/MODELS/LZRHITI.MOD | 10 + CONTENT/BT3025/MODELS/MACHGUN.SUB | 33 + CONTENT/BT3025/MODELS/MAD.DMG | 114 + CONTENT/BT3025/MODELS/MAD1DMG.EXP | 28 + CONTENT/BT3025/MODELS/MAD1THR.CTL | 69 + CONTENT/BT3025/MODELS/MAD2DMG.EXP | 28 + CONTENT/BT3025/MODELS/MAD2THR.CTL | 63 + CONTENT/BT3025/MODELS/MADDEAD.MOD | 9 + CONTENT/BT3025/MODELS/MADDMG.EXP | 28 + CONTENT/BT3025/MODELS/MADTHR.CTL | 57 + CONTENT/BT3025/MODELS/MAJHIT.MOD | 9 + CONTENT/BT3025/MODELS/MECHALRM.MOD | 25 + CONTENT/BT3025/MODELS/MECHDEAD.MOD | 10 + CONTENT/BT3025/MODELS/MECHMOVR.MOD | 17 + CONTENT/BT3025/MODELS/MED.DMG | 3 + CONTENT/BT3025/MODELS/MEDDEAD.MOD | 10 + CONTENT/BT3025/MODELS/MGHIT.MOD | 10 + CONTENT/BT3025/MODELS/MGHITI.MOD | 9 + CONTENT/BT3025/MODELS/MINHIT.MOD | 9 + CONTENT/BT3025/MODELS/MLASER.SUB | 35 + CONTENT/BT3025/MODELS/MSL.DMG | 3 + CONTENT/BT3025/MODELS/MSL.MOD | 16 + CONTENT/BT3025/MODELS/MSLBASE.MOD | 8 + CONTENT/BT3025/MODELS/MSLDEAD.MOD | 11 + CONTENT/BT3025/MODELS/MSLG.MOD | 20 + CONTENT/BT3025/MODELS/MSLH.MOD | 11 + CONTENT/BT3025/MODELS/MSLHIT.MOD | 11 + CONTENT/BT3025/MODELS/MSLHITI.MOD | 10 + CONTENT/BT3025/MODELS/MSLR.DMG | 3 + CONTENT/BT3025/MODELS/MSLR.MOD | 20 + CONTENT/BT3025/MODELS/MSLRB.MOD | 11 + CONTENT/BT3025/MODELS/MSLROAD1.MOD | 5 + CONTENT/BT3025/MODELS/MYOMERS.SUB | 27 + CONTENT/BT3025/MODELS/NORETURN.MOD | 10 + CONTENT/BT3025/MODELS/NRK.MOD | 24 + CONTENT/BT3025/MODELS/NRK10.SUB | 33 + CONTENT/BT3025/MODELS/NRK15.SUB | 33 + CONTENT/BT3025/MODELS/NRK20.SUB | 33 + CONTENT/BT3025/MODELS/NRK5.SUB | 33 + CONTENT/BT3025/MODELS/NTR.MOD | 5 + CONTENT/BT3025/MODELS/OLDCON.SUB | 13 + CONTENT/BT3025/MODELS/OLDGEN.SUB | 17 + CONTENT/BT3025/MODELS/OLDLOKI.SUB | 132 + CONTENT/BT3025/MODELS/OWN1DMG.EXP | 28 + CONTENT/BT3025/MODELS/OWN1THR.CTL | 51 + CONTENT/BT3025/MODELS/OWNDEAD.MOD | 9 + CONTENT/BT3025/MODELS/OWNDMG.EXP | 28 + CONTENT/BT3025/MODELS/OWNTHR.CTL | 69 + CONTENT/BT3025/MODELS/PDSH.MOD | 20 + CONTENT/BT3025/MODELS/PGN.DMG | 3 + CONTENT/BT3025/MODELS/PGN.MOD | 36 + CONTENT/BT3025/MODELS/PLAYER.MOD | 3 + CONTENT/BT3025/MODELS/PLIT.MOD | 17 + CONTENT/BT3025/MODELS/PPC.SUB | 36 + CONTENT/BT3025/MODELS/PPCHIT.MOD | 12 + CONTENT/BT3025/MODELS/PPCHITI.MOD | 10 + CONTENT/BT3025/MODELS/PROFILE1.MOD | 5 + CONTENT/BT3025/MODELS/PROFILE2.MOD | 5 + CONTENT/BT3025/MODELS/PROFILE3.MOD | 5 + CONTENT/BT3025/MODELS/PROFILE4.MOD | 5 + CONTENT/BT3025/MODELS/PROFILE5.MOD | 5 + CONTENT/BT3025/MODELS/PROFILE6.MOD | 5 + CONTENT/BT3025/MODELS/PROFILE7.MOD | 5 + CONTENT/BT3025/MODELS/PROFILE8.MOD | 5 + CONTENT/BT3025/MODELS/PROJTILE.MOD | 16 + CONTENT/BT3025/MODELS/PWIN1.MOD | 5 + CONTENT/BT3025/MODELS/PWIN2.MOD | 5 + CONTENT/BT3025/MODELS/PWIN3.MOD | 5 + CONTENT/BT3025/MODELS/PWIN4.MOD | 5 + CONTENT/BT3025/MODELS/PWIN5.MOD | 5 + CONTENT/BT3025/MODELS/PWIN6.MOD | 5 + CONTENT/BT3025/MODELS/PWIN7.MOD | 5 + CONTENT/BT3025/MODELS/PWIN8.MOD | 5 + CONTENT/BT3025/MODELS/RAPDEAD.MOD | 9 + CONTENT/BT3025/MODELS/RAPDMG.EXP | 28 + CONTENT/BT3025/MODELS/RAPTHR.CTL | 63 + CONTENT/BT3025/MODELS/RAVFLOOR.MOD | 9 + CONTENT/BT3025/MODELS/RAVINET1.MOD | 6 + CONTENT/BT3025/MODELS/RAVINET2.MOD | 6 + CONTENT/BT3025/MODELS/RAVINET3.MOD | 6 + CONTENT/BT3025/MODELS/RAVINET4.MOD | 6 + CONTENT/BT3025/MODELS/RAVINET5.MOD | 6 + CONTENT/BT3025/MODELS/RAVINET6.MOD | 6 + CONTENT/BT3025/MODELS/RAVINET7.MOD | 6 + CONTENT/BT3025/MODELS/RAVINET8.MOD | 6 + CONTENT/BT3025/MODELS/RAVWIN.MOD | 6 + CONTENT/BT3025/MODELS/RB1.MOD | 5 + CONTENT/BT3025/MODELS/RB2.MOD | 5 + CONTENT/BT3025/MODELS/RB3.MOD | 5 + CONTENT/BT3025/MODELS/RB4.MOD | 5 + CONTENT/BT3025/MODELS/RB5.MOD | 5 + CONTENT/BT3025/MODELS/RB6.MOD | 5 + CONTENT/BT3025/MODELS/RD1.MOD | 5 + CONTENT/BT3025/MODELS/RD2.MOD | 5 + CONTENT/BT3025/MODELS/RESERVE.SUB | 14 + CONTENT/BT3025/MODELS/RESULT.TXT | 8 + CONTENT/BT3025/MODELS/RESULT2.TXT | 5 + CONTENT/BT3025/MODELS/RK1.MOD | 11 + CONTENT/BT3025/MODELS/RK2.MOD | 11 + CONTENT/BT3025/MODELS/RK3.MOD | 11 + CONTENT/BT3025/MODELS/RK4.MOD | 11 + CONTENT/BT3025/MODELS/RK5.MOD | 11 + CONTENT/BT3025/MODELS/RK6.MOD | 11 + CONTENT/BT3025/MODELS/RK7.MOD | 11 + CONTENT/BT3025/MODELS/ROMMEL.MOD | 17 + CONTENT/BT3025/MODELS/RWD.MOD | 8 + CONTENT/BT3025/MODELS/RWIN1.MOD | 6 + CONTENT/BT3025/MODELS/SAW.MOD | 8 + CONTENT/BT3025/MODELS/SB1.MOD | 8 + CONTENT/BT3025/MODELS/SB1B.MOD | 8 + CONTENT/BT3025/MODELS/SB1C.MOD | 8 + CONTENT/BT3025/MODELS/SB1D.MOD | 8 + CONTENT/BT3025/MODELS/SB1E.MOD | 11 + CONTENT/BT3025/MODELS/SB1N.MOD | 11 + CONTENT/BT3025/MODELS/SB1S.MOD | 11 + CONTENT/BT3025/MODELS/SB1W.MOD | 11 + CONTENT/BT3025/MODELS/SB2.MOD | 8 + CONTENT/BT3025/MODELS/SB2B.MOD | 8 + CONTENT/BT3025/MODELS/SB2C.MOD | 8 + CONTENT/BT3025/MODELS/SB2D.MOD | 8 + CONTENT/BT3025/MODELS/SB2E.MOD | 8 + CONTENT/BT3025/MODELS/SB2N.MOD | 8 + CONTENT/BT3025/MODELS/SB2S.MOD | 8 + CONTENT/BT3025/MODELS/SB2W.MOD | 8 + CONTENT/BT3025/MODELS/SB3E.MOD | 8 + CONTENT/BT3025/MODELS/SB3N.MOD | 8 + CONTENT/BT3025/MODELS/SB3S.MOD | 11 + CONTENT/BT3025/MODELS/SB3W.MOD | 8 + CONTENT/BT3025/MODELS/SB4E.MOD | 8 + CONTENT/BT3025/MODELS/SB4N.MOD | 8 + CONTENT/BT3025/MODELS/SB4S.MOD | 8 + CONTENT/BT3025/MODELS/SB4W.MOD | 8 + CONTENT/BT3025/MODELS/SEMI.MOD | 14 + CONTENT/BT3025/MODELS/SEMIRIG.MOD | 14 + CONTENT/BT3025/MODELS/SENSOR.SUB | 19 + CONTENT/BT3025/MODELS/SKY.MOD | 5 + CONTENT/BT3025/MODELS/SL2.MOD | 17 + CONTENT/BT3025/MODELS/SLASER.SUB | 35 + CONTENT/BT3025/MODELS/SLT.MOD | 8 + CONTENT/BT3025/MODELS/SML.DMG | 3 + CONTENT/BT3025/MODELS/SMLDEAD.MOD | 10 + CONTENT/BT3025/MODELS/SN1.MOD | 8 + CONTENT/BT3025/MODELS/SN2.MOD | 12 + CONTENT/BT3025/MODELS/SN4.MOD | 12 + CONTENT/BT3025/MODELS/SND1DMG.EXP | 28 + CONTENT/BT3025/MODELS/SND1THR.CTL | 57 + CONTENT/BT3025/MODELS/SND2DMG.EXP | 28 + CONTENT/BT3025/MODELS/SND2THR.CTL | 81 + CONTENT/BT3025/MODELS/SNDDEAD.MOD | 9 + CONTENT/BT3025/MODELS/SNDDMG.EXP | 28 + CONTENT/BT3025/MODELS/SNDTHR.CTL | 75 + CONTENT/BT3025/MODELS/SNH.MOD | 14 + CONTENT/BT3025/MODELS/SNTK1.MOD | 12 + CONTENT/BT3025/MODELS/SR1E.MOD | 11 + CONTENT/BT3025/MODELS/SR1N.MOD | 11 + CONTENT/BT3025/MODELS/SR1S.MOD | 11 + CONTENT/BT3025/MODELS/SR1W.MOD | 11 + CONTENT/BT3025/MODELS/SRC1NE.MOD | 8 + CONTENT/BT3025/MODELS/SRC1NW.MOD | 8 + CONTENT/BT3025/MODELS/SRC1SE.MOD | 8 + CONTENT/BT3025/MODELS/SRC1SW.MOD | 8 + CONTENT/BT3025/MODELS/SRCHLITE.SUB | 10 + CONTENT/BT3025/MODELS/SRM.MOD | 24 + CONTENT/BT3025/MODELS/SRM2.SUB | 33 + CONTENT/BT3025/MODELS/SRM4.SUB | 33 + CONTENT/BT3025/MODELS/SRM6.SUB | 33 + CONTENT/BT3025/MODELS/SRMCARRY.MOD | 18 + CONTENT/BT3025/MODELS/ST1.MOD | 11 + CONTENT/BT3025/MODELS/STATE.RST | 12 + CONTENT/BT3025/MODELS/STB.MOD | 11 + CONTENT/BT3025/MODELS/STEPHIT.MOD | 11 + CONTENT/BT3025/MODELS/STF.MOD | 11 + CONTENT/BT3025/MODELS/STH.MOD | 11 + CONTENT/BT3025/MODELS/STIDEAD.MOD | 9 + CONTENT/BT3025/MODELS/STIDMG.EXP | 28 + CONTENT/BT3025/MODELS/STITHR.CTL | 51 + CONTENT/BT3025/MODELS/STRIKER.MOD | 18 + CONTENT/BT3025/MODELS/STRK.MOD | 24 + CONTENT/BT3025/MODELS/STRK2.SUB | 33 + CONTENT/BT3025/MODELS/STRK4.SUB | 33 + CONTENT/BT3025/MODELS/STRK6.SUB | 33 + CONTENT/BT3025/MODELS/STS.MOD | 11 + CONTENT/BT3025/MODELS/STT.MOD | 11 + CONTENT/BT3025/MODELS/SUB.BLD | 116 + CONTENT/BT3025/MODELS/SV2.MOD | 8 + CONTENT/BT3025/MODELS/SV2B.MOD | 8 + CONTENT/BT3025/MODELS/SV2C.MOD | 8 + CONTENT/BT3025/MODELS/SV2D.MOD | 8 + CONTENT/BT3025/MODELS/SV3.MOD | 8 + CONTENT/BT3025/MODELS/SV3B.MOD | 8 + CONTENT/BT3025/MODELS/SV3C.MOD | 8 + CONTENT/BT3025/MODELS/SV3D.MOD | 8 + CONTENT/BT3025/MODELS/SW1.MOD | 11 + CONTENT/BT3025/MODELS/SW2.MOD | 11 + CONTENT/BT3025/MODELS/SW3.MOD | 11 + CONTENT/BT3025/MODELS/SW4.MOD | 11 + CONTENT/BT3025/MODELS/SW5.MOD | 11 + CONTENT/BT3025/MODELS/SW6.MOD | 11 + CONTENT/BT3025/MODELS/SWIFTWND.MOD | 18 + CONTENT/BT3025/MODELS/TEST.TXT | 1 + CONTENT/BT3025/MODELS/TEXT.TXT | 20 + CONTENT/BT3025/MODELS/THERMAL.SUB | 10 + CONTENT/BT3025/MODELS/THR.DMG | 121 + CONTENT/BT3025/MODELS/THR1DEAD.MOD | 9 + CONTENT/BT3025/MODELS/THR1DMG.EXP | 28 + CONTENT/BT3025/MODELS/THR1THR.CTL | 75 + CONTENT/BT3025/MODELS/THR6DEAD.MOD | 9 + CONTENT/BT3025/MODELS/THR6DMG.EXP | 28 + CONTENT/BT3025/MODELS/THR6THR.CTL | 81 + CONTENT/BT3025/MODELS/THRCTL.BLD | 21 + CONTENT/BT3025/MODELS/THRDEAD.MOD | 9 + CONTENT/BT3025/MODELS/THRDMG.EXP | 28 + CONTENT/BT3025/MODELS/THRDMGRD.EXP | 9 + CONTENT/BT3025/MODELS/THRTHR.CTL | 63 + CONTENT/BT3025/MODELS/TK1.MOD | 8 + CONTENT/BT3025/MODELS/TM1.MOD | 5 + CONTENT/BT3025/MODELS/TM2.MOD | 5 + CONTENT/BT3025/MODELS/TMC1.MOD | 11 + CONTENT/BT3025/MODELS/TMC2.MOD | 11 + CONTENT/BT3025/MODELS/TMC3.MOD | 8 + CONTENT/BT3025/MODELS/TMC4.MOD | 8 + CONTENT/BT3025/MODELS/TMC5.MOD | 8 + CONTENT/BT3025/MODELS/TMC6.MOD | 8 + CONTENT/BT3025/MODELS/TMC7.MOD | 8 + CONTENT/BT3025/MODELS/TMC8.MOD | 8 + CONTENT/BT3025/MODELS/TNT.MOD | 20 + CONTENT/BT3025/MODELS/TORSO.SUB | 21 + CONTENT/BT3025/MODELS/TORSOLMT.SUB | 20 + CONTENT/BT3025/MODELS/TREE.MOD | 17 + CONTENT/BT3025/MODELS/TRK.DMG | 3 + CONTENT/BT3025/MODELS/TRK1.MOD | 14 + CONTENT/BT3025/MODELS/TRK3.MOD | 14 + CONTENT/BT3025/MODELS/TRK4.MOD | 14 + CONTENT/BT3025/MODELS/TRKDEAD.MOD | 10 + CONTENT/BT3025/MODELS/TT1.MOD | 14 + CONTENT/BT3025/MODELS/TT2.MOD | 14 + CONTENT/BT3025/MODELS/TWR.DMG | 3 + CONTENT/BT3025/MODELS/TWR.MOD | 20 + CONTENT/BT3025/MODELS/TWRDEAD.MOD | 11 + CONTENT/BT3025/MODELS/VEHICLE.TBL | 46 + CONTENT/BT3025/MODELS/VUL1DMG.EXP | 28 + CONTENT/BT3025/MODELS/VUL1THR.CTL | 69 + CONTENT/BT3025/MODELS/VUL2DMG.EXP | 28 + CONTENT/BT3025/MODELS/VUL2THR.CTL | 81 + CONTENT/BT3025/MODELS/VULDEAD.MOD | 9 + CONTENT/BT3025/MODELS/VULDMG.EXP | 28 + CONTENT/BT3025/MODELS/VULTHR.CTL | 69 + CONTENT/BT3025/MODELS/WALL1.MOD | 11 + CONTENT/BT3025/MODELS/WALL10K.MOD | 7 + CONTENT/BT3025/MODELS/WALL2.MOD | 11 + CONTENT/BT3025/MODELS/WALL3.MOD | 11 + CONTENT/BT3025/MODELS/WL1.MOD | 8 + CONTENT/BT3025/MODELS/WL2.MOD | 8 + CONTENT/BT3025/MODELS/WL3.MOD | 8 + CONTENT/BT3025/MODELS/WL4.MOD | 8 + CONTENT/BT3025/MODELS/WL5.MOD | 8 + CONTENT/BT3025/MODELS/WL6.MOD | 8 + CONTENT/BT3025/MODELS/WL7.MOD | 8 + CONTENT/BT3025/MODELS/WL8.MOD | 8 + CONTENT/BT3025/MODELS/WL9.MOD | 8 + CONTENT/BT3025/MODELS/WNDSFX01.MOD | 5 + CONTENT/BT3025/MODELS/WNDSFX02.MOD | 5 + CONTENT/BT3025/MODELS/WNDSFX03.MOD | 5 + CONTENT/BT3025/MODELS/WOLF.MOD | 2 + CONTENT/BT3025/MODELS/WPN.BLD | 64 + CONTENT/BT3025/MODELS/WPNDMG.TBL | 47 + CONTENT/BT3025/MODELS/WST.MOD | 20 + CONTENT/BT3025/NEWSTUFF.BLD | 21 + CONTENT/BT3025/NULL | 24 + CONTENT/BT3025/RESULT2.TXT | 21 + CONTENT/BT3025/SHOWENV.BAT | 12 + CONTENT/BT3025/SOLIDS/AB01_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/AB02_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/AB03_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/AB04_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/AB05_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/AB09_CV.SLD | 197 + CONTENT/BT3025/SOLIDS/ADWLK1~1.SLD | 50 + CONTENT/BT3025/SOLIDS/ADWLK2~1.SLD | 50 + CONTENT/BT3025/SOLIDS/ADWLK3~1.SLD | 29 + CONTENT/BT3025/SOLIDS/APC.SLD | 50 + CONTENT/BT3025/SOLIDS/AR02_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/AR04_CV.SLD | 197 + CONTENT/BT3025/SOLIDS/ARBAN_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/ARENA1.XST | 17 + CONTENT/BT3025/SOLIDS/ARENA2.XST | 17 + CONTENT/BT3025/SOLIDS/ARENA3.XST | 17 + CONTENT/BT3025/SOLIDS/ARLID_CV.SLD | 28 + CONTENT/BT3025/SOLIDS/ARMRMOVR.SLD | 29 + CONTENT/BT3025/SOLIDS/ARTRUCKS.XST | 17 + CONTENT/BT3025/SOLIDS/AVA_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/AW03_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/AW05_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/AWBOX_CV.SLD | 71 + CONTENT/BT3025/SOLIDS/BAC1_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/BCOR1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/BCOR2_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/BDET4_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/BLANK.XST | 17 + CONTENT/BT3025/SOLIDS/BLD03_CV.SLD | 71 + CONTENT/BT3025/SOLIDS/BLD04_CV.SLD | 71 + CONTENT/BT3025/SOLIDS/BLD06_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/BLD20_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/BLD24_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/BLD26_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/BLD27_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/BLH_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/BNK_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/BPIP1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/BULLDOG.SLD | 29 + CONTENT/BT3025/SOLIDS/BUTTEA_C.SLD | 92 + CONTENT/BT3025/SOLIDS/BUTTEB_C.SLD | 113 + CONTENT/BT3025/SOLIDS/BUTTEC_C.SLD | 113 + CONTENT/BT3025/SOLIDS/BUTTED_C.SLD | 92 + CONTENT/BT3025/SOLIDS/BUTTEE_C.SLD | 113 + CONTENT/BT3025/SOLIDS/BWLK1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/CALPB_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/CALP_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/CAVERN.XST | 16 + CONTENT/BT3025/SOLIDS/CITY1.XST | 15 + CONTENT/BT3025/SOLIDS/COMTRUCK.SLD | 50 + CONTENT/BT3025/SOLIDS/COOLANT.SLD | 71 + CONTENT/BT3025/SOLIDS/CRT_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/DBASE.XST | 18 + CONTENT/BT3025/SOLIDS/DES.XST | 17 + CONTENT/BT3025/SOLIDS/DISH_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/DOZER.SLD | 50 + CONTENT/BT3025/SOLIDS/FIR_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/FL1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/FP2D_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/FP2_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/FP3_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/FRSTRM.XST | 17 + CONTENT/BT3025/SOLIDS/FT1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/FT2_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/GD1_CV.SLD | 71 + CONTENT/BT3025/SOLIDS/GD2_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/GD3_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/GD4_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/GD5_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/GNR_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/GR100ACV.SLD | 29 + CONTENT/BT3025/SOLIDS/GR100COL.SLD | 29 + CONTENT/BT3025/SOLIDS/GR100_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/GRASS.XST | 17 + CONTENT/BT3025/SOLIDS/HARASSER.SLD | 29 + CONTENT/BT3025/SOLIDS/HC1_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/HC2_CV.SLD | 71 + CONTENT/BT3025/SOLIDS/HILLA_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/HILLB_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/HILLC_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/HILLG1CO.SLD | 71 + CONTENT/BT3025/SOLIDS/HILLG1_C.SLD | 71 + CONTENT/BT3025/SOLIDS/HILLG2CO.SLD | 50 + CONTENT/BT3025/SOLIDS/HILLG2_C.SLD | 50 + CONTENT/BT3025/SOLIDS/HILLG3CO.SLD | 50 + CONTENT/BT3025/SOLIDS/HILLG3_C.SLD | 50 + CONTENT/BT3025/SOLIDS/HL1_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/HN1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/HUMMER.SLD | 50 + CONTENT/BT3025/SOLIDS/HUT_CV.SLD | 71 + CONTENT/BT3025/SOLIDS/HWZ_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/JAK_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/JAX1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/JAX2_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/LOK_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/LRMCARRY.SLD | 29 + CONTENT/BT3025/SOLIDS/MAD_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/MECHMOVR.SLD | 71 + CONTENT/BT3025/SOLIDS/MSLBS_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/MSLG_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/MSLH_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/MSLRB_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/MSLR_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/MSL_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/OWN_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/PDSH_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/PGN_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/PLIT_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/POLAR1.XST | 17 + CONTENT/BT3025/SOLIDS/POLAR2.XST | 17 + CONTENT/BT3025/SOLIDS/POLAR3.XST | 17 + CONTENT/BT3025/SOLIDS/POLAR4.XST | 17 + CONTENT/BT3025/SOLIDS/RAP_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/RAV.XST | 17 + CONTENT/BT3025/SOLIDS/RAV1.XST | 17 + CONTENT/BT3025/SOLIDS/RFLOOR.SLD | 30 + CONTENT/BT3025/SOLIDS/RFLOOR_C.SLD | 30 + CONTENT/BT3025/SOLIDS/RK5_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/RK6_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/RK7_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/ROMMEL.SLD | 29 + CONTENT/BT3025/SOLIDS/SAW_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB1B_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB1C_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB1D_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB1E_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB1N_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB1S_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB1W_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB2B_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB2C_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB2D_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB2E_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB2N_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB2S_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB2W_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SB2_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB3E_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB3N_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB3S_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB3W_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB4E_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB4N_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB4S_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SB4W_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SEMI.SLD | 50 + CONTENT/BT3025/SOLIDS/SEMIRIG.SLD | 71 + CONTENT/BT3025/SOLIDS/SL2_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SN1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SND_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/SNH_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SR1E_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SR1N_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SR1S_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SR1W_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SRC1NE_C.SLD | 72 + CONTENT/BT3025/SOLIDS/SRC1NW_C.SLD | 72 + CONTENT/BT3025/SOLIDS/SRC1SE_C.SLD | 72 + CONTENT/BT3025/SOLIDS/SRC1SW_C.SLD | 72 + CONTENT/BT3025/SOLIDS/SRMCARRY.SLD | 50 + CONTENT/BT3025/SOLIDS/ST1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/STATE.RST | 12 + CONTENT/BT3025/SOLIDS/STB_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/STF_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/STI_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/STRIKER.SLD | 71 + CONTENT/BT3025/SOLIDS/STS_CV.SLD | 71 + CONTENT/BT3025/SOLIDS/SV2B_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/SV2C_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/SV2D_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/SV2_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/SV3B_CV.SLD | 176 + CONTENT/BT3025/SOLIDS/SV3C_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/SV3D_CV.SLD | 134 + CONTENT/BT3025/SOLIDS/SV3_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/SW1_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SW2_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SW3_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SW4_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SW5_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/SW6_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/SWIFTWND.SLD | 50 + CONTENT/BT3025/SOLIDS/TEST.XST | 18 + CONTENT/BT3025/SOLIDS/THR_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/TK1_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/TNT_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/TREE_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/TRK1_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/TRK3_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/TRK4_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/TT1_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/TT2_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/TWR_CV.SLD | 29 + CONTENT/BT3025/SOLIDS/VUL_CV.SLD | 30 + CONTENT/BT3025/SOLIDS/WALL10K.SLD | 93 + CONTENT/BT3025/SOLIDS/WL2_CV.SLD | 92 + CONTENT/BT3025/SOLIDS/WL4_CV.SLD | 113 + CONTENT/BT3025/SOLIDS/WL5_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/WL6_CV.SLD | 155 + CONTENT/BT3025/SOLIDS/WL7_CV.SLD | 176 + CONTENT/BT3025/SOLIDS/WL9_CV.SLD | 50 + CONTENT/BT3025/SOLIDS/WST_CV.SLD | 92 + CONTENT/BT3025/TEST.BAT | 48 + CONTENT/BT3025/VIDEO/AUTOARM.SKL | 116 + CONTENT/BT3025/VIDEO/AUTODARM.SKL | 116 + CONTENT/BT3025/VIDEO/AVX2SKIN.DZM | 5 + CONTENT/BT3025/VIDEO/AVXSKIN.DZM | 5 + CONTENT/BT3025/VIDEO/BAXSKIN.DZM | 2 + CONTENT/BT3025/VIDEO/BLXSKIN.DZM | 6 + CONTENT/BT3025/VIDEO/BUILD/APCS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/APCS.VGF | 44 + CONTENT/BT3025/VIDEO/BUILD/ARMRS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/BUILD/ARMRS.VGF | 39 + CONTENT/BT3025/VIDEO/BUILD/BACKUP/GRASS.VMF | 82 + CONTENT/BT3025/VIDEO/BUILD/BLD08_LP.VGF | 75 + CONTENT/BT3025/VIDEO/BUILD/BUILDBAS.BAT | 18 + CONTENT/BT3025/VIDEO/BUILD/BUILDGEN.BAT | 18 + CONTENT/BT3025/VIDEO/BUILD/BUILDLGO.BAT | 18 + CONTENT/BT3025/VIDEO/BUILD/BUILDTEX.BAT | 20 + CONTENT/BT3025/VIDEO/BUILD/BULLS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/BUILD/BULLS.VGF | 39 + CONTENT/BT3025/VIDEO/BUILD/CALIOPE.BMF | Bin 0 -> 2413 bytes CONTENT/BT3025/VIDEO/BUILD/CALP_LP.VGF | 49 + CONTENT/BT3025/VIDEO/BUILD/COMS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/COMS.VGF | 44 + CONTENT/BT3025/VIDEO/BUILD/COOLS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/BUILD/COOLS.VGF | 39 + CONTENT/BT3025/VIDEO/BUILD/DBASE.BMF | Bin 0 -> 1574 bytes CONTENT/BT3025/VIDEO/BUILD/DCLOUDS.BGF | Bin 0 -> 2177 bytes CONTENT/BT3025/VIDEO/BUILD/DISH_LP.VGF | 36 + .../BT3025/VIDEO/BUILD/DIVISION.SAV/APCS.BGF | Bin 0 -> 268 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/ARMRS.BGF | Bin 0 -> 204 bytes .../VIDEO/BUILD/DIVISION.SAV/BTRAVWIN.BMF | Bin 0 -> 801 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/BULLS.BGF | Bin 0 -> 204 bytes .../VIDEO/BUILD/DIVISION.SAV/CALIOPE.BMF | Bin 0 -> 2413 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/COMS.BGF | Bin 0 -> 268 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/COOLS.BGF | Bin 0 -> 204 bytes .../VIDEO/BUILD/DIVISION.SAV/DCLOUDS.BGF | Bin 0 -> 2177 bytes .../VIDEO/BUILD/DIVISION.SAV/DOZERS.BGF | Bin 0 -> 268 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/GRASS.BMF | Bin 0 -> 381 bytes .../VIDEO/BUILD/DIVISION.SAV/HARASS.BGF | Bin 0 -> 268 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/HUMMS.BGF | Bin 0 -> 204 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/LRMS.BGF | Bin 0 -> 344 bytes .../VIDEO/BUILD/DIVISION.SAV/MECHMOVS.BGF | Bin 0 -> 268 bytes .../VIDEO/BUILD/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 230 bytes .../VIDEO/BUILD/DIVISION.SAV/ROMMELS.BGF | Bin 0 -> 268 bytes .../VIDEO/BUILD/DIVISION.SAV/SEMIRIGS.BGF | Bin 0 -> 204 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/SEMIS.BGF | Bin 0 -> 204 bytes .../BT3025/VIDEO/BUILD/DIVISION.SAV/SRMS.BGF | Bin 0 -> 268 bytes .../VIDEO/BUILD/DIVISION.SAV/STRIKERS.BGF | Bin 0 -> 268 bytes .../VIDEO/BUILD/DIVISION.SAV/SWIFTS.BGF | Bin 0 -> 395 bytes CONTENT/BT3025/VIDEO/BUILD/DOZERS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/DOZERS.VGF | 44 + .../BT3025/VIDEO/BUILD/EDITBACK/BLD08_LP.VGF | 74 + .../BT3025/VIDEO/BUILD/EDITBACK/BTRAVWIN.VMF | 154 + .../BT3025/VIDEO/BUILD/EDITBACK/BUILDBAS.BAT | 18 + .../BT3025/VIDEO/BUILD/EDITBACK/BUILDGEN.BAT | 18 + .../BT3025/VIDEO/BUILD/EDITBACK/BUILDLGO.BAT | 19 + .../BT3025/VIDEO/BUILD/EDITBACK/BUILDTEX.BAT | 20 + .../BT3025/VIDEO/BUILD/EDITBACK/CALP_LP.VGF | 48 + .../BT3025/VIDEO/BUILD/EDITBACK/DISH_LP.VGF | 35 + CONTENT/BT3025/VIDEO/BUILD/EDITBACK/GRASS.VMF | 69 + .../BT3025/VIDEO/BUILD/EDITBACK/RAVINES.VMF | 62 + CONTENT/BT3025/VIDEO/BUILD/GRASS.BMF | Bin 0 -> 441 bytes CONTENT/BT3025/VIDEO/BUILD/GRASS.VMF | 69 + CONTENT/BT3025/VIDEO/BUILD/HARASS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/HARASS.VGF | 44 + CONTENT/BT3025/VIDEO/BUILD/HUMMS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/BUILD/HUMMS.VGF | 39 + CONTENT/BT3025/VIDEO/BUILD/LRMS.BGF | Bin 0 -> 344 bytes CONTENT/BT3025/VIDEO/BUILD/LRMS.VGF | 51 + CONTENT/BT3025/VIDEO/BUILD/MECHMOVS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/MECHMOVS.VGF | 44 + CONTENT/BT3025/VIDEO/BUILD/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/BUILD/RAVINES.VMF | 62 + CONTENT/BT3025/VIDEO/BUILD/ROMMELS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/ROMMELS.VGF | 44 + CONTENT/BT3025/VIDEO/BUILD/SEMIRIGS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/BUILD/SEMIRIGS.VGF | 39 + CONTENT/BT3025/VIDEO/BUILD/SEMIS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/BUILD/SEMIS.VGF | 39 + CONTENT/BT3025/VIDEO/BUILD/SRMS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/SRMS.VGF | 44 + CONTENT/BT3025/VIDEO/BUILD/STATE.RST | 64 + CONTENT/BT3025/VIDEO/BUILD/STRIKERS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/BUILD/STRIKERS.VGF | 44 + CONTENT/BT3025/VIDEO/BUILD/SWIFTS.BGF | Bin 0 -> 395 bytes CONTENT/BT3025/VIDEO/BUILD/SWIFTS.VGF | 55 + CONTENT/BT3025/VIDEO/DAFC.PFX | 32 + CONTENT/BT3025/VIDEO/DBIGBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/DDAM1.PFX | 32 + CONTENT/BT3025/VIDEO/DDAM2.PFX | 32 + CONTENT/BT3025/VIDEO/DDAM3.PFX | 32 + CONTENT/BT3025/VIDEO/DDAM4.PFX | 32 + CONTENT/BT3025/VIDEO/DDAM5.PFX | 33 + CONTENT/BT3025/VIDEO/DDTHSMK.PFX | 32 + CONTENT/BT3025/VIDEO/DLRMTAIL.PFX | 33 + CONTENT/BT3025/VIDEO/DMEDBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/DMISSING.PFX | 33 + CONTENT/BT3025/VIDEO/DNBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/DSMLBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/DSRM.PFX | 33 + CONTENT/BT3025/VIDEO/DTRKBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/DTRKBURN.PFX | 32 + CONTENT/BT3025/VIDEO/FIRXSKIN.DZM | 3 + CONTENT/BT3025/VIDEO/FLUSH.PFX | 33 + CONTENT/BT3025/VIDEO/GEO/AB07D_FR.BGF | Bin 0 -> 1636 bytes CONTENT/BT3025/VIDEO/GEO/AB08.BGF | Bin 0 -> 2476 bytes CONTENT/BT3025/VIDEO/GEO/AB09D_FR.BGF | Bin 0 -> 1896 bytes CONTENT/BT3025/VIDEO/GEO/AB10D_FR.BGF | Bin 0 -> 1645 bytes CONTENT/BT3025/VIDEO/GEO/ABG.BGF | Bin 0 -> 249 bytes CONTENT/BT3025/VIDEO/GEO/ACT01.BGF | Bin 0 -> 776 bytes CONTENT/BT3025/VIDEO/GEO/ACT02.BGF | Bin 0 -> 655 bytes CONTENT/BT3025/VIDEO/GEO/ACT03.BGF | Bin 0 -> 677 bytes CONTENT/BT3025/VIDEO/GEO/ACT04.BGF | Bin 0 -> 1243 bytes CONTENT/BT3025/VIDEO/GEO/ACT05.BGF | Bin 0 -> 839 bytes CONTENT/BT3025/VIDEO/GEO/ADSUP1.BGF | Bin 0 -> 571 bytes CONTENT/BT3025/VIDEO/GEO/ADSUP2.BGF | Bin 0 -> 327 bytes CONTENT/BT3025/VIDEO/GEO/ADWLK1.BGF | Bin 0 -> 948 bytes CONTENT/BT3025/VIDEO/GEO/ADWLK2.BGF | Bin 0 -> 974 bytes CONTENT/BT3025/VIDEO/GEO/ADWLK3.BGF | Bin 0 -> 562 bytes CONTENT/BT3025/VIDEO/GEO/APCS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/AR01_FR.BGF | Bin 0 -> 993 bytes CONTENT/BT3025/VIDEO/GEO/AR03_FR.BGF | Bin 0 -> 935 bytes CONTENT/BT3025/VIDEO/GEO/AR04_FR.BGF | Bin 0 -> 1162 bytes CONTENT/BT3025/VIDEO/GEO/ARBAN1.BGF | Bin 0 -> 2282 bytes CONTENT/BT3025/VIDEO/GEO/ARBAN2.BGF | Bin 0 -> 2281 bytes CONTENT/BT3025/VIDEO/GEO/ARBAN3.BGF | Bin 0 -> 2285 bytes CONTENT/BT3025/VIDEO/GEO/ARBAN4.BGF | Bin 0 -> 2284 bytes CONTENT/BT3025/VIDEO/GEO/ARBAN5.BGF | Bin 0 -> 2284 bytes CONTENT/BT3025/VIDEO/GEO/ARBAN6.BGF | Bin 0 -> 2281 bytes CONTENT/BT3025/VIDEO/GEO/ARCLD.BGF | Bin 0 -> 526 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/ARENA/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/ARENA3/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT3025/VIDEO/GEO/ARHORIZ.BGF | Bin 0 -> 604 bytes CONTENT/BT3025/VIDEO/GEO/ARLID.BGF | Bin 0 -> 529 bytes CONTENT/BT3025/VIDEO/GEO/ARMRS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/GEO/AVA_LBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/AVA_LDOO.BGF | Bin 0 -> 1383 bytes CONTENT/BT3025/VIDEO/GEO/AVA_LFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT3025/VIDEO/GEO/AVA_LITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/AVA_LOTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/AVA_RBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/AVA_RDOO.BGF | Bin 0 -> 1383 bytes CONTENT/BT3025/VIDEO/GEO/AVA_RFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT3025/VIDEO/GEO/AVA_RITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/AVA_ROTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/AVX_TOR.BGF | Bin 0 -> 1434 bytes CONTENT/BT3025/VIDEO/GEO/AW01.BGF | Bin 0 -> 863 bytes CONTENT/BT3025/VIDEO/GEO/AW02.BGF | Bin 0 -> 868 bytes CONTENT/BT3025/VIDEO/GEO/AW03.BGF | Bin 0 -> 371 bytes CONTENT/BT3025/VIDEO/GEO/AW05.BGF | Bin 0 -> 1160 bytes CONTENT/BT3025/VIDEO/GEO/AWBOX1.BGF | Bin 0 -> 567 bytes CONTENT/BT3025/VIDEO/GEO/AWWLK1.BGF | Bin 0 -> 618 bytes CONTENT/BT3025/VIDEO/GEO/BAC1.BGF | Bin 0 -> 868 bytes CONTENT/BT3025/VIDEO/GEO/BALL1.BGF | Bin 0 -> 1597 bytes CONTENT/BT3025/VIDEO/GEO/BALL2.BGF | Bin 0 -> 1316 bytes CONTENT/BT3025/VIDEO/GEO/BALL3.BGF | Bin 0 -> 1316 bytes CONTENT/BT3025/VIDEO/GEO/BALL4.BGF | Bin 0 -> 1316 bytes CONTENT/BT3025/VIDEO/GEO/BBG.BGF | Bin 0 -> 256 bytes CONTENT/BT3025/VIDEO/GEO/BCOR1.BGF | Bin 0 -> 1965 bytes CONTENT/BT3025/VIDEO/GEO/BCOR2.BGF | Bin 0 -> 2125 bytes CONTENT/BT3025/VIDEO/GEO/BDET1.BGF | Bin 0 -> 898 bytes CONTENT/BT3025/VIDEO/GEO/BDET2.BGF | Bin 0 -> 634 bytes CONTENT/BT3025/VIDEO/GEO/BDET3.BGF | Bin 0 -> 1191 bytes CONTENT/BT3025/VIDEO/GEO/BDET4.BGF | Bin 0 -> 838 bytes CONTENT/BT3025/VIDEO/GEO/BDET6.BGF | Bin 0 -> 571 bytes CONTENT/BT3025/VIDEO/GEO/BLD08_LP.BGF | Bin 0 -> 750 bytes CONTENT/BT3025/VIDEO/GEO/BLHDLARM.BGF | Bin 0 -> 2346 bytes CONTENT/BT3025/VIDEO/GEO/BLHDRARM.BGF | Bin 0 -> 2346 bytes CONTENT/BT3025/VIDEO/GEO/BLUEBEAM.BGF | Bin 0 -> 2300 bytes CONTENT/BT3025/VIDEO/GEO/BNKD_FR.BGF | Bin 0 -> 1665 bytes CONTENT/BT3025/VIDEO/GEO/BNK_FR.BGF | Bin 0 -> 735 bytes CONTENT/BT3025/VIDEO/GEO/BNK_LP.BGF | Bin 0 -> 252 bytes CONTENT/BT3025/VIDEO/GEO/BPIP1.BGF | Bin 0 -> 627 bytes CONTENT/BT3025/VIDEO/GEO/BPIP1D.BGF | Bin 0 -> 1983 bytes CONTENT/BT3025/VIDEO/GEO/BULLET.BGF | Bin 0 -> 285 bytes CONTENT/BT3025/VIDEO/GEO/BULLS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/GEO/BWLK1.BGF | Bin 0 -> 634 bytes CONTENT/BT3025/VIDEO/GEO/CALP_LP.BGF | Bin 0 -> 330 bytes CONTENT/BT3025/VIDEO/GEO/CAMPOS.BGF | Bin 0 -> 1224 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/CAVERN/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT3025/VIDEO/GEO/CH1.BGF | Bin 0 -> 395 bytes CONTENT/BT3025/VIDEO/GEO/CH2.BGF | Bin 0 -> 327 bytes CONTENT/BT3025/VIDEO/GEO/COMS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/COOLS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/GEO/CRTD_FR.BGF | Bin 0 -> 954 bytes CONTENT/BT3025/VIDEO/GEO/CTAR_LP.BGF | Bin 0 -> 1379 bytes CONTENT/BT3025/VIDEO/GEO/D1DIRT.BGF | Bin 0 -> 2086 bytes .../VIDEO/GEO/DAY/DIVISION.SAV/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT3025/VIDEO/GEO/DAY/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT3025/VIDEO/GEO/DAY/DSKY.BMF | Bin 0 -> 2177 bytes CONTENT/BT3025/VIDEO/GEO/DAY/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT3025/VIDEO/GEO/DECLOUDS.BGF | Bin 0 -> 797 bytes CONTENT/BT3025/VIDEO/GEO/DISH_LP.BGF | Bin 0 -> 216 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/ARMRS.BGF | Bin 0 -> 204 bytes .../VIDEO/GEO/DIVISION.SAV/BLD08_LP.BGF | Bin 0 -> 753 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/CALP_LP.BGF | Bin 0 -> 332 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/COMS.BGF | Bin 0 -> 268 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/CTAR_LP.BGF | Bin 0 -> 1380 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/D1DIRT.BGF | Bin 0 -> 2086 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/DISH_LP.BGF | Bin 0 -> 217 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/DTAR_LP.BGF | Bin 0 -> 1041 bytes .../VIDEO/GEO/DIVISION.SAV/RAVFLOOR.BGF | Bin 0 -> 807 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 322 bytes .../VIDEO/GEO/DIVISION.SAV/SEMIRIGS.BGF | Bin 0 -> 204 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/TREESH.BGF | Bin 0 -> 291 bytes .../BT3025/VIDEO/GEO/DIVISION.SAV/TRUNK.BGF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/GEO/DOZERS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/DTAR_LP.BGF | Bin 0 -> 1040 bytes CONTENT/BT3025/VIDEO/GEO/EVENING/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT3025/VIDEO/GEO/EVENING/SKY.BGF | Bin 0 -> 539 bytes CONTENT/BT3025/VIDEO/GEO/EVENING/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT3025/VIDEO/GEO/EVENING/SPOT.BU | Bin 0 -> 522 bytes CONTENT/BT3025/VIDEO/GEO/EXDISK_A.BGF | Bin 0 -> 2085 bytes CONTENT/BT3025/VIDEO/GEO/EXDISK_B.BGF | Bin 0 -> 2085 bytes CONTENT/BT3025/VIDEO/GEO/EXDISK_C.BGF | Bin 0 -> 2085 bytes CONTENT/BT3025/VIDEO/GEO/EXP.BGF | Bin 0 -> 297 bytes CONTENT/BT3025/VIDEO/GEO/FD1.BGF | Bin 0 -> 532 bytes CONTENT/BT3025/VIDEO/GEO/FD2.BGF | Bin 0 -> 800 bytes CONTENT/BT3025/VIDEO/GEO/FD3.BGF | Bin 0 -> 427 bytes CONTENT/BT3025/VIDEO/GEO/FD4.BGF | Bin 0 -> 438 bytes CONTENT/BT3025/VIDEO/GEO/FL1.BGF | Bin 0 -> 254 bytes CONTENT/BT3025/VIDEO/GEO/FLAMEBIG.BGF | Bin 0 -> 917 bytes CONTENT/BT3025/VIDEO/GEO/FLAMEBIG.VGF | 71 + CONTENT/BT3025/VIDEO/GEO/FLAMESML.BGF | Bin 0 -> 153 bytes CONTENT/BT3025/VIDEO/GEO/FLAMESML.VGF | 30 + CONTENT/BT3025/VIDEO/GEO/FP0_LP.BGF | Bin 0 -> 300 bytes CONTENT/BT3025/VIDEO/GEO/FP1D.BGF | Bin 0 -> 1811 bytes CONTENT/BT3025/VIDEO/GEO/FP2.BGF | Bin 0 -> 1171 bytes CONTENT/BT3025/VIDEO/GEO/FP2_LP.BGF | Bin 0 -> 152 bytes CONTENT/BT3025/VIDEO/GEO/FT1D_FR.BGF | Bin 0 -> 1428 bytes CONTENT/BT3025/VIDEO/GEO/FT1_FR.BGF | Bin 0 -> 1625 bytes CONTENT/BT3025/VIDEO/GEO/FT1_LP.BGF | Bin 0 -> 334 bytes CONTENT/BT3025/VIDEO/GEO/FT2D_FR.BGF | Bin 0 -> 1336 bytes CONTENT/BT3025/VIDEO/GEO/FT2_FR.BGF | Bin 0 -> 1209 bytes CONTENT/BT3025/VIDEO/GEO/FT2_LP.BGF | Bin 0 -> 413 bytes CONTENT/BT3025/VIDEO/GEO/GD5.BGF | Bin 0 -> 1778 bytes CONTENT/BT3025/VIDEO/GEO/GNR_LP.BGF | Bin 0 -> 218 bytes CONTENT/BT3025/VIDEO/GEO/GREEBEAM.BGF | Bin 0 -> 2301 bytes CONTENT/BT3025/VIDEO/GEO/HARASS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/HC1D_FR.BGF | Bin 0 -> 892 bytes CONTENT/BT3025/VIDEO/GEO/HC1_LP.BGF | Bin 0 -> 252 bytes CONTENT/BT3025/VIDEO/GEO/HC2D_FR.BGF | Bin 0 -> 1144 bytes CONTENT/BT3025/VIDEO/GEO/HC2_LP.BGF | Bin 0 -> 302 bytes CONTENT/BT3025/VIDEO/GEO/HN1_FR.BGF | Bin 0 -> 2004 bytes CONTENT/BT3025/VIDEO/GEO/HN1_LP.BGF | Bin 0 -> 220 bytes CONTENT/BT3025/VIDEO/GEO/HOTBOX.BGF | Bin 0 -> 284 bytes CONTENT/BT3025/VIDEO/GEO/HUMMS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/GEO/HUT_FR.BGF | Bin 0 -> 1020 bytes CONTENT/BT3025/VIDEO/GEO/HUT_LP.BGF | Bin 0 -> 200 bytes CONTENT/BT3025/VIDEO/GEO/JAX1.BGF | Bin 0 -> 2554 bytes CONTENT/BT3025/VIDEO/GEO/JAX1D_FR.BGF | Bin 0 -> 2511 bytes CONTENT/BT3025/VIDEO/GEO/JAX1_FR.BGF | Bin 0 -> 575 bytes CONTENT/BT3025/VIDEO/GEO/JAX2.BGF | Bin 0 -> 2554 bytes CONTENT/BT3025/VIDEO/GEO/JAX2D_FR.BGF | Bin 0 -> 575 bytes CONTENT/BT3025/VIDEO/GEO/JAX2_FR.BGF | Bin 0 -> 575 bytes CONTENT/BT3025/VIDEO/GEO/LDBR.BGF | Bin 0 -> 1549 bytes CONTENT/BT3025/VIDEO/GEO/LOKDLIGH.BGF | Bin 0 -> 2110 bytes CONTENT/BT3025/VIDEO/GEO/LOKDRARM.BGF | Bin 0 -> 2504 bytes CONTENT/BT3025/VIDEO/GEO/LOKDRGUN.BGF | Bin 0 -> 2315 bytes CONTENT/BT3025/VIDEO/GEO/LOK_LIGH.BGF | Bin 0 -> 1620 bytes CONTENT/BT3025/VIDEO/GEO/LOK_MSL.BGF | Bin 0 -> 2017 bytes CONTENT/BT3025/VIDEO/GEO/LOX_TOR.BGF | Bin 0 -> 1131 bytes CONTENT/BT3025/VIDEO/GEO/LRMS.BGF | Bin 0 -> 344 bytes CONTENT/BT3025/VIDEO/GEO/MAD_LBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/MAD_LDOO.BGF | Bin 0 -> 1380 bytes CONTENT/BT3025/VIDEO/GEO/MAD_LFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT3025/VIDEO/GEO/MAD_LITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/MAD_LOTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/MAD_RBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/MAD_RDOO.BGF | Bin 0 -> 1380 bytes CONTENT/BT3025/VIDEO/GEO/MAD_RFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT3025/VIDEO/GEO/MAD_RITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/MAD_ROTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/MAX_LBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/MAX_LFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT3025/VIDEO/GEO/MAX_LITO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/MAX_LOTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/MAX_RBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/MAX_RFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT3025/VIDEO/GEO/MAX_RITO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/MAX_ROTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/MECHMOVS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/MISSILE.BGF | Bin 0 -> 1813 bytes CONTENT/BT3025/VIDEO/GEO/MORNING/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT3025/VIDEO/GEO/MORNING/RAVFLOOR.BGF | Bin 0 -> 807 bytes CONTENT/BT3025/VIDEO/GEO/MORNING/SEMIS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/GEO/MORNING/SKY.BGF | Bin 0 -> 539 bytes CONTENT/BT3025/VIDEO/GEO/MORNING/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT3025/VIDEO/GEO/MSLB_LP.BGF | Bin 0 -> 1102 bytes CONTENT/BT3025/VIDEO/GEO/MSLG_FR.BGF | Bin 0 -> 1746 bytes CONTENT/BT3025/VIDEO/GEO/MSLG_LP.BGF | Bin 0 -> 344 bytes CONTENT/BT3025/VIDEO/GEO/MSLH_FR.BGF | Bin 0 -> 1595 bytes CONTENT/BT3025/VIDEO/GEO/MSLH_LP.BGF | Bin 0 -> 205 bytes CONTENT/BT3025/VIDEO/GEO/MSLRD_FR.BGF | Bin 0 -> 1333 bytes CONTENT/BT3025/VIDEO/GEO/MSLR_FR.BGF | Bin 0 -> 1235 bytes CONTENT/BT3025/VIDEO/GEO/MSLR_LP.BGF | Bin 0 -> 443 bytes CONTENT/BT3025/VIDEO/GEO/MSL_FR.BGF | Bin 0 -> 707 bytes CONTENT/BT3025/VIDEO/GEO/MUZFLASH.BGF | Bin 0 -> 814 bytes CONTENT/BT3025/VIDEO/GEO/NIGHT/DSKY.BGF | Bin 0 -> 2177 bytes CONTENT/BT3025/VIDEO/GEO/NIGHT/SKY.BGF | Bin 0 -> 1660 bytes CONTENT/BT3025/VIDEO/GEO/NIGHT/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT3025/VIDEO/GEO/NTR.BGF | Bin 0 -> 254 bytes CONTENT/BT3025/VIDEO/GEO/OWNDCAM.BGF | Bin 0 -> 2132 bytes CONTENT/BT3025/VIDEO/GEO/OWN_LANT.BGF | Bin 0 -> 611 bytes CONTENT/BT3025/VIDEO/GEO/OWN_RANT.BGF | Bin 0 -> 611 bytes CONTENT/BT3025/VIDEO/GEO/OWX_LBTO.BGF | Bin 0 -> 842 bytes CONTENT/BT3025/VIDEO/GEO/OWX_LDLE.BGF | Bin 0 -> 2402 bytes CONTENT/BT3025/VIDEO/GEO/OWX_LFTO.BGF | Bin 0 -> 954 bytes CONTENT/BT3025/VIDEO/GEO/OWX_RBTO.BGF | Bin 0 -> 842 bytes CONTENT/BT3025/VIDEO/GEO/OWX_RDLE.BGF | Bin 0 -> 2402 bytes CONTENT/BT3025/VIDEO/GEO/OWX_RFTO.BGF | Bin 0 -> 954 bytes CONTENT/BT3025/VIDEO/GEO/PDSD_FR.BGF | Bin 0 -> 1049 bytes CONTENT/BT3025/VIDEO/GEO/PDSH_FR.BGF | Bin 0 -> 1297 bytes CONTENT/BT3025/VIDEO/GEO/PDSH_LP.BGF | Bin 0 -> 236 bytes CONTENT/BT3025/VIDEO/GEO/PGNDBASE.BGF | Bin 0 -> 1806 bytes CONTENT/BT3025/VIDEO/GEO/PGND_FR.BGF | Bin 0 -> 1480 bytes CONTENT/BT3025/VIDEO/GEO/PGN_BASE.BGF | Bin 0 -> 1820 bytes CONTENT/BT3025/VIDEO/GEO/PGN_FR.BGF | Bin 0 -> 1603 bytes CONTENT/BT3025/VIDEO/GEO/PLACE1.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLACE2.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLACE3.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLACE4.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLACE5.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLACE6.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLACE7.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLACE8.BGF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/GEO/PLIT_FR.BGF | Bin 0 -> 1249 bytes CONTENT/BT3025/VIDEO/GEO/PLTD_FR.BGF | Bin 0 -> 800 bytes CONTENT/BT3025/VIDEO/GEO/PNAME1.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/PNAME2.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/PNAME3.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/PNAME4.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/PNAME5.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/PNAME6.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/PNAME7.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/PNAME8.BGF | Bin 0 -> 235 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/AVA_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/BLH_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/FIR_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/LOK_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/MAD_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/OWN_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/SND_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/STI_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/THR_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/POLAR/VUL_TSHD.BGF | Bin 0 -> 188 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE1.BGF | Bin 0 -> 1506 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE2.BGF | Bin 0 -> 1262 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE3.BGF | Bin 0 -> 1230 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE4.BGF | Bin 0 -> 1402 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE5.BGF | Bin 0 -> 1398 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE6.BGF | Bin 0 -> 1334 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE7.BGF | Bin 0 -> 1366 bytes CONTENT/BT3025/VIDEO/GEO/PROFILE8.BGF | Bin 0 -> 1462 bytes CONTENT/BT3025/VIDEO/GEO/PWIN1.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/PWIN2.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/PWIN3.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/PWIN4.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/PWIN5.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/PWIN6.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/PWIN7.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/PWIN8.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/RAV/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT3025/VIDEO/GEO/RAV/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT3025/VIDEO/GEO/RAV/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/RAV/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT3025/VIDEO/GEO/RAV/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT3025/VIDEO/GEO/RAV/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/RAV/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/RAV/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT3025/VIDEO/GEO/RAV/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/RAV/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/RAV/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/AVA_TSHD.BGF | Bin 0 -> 2037 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/BLH_TSHD.BGF | Bin 0 -> 1903 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/FIR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/LOK_TSHD.BGF | Bin 0 -> 1886 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/MAD_TSHD.BGF | Bin 0 -> 2138 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/OWN_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/RAP_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/SND_TSHD.BGF | Bin 0 -> 1696 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/STI_TSHD.BGF | Bin 0 -> 1834 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/THR_TSHD.BGF | Bin 0 -> 1648 bytes CONTENT/BT3025/VIDEO/GEO/RAV1/VUL_TSHD.BGF | Bin 0 -> 1582 bytes CONTENT/BT3025/VIDEO/GEO/RAVFLOOR.BGF | Bin 0 -> 807 bytes CONTENT/BT3025/VIDEO/GEO/RAVINES.BMF | Bin 0 -> 322 bytes CONTENT/BT3025/VIDEO/GEO/RB6.BGF | Bin 0 -> 1745 bytes CONTENT/BT3025/VIDEO/GEO/RD1.BGF | Bin 0 -> 251 bytes CONTENT/BT3025/VIDEO/GEO/RD2.BGF | Bin 0 -> 251 bytes CONTENT/BT3025/VIDEO/GEO/RED_BEAM.BGF | Bin 0 -> 2299 bytes CONTENT/BT3025/VIDEO/GEO/ROMMELS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/RWD.BGF | Bin 0 -> 488 bytes CONTENT/BT3025/VIDEO/GEO/RWIN1.BGF | Bin 0 -> 1528 bytes CONTENT/BT3025/VIDEO/GEO/SAW.BGF | Bin 0 -> 250 bytes CONTENT/BT3025/VIDEO/GEO/SB1.BGF | Bin 0 -> 2141 bytes CONTENT/BT3025/VIDEO/GEO/SB1B.BGF | Bin 0 -> 1314 bytes CONTENT/BT3025/VIDEO/GEO/SB1C.BGF | Bin 0 -> 1446 bytes CONTENT/BT3025/VIDEO/GEO/SB1D.BGF | Bin 0 -> 1386 bytes CONTENT/BT3025/VIDEO/GEO/SB1E.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB1N.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB1S.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB1W.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB2.BGF | Bin 0 -> 2069 bytes CONTENT/BT3025/VIDEO/GEO/SB2B.BGF | Bin 0 -> 1218 bytes CONTENT/BT3025/VIDEO/GEO/SB2C.BGF | Bin 0 -> 1422 bytes CONTENT/BT3025/VIDEO/GEO/SB2D.BGF | Bin 0 -> 1326 bytes CONTENT/BT3025/VIDEO/GEO/SB2E.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB2N.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB2S.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB2W.BGF | Bin 0 -> 1210 bytes CONTENT/BT3025/VIDEO/GEO/SB3E.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SB3N.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SB3S.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SB3W.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SB4E.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SB4N.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SB4S.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SB4W.BGF | Bin 0 -> 922 bytes CONTENT/BT3025/VIDEO/GEO/SEMIRIGS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/GEO/SEMIS.BGF | Bin 0 -> 204 bytes CONTENT/BT3025/VIDEO/GEO/SHOCK.BGF | Bin 0 -> 175 bytes CONTENT/BT3025/VIDEO/GEO/SL2D_FR.BGF | Bin 0 -> 1261 bytes CONTENT/BT3025/VIDEO/GEO/SLD2_FR.BGF | Bin 0 -> 1283 bytes CONTENT/BT3025/VIDEO/GEO/SLT.BGF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/GEO/SMK_A.BGF | Bin 0 -> 779 bytes CONTENT/BT3025/VIDEO/GEO/SMK_B.BGF | Bin 0 -> 779 bytes CONTENT/BT3025/VIDEO/GEO/SMK_C.BGF | Bin 0 -> 779 bytes CONTENT/BT3025/VIDEO/GEO/SN1.BGF | Bin 0 -> 2141 bytes CONTENT/BT3025/VIDEO/GEO/SN2.BGF | Bin 0 -> 2267 bytes CONTENT/BT3025/VIDEO/GEO/SN4.BGF | Bin 0 -> 803 bytes CONTENT/BT3025/VIDEO/GEO/SND_DOOR.BGF | Bin 0 -> 1371 bytes CONTENT/BT3025/VIDEO/GEO/SND_RARM.BGF | Bin 0 -> 2120 bytes CONTENT/BT3025/VIDEO/GEO/SNHD_FR.BGF | Bin 0 -> 851 bytes CONTENT/BT3025/VIDEO/GEO/SNH_FR.BGF | Bin 0 -> 851 bytes CONTENT/BT3025/VIDEO/GEO/SNX_TOR.BGF | Bin 0 -> 667 bytes CONTENT/BT3025/VIDEO/GEO/SPK1.BGF | Bin 0 -> 1165 bytes CONTENT/BT3025/VIDEO/GEO/SPK2.BGF | Bin 0 -> 1165 bytes CONTENT/BT3025/VIDEO/GEO/SPOT.BGF | Bin 0 -> 522 bytes CONTENT/BT3025/VIDEO/GEO/SR1E.BGF | Bin 0 -> 2003 bytes CONTENT/BT3025/VIDEO/GEO/SR1N.BGF | Bin 0 -> 2003 bytes CONTENT/BT3025/VIDEO/GEO/SR1S.BGF | Bin 0 -> 2003 bytes CONTENT/BT3025/VIDEO/GEO/SR1W.BGF | Bin 0 -> 2003 bytes CONTENT/BT3025/VIDEO/GEO/SRMS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/ST1.BGF | Bin 0 -> 258 bytes CONTENT/BT3025/VIDEO/GEO/STF.BGF | Bin 0 -> 2074 bytes CONTENT/BT3025/VIDEO/GEO/STRIKERS.BGF | Bin 0 -> 268 bytes CONTENT/BT3025/VIDEO/GEO/SV2BR.BGF | Bin 0 -> 2522 bytes CONTENT/BT3025/VIDEO/GEO/SV2BS.BGF | Bin 0 -> 1133 bytes CONTENT/BT3025/VIDEO/GEO/SV2DR.BGF | Bin 0 -> 2404 bytes CONTENT/BT3025/VIDEO/GEO/SV2DS.BGF | Bin 0 -> 1229 bytes CONTENT/BT3025/VIDEO/GEO/SV2R.BGF | Bin 0 -> 2066 bytes CONTENT/BT3025/VIDEO/GEO/SV2S.BGF | Bin 0 -> 1349 bytes CONTENT/BT3025/VIDEO/GEO/SV3BR.BGF | Bin 0 -> 2537 bytes CONTENT/BT3025/VIDEO/GEO/SV3BS.BGF | Bin 0 -> 1193 bytes CONTENT/BT3025/VIDEO/GEO/SV3CR.BGF | Bin 0 -> 1708 bytes CONTENT/BT3025/VIDEO/GEO/SV3CS.BGF | Bin 0 -> 1949 bytes CONTENT/BT3025/VIDEO/GEO/SV3DR.BGF | Bin 0 -> 1631 bytes CONTENT/BT3025/VIDEO/GEO/SV3DS.BGF | Bin 0 -> 2093 bytes CONTENT/BT3025/VIDEO/GEO/SV3R.BGF | Bin 0 -> 1907 bytes CONTENT/BT3025/VIDEO/GEO/SV3S.BGF | Bin 0 -> 1229 bytes CONTENT/BT3025/VIDEO/GEO/SW1.BGF | Bin 0 -> 610 bytes CONTENT/BT3025/VIDEO/GEO/SW2.BGF | Bin 0 -> 682 bytes CONTENT/BT3025/VIDEO/GEO/SW3.BGF | Bin 0 -> 457 bytes CONTENT/BT3025/VIDEO/GEO/SW4.BGF | Bin 0 -> 1327 bytes CONTENT/BT3025/VIDEO/GEO/SW5.BGF | Bin 0 -> 1423 bytes CONTENT/BT3025/VIDEO/GEO/SW6.BGF | Bin 0 -> 883 bytes CONTENT/BT3025/VIDEO/GEO/SWIFTS.BGF | Bin 0 -> 395 bytes CONTENT/BT3025/VIDEO/GEO/THRDBR.BGF | Bin 0 -> 153 bytes CONTENT/BT3025/VIDEO/GEO/THXDMSL.BGF | Bin 0 -> 1532 bytes CONTENT/BT3025/VIDEO/GEO/THX_DOOR.BGF | Bin 0 -> 1635 bytes CONTENT/BT3025/VIDEO/GEO/THX_TOR.BGF | Bin 0 -> 342 bytes CONTENT/BT3025/VIDEO/GEO/TMC1.BGF | Bin 0 -> 547 bytes CONTENT/BT3025/VIDEO/GEO/TMC2.BGF | Bin 0 -> 350 bytes CONTENT/BT3025/VIDEO/GEO/TMC3.BGF | Bin 0 -> 680 bytes CONTENT/BT3025/VIDEO/GEO/TMC3_LP.BGF | Bin 0 -> 414 bytes CONTENT/BT3025/VIDEO/GEO/TMC4.BGF | Bin 0 -> 323 bytes CONTENT/BT3025/VIDEO/GEO/TMC4_LP.BGF | Bin 0 -> 250 bytes CONTENT/BT3025/VIDEO/GEO/TMC5.BGF | Bin 0 -> 264 bytes CONTENT/BT3025/VIDEO/GEO/TMC5_LP.BGF | Bin 0 -> 218 bytes CONTENT/BT3025/VIDEO/GEO/TMC6.BGF | Bin 0 -> 264 bytes CONTENT/BT3025/VIDEO/GEO/TMC6_LP.BGF | Bin 0 -> 218 bytes CONTENT/BT3025/VIDEO/GEO/TMC7.BGF | Bin 0 -> 288 bytes CONTENT/BT3025/VIDEO/GEO/TMC7_LP.BGF | Bin 0 -> 234 bytes CONTENT/BT3025/VIDEO/GEO/TMC8.BGF | Bin 0 -> 763 bytes CONTENT/BT3025/VIDEO/GEO/TMC8_LP.BGF | Bin 0 -> 414 bytes CONTENT/BT3025/VIDEO/GEO/TMSM_A.BGF | Bin 0 -> 2313 bytes CONTENT/BT3025/VIDEO/GEO/TMSM_B.BGF | Bin 0 -> 2313 bytes CONTENT/BT3025/VIDEO/GEO/TMSM_C.BGF | Bin 0 -> 2313 bytes CONTENT/BT3025/VIDEO/GEO/TMS_A.BGF | Bin 0 -> 1811 bytes CONTENT/BT3025/VIDEO/GEO/TMS_B.BGF | Bin 0 -> 1811 bytes CONTENT/BT3025/VIDEO/GEO/TMS_C.BGF | Bin 0 -> 1811 bytes CONTENT/BT3025/VIDEO/GEO/TREESH.BGF | Bin 0 -> 291 bytes CONTENT/BT3025/VIDEO/GEO/TRK1D_FR.BGF | Bin 0 -> 1230 bytes CONTENT/BT3025/VIDEO/GEO/TRK1_FR.BGF | Bin 0 -> 1615 bytes CONTENT/BT3025/VIDEO/GEO/TRK3D_FR.BGF | Bin 0 -> 1407 bytes CONTENT/BT3025/VIDEO/GEO/TRK3_FR.BGF | Bin 0 -> 1407 bytes CONTENT/BT3025/VIDEO/GEO/TRK4D_FR.BGF | Bin 0 -> 1138 bytes CONTENT/BT3025/VIDEO/GEO/TRK4_FR.BGF | Bin 0 -> 1218 bytes CONTENT/BT3025/VIDEO/GEO/TRUNK.BGF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/GEO/TSPHERE.BGF | Bin 0 -> 2085 bytes CONTENT/BT3025/VIDEO/GEO/TWRD_FR.BGF | Bin 0 -> 743 bytes CONTENT/BT3025/VIDEO/GEO/TWR_FR.BGF | Bin 0 -> 1364 bytes CONTENT/BT3025/VIDEO/GEO/TWR_LP.BGF | Bin 0 -> 282 bytes CONTENT/BT3025/VIDEO/GEO/VUL_LBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/VUL_LDDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT3025/VIDEO/GEO/VUL_LFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT3025/VIDEO/GEO/VUL_LITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/VUL_LOTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/VUL_LUDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT3025/VIDEO/GEO/VUL_RBTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/VUL_RDDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT3025/VIDEO/GEO/VUL_RFOT.BGF | Bin 0 -> 2435 bytes CONTENT/BT3025/VIDEO/GEO/VUL_RITO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/VUL_ROTO.BGF | Bin 0 -> 1053 bytes CONTENT/BT3025/VIDEO/GEO/VUL_RUDO.BGF | Bin 0 -> 1405 bytes CONTENT/BT3025/VIDEO/GEO/VUX_LBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/VUX_LFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT3025/VIDEO/GEO/VUX_LITO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/VUX_LOTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/VUX_RBTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/VUX_RFOT.BGF | Bin 0 -> 1197 bytes CONTENT/BT3025/VIDEO/GEO/VUX_RITO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/VUX_ROTO.BGF | Bin 0 -> 578 bytes CONTENT/BT3025/VIDEO/GEO/WSTD_FR.BGF | Bin 0 -> 1755 bytes CONTENT/BT3025/VIDEO/GEO/WST_FR.BGF | Bin 0 -> 1497 bytes CONTENT/BT3025/VIDEO/GEO/WST_LP.BGF | Bin 0 -> 270 bytes CONTENT/BT3025/VIDEO/IDAM1.PFX | 32 + CONTENT/BT3025/VIDEO/IDAM2.PFX | 32 + CONTENT/BT3025/VIDEO/IDAM3.PFX | 32 + CONTENT/BT3025/VIDEO/IDAM4.PFX | 32 + CONTENT/BT3025/VIDEO/IDAM5.PFX | 33 + CONTENT/BT3025/VIDEO/JAKSKIN.DZM | 74 + CONTENT/BT3025/VIDEO/JAXSKIN.DZM | 3 + CONTENT/BT3025/VIDEO/LASARM.SKL | 86 + CONTENT/BT3025/VIDEO/LOX1SKIN.DZM | 9 + CONTENT/BT3025/VIDEO/LOXSKIN.DZM | 9 + CONTENT/BT3025/VIDEO/MAT/AVAFX.BMF | Bin 0 -> 898 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN0.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN1.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN2.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN3.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN4.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN5.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN6.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVXSKIN7.BMF | Bin 0 -> 287 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK0.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK1.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK2.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK3.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK4.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK5.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK6.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BLK7.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN0.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN1.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN2.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN3.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN4.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN5.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN6.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_BRN7.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN0.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN1.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN2.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN3.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN4.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN5.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN6.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRN7.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY0.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY1.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY2.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY3.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY4.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY5.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY6.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_GRY7.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED0.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED1.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED2.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED3.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED4.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED5.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED6.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_RED7.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN0.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN1.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN2.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN3.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN4.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN5.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN6.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_TAN7.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT0.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT1.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT2.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT3.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT4.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT5.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT6.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/AVX_WHT7.BMF | Bin 0 -> 317 bytes CONTENT/BT3025/VIDEO/MAT/BLHFX.BMF | Bin 0 -> 1388 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLXSKIN7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BLK7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_BRN7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRN7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_GRY7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_RED7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_TAN7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT0.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT1.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT2.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT3.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT4.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT5.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT6.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BLX_WHT7.BMF | Bin 0 -> 238 bytes CONTENT/BT3025/VIDEO/MAT/BMAP.BMF | Bin 0 -> 480 bytes CONTENT/BT3025/VIDEO/MAT/BTCULT.BMF | 1 + CONTENT/BT3025/VIDEO/MAT/BTPOLWIN.BMF | Bin 0 -> 1048 bytes CONTENT/BT3025/VIDEO/MAT/BTRAVWIN.BMF | Bin 0 -> 801 bytes CONTENT/BT3025/VIDEO/MAT/CALIOPE.BMF | Bin 0 -> 2413 bytes .../VIDEO/MAT/DAY/DIVISION.SAV/GRASS.BMF | Bin 0 -> 441 bytes .../VIDEO/MAT/DAY/DIVISION.SAV/GRASSBU.BMF | Bin 0 -> 441 bytes .../VIDEO/MAT/DAY/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/MAT/DAY/GRASS.BMF | Bin 0 -> 441 bytes CONTENT/BT3025/VIDEO/MAT/DAY/GRASS.VMF | 69 + CONTENT/BT3025/VIDEO/MAT/DAY/GRASSBU.BMF | Bin 0 -> 441 bytes CONTENT/BT3025/VIDEO/MAT/DAY/GRASSBU.VMF | 69 + CONTENT/BT3025/VIDEO/MAT/DAY/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/MAT/DAY/RAVINES.VMF | 62 + CONTENT/BT3025/VIDEO/MAT/DBASE.BMF | Bin 0 -> 1574 bytes .../BT3025/VIDEO/MAT/DIVISION.SAV/CALIOPE.BMF | Bin 0 -> 2413 bytes .../BT3025/VIDEO/MAT/DIVISION.SAV/DBASE.BMF | Bin 0 -> 1574 bytes .../BT3025/VIDEO/MAT/DIVISION.SAV/GRASS.BMF | Bin 0 -> 441 bytes .../BT3025/VIDEO/MAT/DIVISION.SAV/GRASS.VMF | 61 + .../BT3025/VIDEO/MAT/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes .../BT3025/VIDEO/MAT/DIVISION.SAV/RAVINES.VMF | 50 + CONTENT/BT3025/VIDEO/MAT/DUMMY.BMF | Bin 0 -> 128 bytes .../VIDEO/MAT/EVENING/DIVISION.SAV/GRASS.BMF | Bin 0 -> 471 bytes .../MAT/EVENING/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/MAT/EVENING/GRASS.BMF | Bin 0 -> 471 bytes CONTENT/BT3025/VIDEO/MAT/EVENING/GRASS.VMF | 71 + CONTENT/BT3025/VIDEO/MAT/EVENING/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/MAT/EVENING/RAVINES.VMF | 62 + CONTENT/BT3025/VIDEO/MAT/FIRFX.BMF | Bin 0 -> 798 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIRSKIN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BLK7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_BRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRY0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRY2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRY3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRY4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRY5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRY6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_GRY7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_RED7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_TAN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIR_WHT7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIXSKIN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BLK7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_BRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_GRY7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_RED7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_TAN7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT0.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT1.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT2.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT3.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT4.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT5.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT6.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/FIX_WHT7.BMF | Bin 0 -> 1010 bytes CONTENT/BT3025/VIDEO/MAT/GRASS.BMF | Bin 0 -> 441 bytes CONTENT/BT3025/VIDEO/MAT/GRASS.VMF | 68 + CONTENT/BT3025/VIDEO/MAT/JAKSKIN.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAKSKIN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BLK7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_BRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_GRY7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_RED7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_TAN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAK_WHT7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAXSKIN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BLK7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_BRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_GRY7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_RED7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_TAN7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT0.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT1.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT2.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT3.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT4.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT5.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT6.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/JAX_WHT7.BMF | Bin 0 -> 1001 bytes CONTENT/BT3025/VIDEO/MAT/LOKFX.BMF | Bin 0 -> 984 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN0.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN1.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN2.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN3.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN4.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN5.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN6.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOXSKIN7.BMF | Bin 0 -> 404 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK0.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK1.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK2.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK3.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK4.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK5.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK6.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BLK7.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN0.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN1.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN2.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN3.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN4.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN5.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN6.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_BRN7.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN0.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN1.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN2.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN3.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN4.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN5.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN6.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRN7.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY0.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY1.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY2.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY3.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY4.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY5.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY6.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_GRY7.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED0.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED1.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED2.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED3.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED4.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED5.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED6.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_RED7.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN0.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN1.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN2.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN3.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN4.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN5.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN6.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_TAN7.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT0.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT1.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT2.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT3.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT4.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT5.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT6.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/LOX_WHT7.BMF | Bin 0 -> 554 bytes CONTENT/BT3025/VIDEO/MAT/MADFX.BMF | Bin 0 -> 898 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAXSKIN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BLK7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_BRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_GRY7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_RED7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_TAN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MAX_WHT7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/MECHFX.BMF | Bin 0 -> 984 bytes .../VIDEO/MAT/MORNING/DIVISION.SAV/GRASS.BMF | Bin 0 -> 471 bytes .../MAT/MORNING/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes .../MAT/MORNING/DIVISION.SAV/RAVINES.VMF | 61 + CONTENT/BT3025/VIDEO/MAT/MORNING/GRASS.BMF | Bin 0 -> 471 bytes CONTENT/BT3025/VIDEO/MAT/MORNING/GRASS.VMF | 71 + CONTENT/BT3025/VIDEO/MAT/MORNING/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/MAT/MORNING/RAVINES.VMF | 62 + .../VIDEO/MAT/NIGHT/DIVISION.SAV/GRASS.BMF | Bin 0 -> 471 bytes .../VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.BMF | Bin 0 -> 400 bytes .../VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.VMF | 61 + CONTENT/BT3025/VIDEO/MAT/NIGHT/GRASS.BMF | Bin 0 -> 471 bytes CONTENT/BT3025/VIDEO/MAT/NIGHT/GRASS.VMF | 71 + CONTENT/BT3025/VIDEO/MAT/NIGHT/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/MAT/NIGHT/RAVINES.VMF | 62 + CONTENT/BT3025/VIDEO/MAT/OWNFX.BMF | Bin 0 -> 798 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN0.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN1.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN2.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN3.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN4.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN5.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN6.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWXSKIN7.BMF | Bin 0 -> 1720 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK0.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK1.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK2.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK3.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK4.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK5.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK6.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BLK7.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN0.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN1.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN2.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN3.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN4.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN5.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN6.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_BRN7.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN0.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN1.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN2.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN3.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN4.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN5.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN6.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRN7.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY0.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY1.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY2.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY3.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY4.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY5.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY6.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_GRY7.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED0.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED1.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED2.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED3.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED4.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED5.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED6.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_RED7.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN0.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN1.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN2.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN3.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN4.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN5.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN6.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_TAN7.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT0.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT1.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT2.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT3.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT4.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT5.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT6.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/OWX_WHT7.BMF | Bin 0 -> 2350 bytes CONTENT/BT3025/VIDEO/MAT/RAPFX.BMF | Bin 0 -> 798 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAPSKIN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BLK7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_BRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_GRY7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_RED7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_TAN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAP_WHT7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAVBU.VMF | 50 + CONTENT/BT3025/VIDEO/MAT/RAVINES.BMF | Bin 0 -> 400 bytes CONTENT/BT3025/VIDEO/MAT/RAXFX.BMF | Bin 0 -> 798 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAXSKIN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BLK7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_BRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_GRY7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_RED7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_TAN7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT0.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT1.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT2.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT3.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT4.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT5.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT6.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/RAX_WHT7.BMF | Bin 0 -> 1110 bytes CONTENT/BT3025/VIDEO/MAT/SNDFX.BMF | Bin 0 -> 984 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN0.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN1.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN2.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN3.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN4.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN5.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN6.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNXSKIN7.BMF | Bin 0 -> 324 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK0.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK1.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK2.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK3.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK4.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK5.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK6.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BLK7.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN0.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN1.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN2.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN3.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN4.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN5.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN6.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_BRN7.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN0.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN1.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN2.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN3.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN4.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN5.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN6.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRN7.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY0.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY1.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY2.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY3.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY4.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY5.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY6.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_GRY7.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED0.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED1.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED2.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED3.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED4.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED5.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED6.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_RED7.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN0.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN1.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN2.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN3.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN4.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN5.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN6.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_TAN7.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT0.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT1.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT2.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT3.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT4.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT5.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT6.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/SNX_WHT7.BMF | Bin 0 -> 384 bytes CONTENT/BT3025/VIDEO/MAT/STIFX.BMF | Bin 0 -> 944 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STISKIN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BLK7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_BRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_GRY7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_RED7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_TAN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STI_WHT7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXFX.BMF | Bin 0 -> 944 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STXSKIN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BLK7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_BRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_GRY7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_RED7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_TAN7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT0.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT1.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT2.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT3.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT4.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT5.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT6.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/STX_WHT7.BMF | Bin 0 -> 956 bytes CONTENT/BT3025/VIDEO/MAT/THRFX.BMF | Bin 0 -> 1494 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN0.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN1.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN2.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN3.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN4.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN5.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN6.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THXSKIN7.BMF | Bin 0 -> 534 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK0.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK1.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK2.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK3.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK4.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK5.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK6.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BLK7.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN0.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN1.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN2.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN3.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN4.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN5.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN6.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_BRN7.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN0.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN1.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN2.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN3.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN4.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN5.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN6.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRN7.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY0.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY1.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY2.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY3.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY4.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY5.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY6.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_GRY7.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED0.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED1.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED2.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED3.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED4.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED5.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED6.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_RED7.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN0.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN1.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN2.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN3.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN4.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN5.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN6.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_TAN7.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT0.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT1.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT2.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT3.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT4.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT5.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT6.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/THX_WHT7.BMF | Bin 0 -> 744 bytes CONTENT/BT3025/VIDEO/MAT/VULFX.BMF | Bin 0 -> 898 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUXSKIN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BLK7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_BRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_GRY7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_RED7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_TAN7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT0.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT1.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT2.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT3.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT4.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT5.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT6.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAT/VUX_WHT7.BMF | Bin 0 -> 102 bytes CONTENT/BT3025/VIDEO/MAX1SKIN.DZM | 2 + CONTENT/BT3025/VIDEO/MAX2SKIN.DZM | 2 + CONTENT/BT3025/VIDEO/MAXSKIN.DZM | 2 + CONTENT/BT3025/VIDEO/MAXSKIN.ORG | 2 + CONTENT/BT3025/VIDEO/NAFC.PFX | 32 + CONTENT/BT3025/VIDEO/NBIGBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/NDAM1.PFX | 32 + CONTENT/BT3025/VIDEO/NDAM2.PFX | 32 + CONTENT/BT3025/VIDEO/NDAM3.PFX | 32 + CONTENT/BT3025/VIDEO/NDAM4.PFX | 33 + CONTENT/BT3025/VIDEO/NDAM5.PFX | 33 + CONTENT/BT3025/VIDEO/NDTHSMK.PFX | 32 + CONTENT/BT3025/VIDEO/NLRMTAIL.PFX | 33 + CONTENT/BT3025/VIDEO/NMEDBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/NMISSING.PFX | 33 + CONTENT/BT3025/VIDEO/NNBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/NSMLBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/NSRM.PFX | 33 + CONTENT/BT3025/VIDEO/NTRKBOOM.PFX | 33 + CONTENT/BT3025/VIDEO/NTRKBURN.PFX | 32 + CONTENT/BT3025/VIDEO/OWXSKIN.DZM | 35 + CONTENT/BT3025/VIDEO/PGN.SKL | 55 + CONTENT/BT3025/VIDEO/PGND.SKL | 55 + CONTENT/BT3025/VIDEO/RESULT2.TXT | 5 + CONTENT/BT3025/VIDEO/SHKWAVE.PFX | 33 + CONTENT/BT3025/VIDEO/SMLFLASH.PFX | 33 + CONTENT/BT3025/VIDEO/SMLSMOKE.PFX | 33 + CONTENT/BT3025/VIDEO/SNX2SKIN.DZM | 8 + CONTENT/BT3025/VIDEO/SNXSKIN.DZM | 8 + CONTENT/BT3025/VIDEO/STXSKIN.DZM | 11 + CONTENT/BT3025/VIDEO/TEX/BUILD/BDLGO128.BAT | 17 + CONTENT/BT3025/VIDEO/TEX/BUILD/BUILDLGO.BAT | 18 + CONTENT/BT3025/VIDEO/THX1SKIN.DZM | 11 + CONTENT/BT3025/VIDEO/THXSKIN.DZM | 11 + CONTENT/BT3025/VIDEO/VUL2SKIN.DZM | 79 + CONTENT/BT3025/VIDEO/VUX1SKIN.DZM | 2 + CONTENT/BT3025/VIDEO/VUX2SKIN.DZM | 2 + CONTENT/BT3025/VIDEO/VUXSKIN.DZM | 2 + CONTENT/BT3025/WATTCP.CFG | 4 + CONTENT/MTMCDAI.SYS | Bin 0 -> 16731 bytes CONTENT/RP/$$ARCALL.TMP | 7 + CONTENT/RP/32STUB.EXE | Bin 0 -> 2160 bytes CONTENT/RP/ANIM.BAT | 4 + CONTENT/RP/ANIMCAM.BAT | 60 + CONTENT/RP/ARCALL.BAT | 86 + CONTENT/RP/ARCFILES.LST | 23 + CONTENT/RP/ARCRP.BAT | 58 + CONTENT/RP/AUDIO/AUDIO.INI | 60 + CONTENT/RP/AUDIO/AUDIO.RES | 1 + CONTENT/RP/AUDIO/AUDIOMR.INI | 60 + CONTENT/RP/AUDIO/BARGE.SCP | 161 + CONTENT/RP/AUDIO/BLKSPK.SCP | 161 + CONTENT/RP/AUDIO/BROCCOLI.SCP | 201 + CONTENT/RP/AUDIO/BTLEXT.SCP | 71 + CONTENT/RP/AUDIO/BTTLBRG.SCP | 203 + CONTENT/RP/AUDIO/BUG.SCP | 161 + CONTENT/RP/AUDIO/BURRO.SCP | 136 + CONTENT/RP/AUDIO/CHIGGER.SCP | 177 + CONTENT/RP/AUDIO/CHUTE.SCP | 79 + CONTENT/RP/AUDIO/COLTWR1.SCP | 97 + CONTENT/RP/AUDIO/CTMIX.CFG | 15 + CONTENT/RP/AUDIO/DARK.SCP | 146 + CONTENT/RP/AUDIO/DARKEXT.SCP | 71 + CONTENT/RP/AUDIO/DEMOPACK.SCP | 97 + CONTENT/RP/AUDIO/DPEXP.SCP | 123 + CONTENT/RP/AUDIO/DRAGON.SCP | 186 + CONTENT/RP/AUDIO/FULTNK1.SCP | 97 + CONTENT/RP/AUDIO/GATOR.SCP | 193 + CONTENT/RP/AUDIO/GRUNT.SCP | 176 + CONTENT/RP/AUDIO/HVAC1.SCP | 101 + CONTENT/RP/AUDIO/HVAC2.SCP | 101 + CONTENT/RP/AUDIO/HVAC3.SCP | 101 + CONTENT/RP/AUDIO/ICOM.CFG | 15 + CONTENT/RP/AUDIO/LASEREXP.SCP | 135 + CONTENT/RP/AUDIO/LEPTON.SCP | 161 + CONTENT/RP/AUDIO/LSREXPC.SCP | 135 + CONTENT/RP/AUDIO/LSREXPI.SCP | 150 + CONTENT/RP/AUDIO/LSREXT.SCP | 97 + CONTENT/RP/AUDIO/MANTIS.SCP | 206 + CONTENT/RP/AUDIO/MTNCDR1.SCP | 132 + CONTENT/RP/AUDIO/MTNCDR2.SCP | 97 + CONTENT/RP/AUDIO/MTNCDR3.SCP | 97 + CONTENT/RP/AUDIO/MTNCDR4.SCP | 97 + CONTENT/RP/AUDIO/MTSEXT.SCP | 69 + CONTENT/RP/AUDIO/OREDRP1.SCP | 143 + CONTENT/RP/AUDIO/OREDRP2.SCP | 143 + CONTENT/RP/AUDIO/PCKEXT.SCP | 71 + CONTENT/RP/AUDIO/PLYEXT.SCP | 96 + CONTENT/RP/AUDIO/PLYINT.SCP | 143 + CONTENT/RP/AUDIO/QUARK.SCP | 160 + CONTENT/RP/AUDIO/RDBEXT.SCP | 70 + CONTENT/RP/AUDIO/REFINERY.SCP | 125 + CONTENT/RP/AUDIO/RIPPER.SCP | 176 + CONTENT/RP/AUDIO/RIVET.SCP | 97 + CONTENT/RP/AUDIO/RIVETEXP.SCP | 128 + CONTENT/RP/AUDIO/ROADBLK.SCP | 219 + CONTENT/RP/AUDIO/RVTEXPC.SCP | 128 + CONTENT/RP/AUDIO/RVTEXPI.SCP | 150 + CONTENT/RP/AUDIO/SCORING.SCP | 166 + CONTENT/RP/AUDIO/SKEETER.SCP | 187 + CONTENT/RP/AUDIO/SKTEXT.SCP | 71 + CONTENT/RP/AUDIO/SPITTER.SCP | 187 + CONTENT/RP/AUDIO/SYMBOLS.SCP | 40 + CONTENT/RP/AUDIO/TEMPLATE.SCP | 75 + CONTENT/RP/AUDIO/VCS.CFG | 1 + CONTENT/RP/AUDIO/VLEEXT.SCP | 69 + CONTENT/RP/AUDIO/VOLE.SCP | 186 + CONTENT/RP/AUDIO/VTVLSR.SCP | 121 + CONTENT/RP/AUDIO/VTVMNE.SCP | 74 + CONTENT/RP/AUDIO/VTVRVT.SCP | 109 + CONTENT/RP/AUDIO/WASP.SCP | 176 + CONTENT/RP/AUDIO/WELLHD1.SCP | 101 + CONTENT/RP/AUDIO/WELLHD2.SCP | 101 + CONTENT/RP/AUDIO/WELLHD3.SCP | 101 + CONTENT/RP/AUDIO/WELLHD4.SCP | 101 + CONTENT/RP/AUTOEXEC.BAT | 22 + CONTENT/RP/BLDFILES.LST | 32 + CONTENT/RP/BUILD.BAT | 6 + CONTENT/RP/BUILD1.BAT | 22 + CONTENT/RP/BUILDRES.BAK | 23 + CONTENT/RP/BUILDRES.BAT | 23 + CONTENT/RP/DEARCRP.BAT | 19 + CONTENT/RP/EXCLUDE.LST | 7 + CONTENT/RP/FAILURE.LOG | 13 + CONTENT/RP/FIND.TXT | 11 + CONTENT/RP/FRSTRM.BAT | 3 + CONTENT/RP/GAUGE/BP1_GA.GIM | 18 + CONTENT/RP/GAUGE/BR1B_GA.GIM | 17 + CONTENT/RP/GAUGE/BR1_GA.GIM | 17 + CONTENT/RP/GAUGE/BR2_GA.GIM | 15 + CONTENT/RP/GAUGE/BR3_GA.GIM | 17 + CONTENT/RP/GAUGE/BRE1_GA.GIM | 25 + CONTENT/RP/GAUGE/BUTCROSS.PCC | Bin 0 -> 1657 bytes CONTENT/RP/GAUGE/BUTHORN.PCC | Bin 0 -> 1634 bytes CONTENT/RP/GAUGE/BUTPRES1.PCC | Bin 0 -> 1583 bytes CONTENT/RP/GAUGE/BUTPRES2.PCC | Bin 0 -> 1587 bytes CONTENT/RP/GAUGE/BUTPRES3.PCC | Bin 0 -> 1599 bytes CONTENT/RP/GAUGE/BUTPRES4.PCC | Bin 0 -> 1597 bytes CONTENT/RP/GAUGE/BUTPRES5.PCC | Bin 0 -> 1595 bytes CONTENT/RP/GAUGE/BUTPRES6.PCC | Bin 0 -> 1603 bytes CONTENT/RP/GAUGE/BUTZMIN.PCC | Bin 0 -> 1629 bytes CONTENT/RP/GAUGE/BUTZMOUT.PCC | Bin 0 -> 1639 bytes CONTENT/RP/GAUGE/BU_GA.GIM | 70 + CONTENT/RP/GAUGE/CAMPAL.PCC | Bin 0 -> 899 bytes CONTENT/RP/GAUGE/CC1_GA.GIM | 20 + CONTENT/RP/GAUGE/CFGBOTH.PCC | Bin 0 -> 1518 bytes CONTENT/RP/GAUGE/CFGME.PCC | Bin 0 -> 1084 bytes CONTENT/RP/GAUGE/CFGNONE.PCC | Bin 0 -> 1084 bytes CONTENT/RP/GAUGE/CFGOTHER.PCC | Bin 0 -> 1897 bytes CONTENT/RP/GAUGE/CL1_GA.GIM | 20 + CONTENT/RP/GAUGE/CLKFONT.PCC | Bin 0 -> 1810 bytes CONTENT/RP/GAUGE/CN1_GA.GIM | 29 + CONTENT/RP/GAUGE/CN2_GA.GIM | 15 + CONTENT/RP/GAUGE/CN3U_GA.GIM | 20 + CONTENT/RP/GAUGE/CN3_GA.GIM | 20 + CONTENT/RP/GAUGE/CN4_GA.GIM | 15 + CONTENT/RP/GAUGE/CN5U_GA.GIM | 27 + CONTENT/RP/GAUGE/CN5_GA.GIM | 27 + CONTENT/RP/GAUGE/CN6_GA.GIM | 15 + CONTENT/RP/GAUGE/CN7U_GA.GIM | 29 + CONTENT/RP/GAUGE/CQ1_GA.GIM | 17 + CONTENT/RP/GAUGE/CQ2_GA.GIM | 16 + CONTENT/RP/GAUGE/CR1A_GA.GIM | 41 + CONTENT/RP/GAUGE/CR1_GA.GIM | 43 + CONTENT/RP/GAUGE/CR2_GA.GIM | 34 + CONTENT/RP/GAUGE/CR3_GA.GIM | 35 + CONTENT/RP/GAUGE/CR4_GA.GIM | 15 + CONTENT/RP/GAUGE/CR5_GA.GIM | 15 + CONTENT/RP/GAUGE/CR6_GA.GIM | 15 + CONTENT/RP/GAUGE/CR8_GA.GIM | 15 + CONTENT/RP/GAUGE/CRE_GA.GIM | 24 + CONTENT/RP/GAUGE/CT1_GA.GIM | 19 + CONTENT/RP/GAUGE/D45_GA.GIM | 17 + CONTENT/RP/GAUGE/DPACK_GA.BAK | 23 + CONTENT/RP/GAUGE/DPACK_GA.GIM | 23 + CONTENT/RP/GAUGE/DR1_GA.GIM | 32 + CONTENT/RP/GAUGE/DR2_GA.GIM | 32 + CONTENT/RP/GAUGE/DRW_GA.GIM | 36 + CONTENT/RP/GAUGE/FT1_GA.GIM | 19 + CONTENT/RP/GAUGE/GAR1_GA.GIM | 15 + CONTENT/RP/GAUGE/GAR2_GA.GIM | 16 + CONTENT/RP/GAUGE/GAR_GA.GIM | 21 + CONTENT/RP/GAUGE/GAUGE.BAK | 63 + CONTENT/RP/GAUGE/GAUGE.GAT | 63 + CONTENT/RP/GAUGE/GR1_GA.GIM | 37 + CONTENT/RP/GAUGE/GR2_GA.GIM | 36 + CONTENT/RP/GAUGE/HV5_GA.GIM | 15 + CONTENT/RP/GAUGE/HVE_GA.GIM | 15 + CONTENT/RP/GAUGE/L4GAUGE.1 | 20 + CONTENT/RP/GAUGE/L4GAUGE.2 | 17 + CONTENT/RP/GAUGE/L4GAUGE.GF | 1 + CONTENT/RP/GAUGE/L4GAUGE.INI | 36 + CONTENT/RP/GAUGE/MD3_GA.GIM | 15 + CONTENT/RP/GAUGE/MD4_GA.GIM | 15 + CONTENT/RP/GAUGE/ME1_GA.GIM | 20 + CONTENT/RP/GAUGE/ME3_GA.GIM | 15 + CONTENT/RP/GAUGE/MULE_GA.GIM | 1 + CONTENT/RP/GAUGE/MU_GA.GIM | 56 + CONTENT/RP/GAUGE/OA1_GA.GIM | 15 + CONTENT/RP/GAUGE/OA3_GA.GIM | 15 + CONTENT/RP/GAUGE/OAO_GA.GIM | 15 + CONTENT/RP/GAUGE/OD3_GA.GIM | 34 + CONTENT/RP/GAUGE/PIT1_GA.GIM | 26 + CONTENT/RP/GAUGE/PIT2_GA.GIM | 26 + CONTENT/RP/GAUGE/PL1_GA.GIM | 27 + CONTENT/RP/GAUGE/PM1_GA.GIM | 19 + CONTENT/RP/GAUGE/PO_GA.GIM | 58 + CONTENT/RP/GAUGE/RF1_GA.GIM | 39 + CONTENT/RP/GAUGE/RIVET_GA.GIM | 15 + CONTENT/RP/GAUGE/RL1_GA.GIM | 15 + CONTENT/RP/GAUGE/RL2_GA.GIM | 15 + CONTENT/RP/GAUGE/RL3_GA.GIM | 15 + CONTENT/RP/GAUGE/RP1_GA.GIM | 15 + CONTENT/RP/GAUGE/RP2_GA.GIM | 15 + CONTENT/RP/GAUGE/RP3_GA.GIM | 15 + CONTENT/RP/GAUGE/RPSALTB.PCC | Bin 0 -> 1719 bytes CONTENT/RP/GAUGE/RPSCMPB.PCC | Bin 0 -> 964 bytes CONTENT/RP/GAUGE/RPSCMPE.PCC | Bin 0 -> 938 bytes CONTENT/RP/GAUGE/RPSCMPN.PCC | Bin 0 -> 959 bytes CONTENT/RP/GAUGE/RPSCMPS.PCC | Bin 0 -> 943 bytes CONTENT/RP/GAUGE/RPSCMPW.PCC | Bin 0 -> 975 bytes CONTENT/RP/GAUGE/RPSREV.PCC | Bin 0 -> 1004 bytes CONTENT/RP/GAUGE/RPSSPDB.PCC | Bin 0 -> 1029 bytes CONTENT/RP/GAUGE/SC500_GA.GIM | 15 + CONTENT/RP/GAUGE/SC50_GA.GIM | 15 + CONTENT/RP/GAUGE/SDBU.PCC | Bin 0 -> 2484 bytes CONTENT/RP/GAUGE/SDLU.PCC | Bin 0 -> 1753 bytes CONTENT/RP/GAUGE/SDMA.PCC | Bin 0 -> 2495 bytes CONTENT/RP/GAUGE/SDPA.PCC | Bin 0 -> 2229 bytes CONTENT/RP/GAUGE/SDPO.PCC | Bin 0 -> 2136 bytes CONTENT/RP/GAUGE/SDPU.PCC | Bin 0 -> 2229 bytes CONTENT/RP/GAUGE/SDSA.PCC | Bin 0 -> 2024 bytes CONTENT/RP/GAUGE/SDSU.PCC | Bin 0 -> 2167 bytes CONTENT/RP/GAUGE/SECPAL.PCC | Bin 0 -> 899 bytes CONTENT/RP/GAUGE/SLU.PCC | Bin 0 -> 1985 bytes CONTENT/RP/GAUGE/SMLFONT.PCC | Bin 0 -> 1901 bytes CONTENT/RP/GAUGE/SPO.PCC | Bin 0 -> 2450 bytes CONTENT/RP/GAUGE/SP_GA.GIM | 58 + CONTENT/RP/GAUGE/SSA.PCC | Bin 0 -> 2239 bytes CONTENT/RP/GAUGE/SSU.PCC | Bin 0 -> 2367 bytes CONTENT/RP/GAUGE/STING.BAK | 23 + CONTENT/RP/GAUGE/STING.GIM | 23 + CONTENT/RP/GAUGE/TINYFONT.PCC | Bin 0 -> 1191 bytes CONTENT/RP/GAUGE/TRS_GA.GIM | 17 + CONTENT/RP/GAUGE/VCS.CFG | 1 + CONTENT/RP/GAUGE/VM1_GA.GIM | 15 + CONTENT/RP/GAUGE/WH1_GA.GIM | 37 + CONTENT/RP/GAUGE/WH2_GA.GIM | 36 + CONTENT/RP/GAUGE/WH3_GA.GIM | 37 + CONTENT/RP/GAUGE/WH4_GA.GIM | 37 + CONTENT/RP/GAUGE/WH5_GA.GIM | 37 + CONTENT/RP/GAUGE/WH6_GA.GIM | 87 + CONTENT/RP/GAUGE/WH9_GA.GIM | 25 + CONTENT/RP/GAUGE/WT1_GA.GIM | 37 + CONTENT/RP/GETAUD.BAT | 44 + CONTENT/RP/GETVID.BAT | 44 + CONTENT/RP/GO.BAT | 1 + CONTENT/RP/GRABOPT.BAT | 2 + CONTENT/RP/GRABRES.BAT | 36 + CONTENT/RP/JOYSTICK.INI | 26 + CONTENT/RP/LAST.EGG | 243 + CONTENT/RP/MAKEEGG.BAT | 72 + CONTENT/RP/MAPS/ALL.ZNE | 28 + CONTENT/RP/MAPS/ARENA.CAM | 300 + CONTENT/RP/MAPS/BLADE.CAM | 315 + CONTENT/RP/MAPS/BLANK.CAM | 240 + CONTENT/RP/MAPS/BLANK.SCN | 124 + CONTENT/RP/MAPS/BREWERS.CAM | 299 + CONTENT/RP/MAPS/BURNT.BAK | 255 + CONTENT/RP/MAPS/BURNT.CAM | 255 + CONTENT/RP/MAPS/CANAL.MAP | 35 + CONTENT/RP/MAPS/CN | 2 + CONTENT/RP/MAPS/DR.MAP | 103 + CONTENT/RP/MAPS/FIRST.MAP | 36 + CONTENT/RP/MAPS/GENE.MAP | 54 + CONTENT/RP/MAPS/GREG.MAP | 60 + CONTENT/RP/MAPS/HEADMF.CAM | 269 + CONTENT/RP/MAPS/HEADOFF.BAK | 269 + CONTENT/RP/MAPS/LYZLANE.CAM | 180 + CONTENT/RP/MAPS/PAIN.CAM | 270 + CONTENT/RP/MAPS/PUCKLAND.CAM | 88 + CONTENT/RP/MAPS/PUCKLAND.MAP | 1 + CONTENT/RP/MAPS/THIRD.MAP | 60 + CONTENT/RP/MAPS/THRDRACE.SCE | 6 + CONTENT/RP/MAPS/VCS.CFG | 1 + CONTENT/RP/MAPS/YIP.CAM | 300 + CONTENT/RP/MENU.BAT | 55 + CONTENT/RP/MODELS/2LSRTHR.CTL | 100 + CONTENT/RP/MODELS/2RIVTHR.CTL | 99 + CONTENT/RP/MODELS/2X6L4.CTL | 170 + CONTENT/RP/MODELS/2X6THR.CTL | 83 + CONTENT/RP/MODELS/3RIVTHR.CTL | 127 + CONTENT/RP/MODELS/3X4L4.CTL | 208 + CONTENT/RP/MODELS/3X4THR.CTL | 90 + CONTENT/RP/MODELS/4X4L4.CTL | 246 + CONTENT/RP/MODELS/4X4THR.CTL | 97 + CONTENT/RP/MODELS/BAN.DMG | 1 + CONTENT/RP/MODELS/BAN.MOD | 1 + CONTENT/RP/MODELS/BARGE.BAK | 47 + CONTENT/RP/MODELS/BARGE.DMG | 2 + CONTENT/RP/MODELS/BARGE.MOD | 47 + CONTENT/RP/MODELS/BARGE.SUB | 21 + CONTENT/RP/MODELS/BARGEL4.CTL | 1 + CONTENT/RP/MODELS/BARGETHR.CTL | 1 + CONTENT/RP/MODELS/BAS.DMG | 1 + CONTENT/RP/MODELS/BAS.MOD | 1 + CONTENT/RP/MODELS/BAS.SUB | 1 + CONTENT/RP/MODELS/BASL4.CTL | 1 + CONTENT/RP/MODELS/BASTHR.CTL | 1 + CONTENT/RP/MODELS/BAT.DMG | 1 + CONTENT/RP/MODELS/BAT.MOD | 1 + CONTENT/RP/MODELS/BLKSPK.DMG | 2 + CONTENT/RP/MODELS/BLKSPK.MOD | 47 + CONTENT/RP/MODELS/BLKSPK.SUB | 27 + CONTENT/RP/MODELS/BLKTRN.DMG | 2 + CONTENT/RP/MODELS/BLKTRN.MOD | 48 + CONTENT/RP/MODELS/BLKTRN.SUB | 33 + CONTENT/RP/MODELS/BN1.MOD | 9 + CONTENT/RP/MODELS/BP1.MOD | 11 + CONTENT/RP/MODELS/BR1.MOD | 12 + CONTENT/RP/MODELS/BR1A.MOD | 12 + CONTENT/RP/MODELS/BR1B.MOD | 6 + CONTENT/RP/MODELS/BR2.MOD | 12 + CONTENT/RP/MODELS/BR3.MOD | 12 + CONTENT/RP/MODELS/BR4.MOD | 12 + CONTENT/RP/MODELS/BRE1.MOD | 9 + CONTENT/RP/MODELS/BREW.MOD | 6 + CONTENT/RP/MODELS/BROCCOLI.BAK | 27 + CONTENT/RP/MODELS/BROCCOLI.DMG | 2 + CONTENT/RP/MODELS/BROCCOLI.MOD | 47 + CONTENT/RP/MODELS/BROCCOLI.SUB | 27 + CONTENT/RP/MODELS/BTTLBRG.BAK | 48 + CONTENT/RP/MODELS/BTTLBRG.DMG | 2 + CONTENT/RP/MODELS/BTTLBRG.MOD | 48 + CONTENT/RP/MODELS/BTTLBRG.SUB | 44 + CONTENT/RP/MODELS/BTTLTHR.CTL | 89 + CONTENT/RP/MODELS/BUG.BAK | 47 + CONTENT/RP/MODELS/BUG.DMG | 2 + CONTENT/RP/MODELS/BUG.MOD | 47 + CONTENT/RP/MODELS/BUG.SUB | 21 + CONTENT/RP/MODELS/BULL.BAK | 48 + CONTENT/RP/MODELS/BULL.DMG | 2 + CONTENT/RP/MODELS/BULL.MOD | 48 + CONTENT/RP/MODELS/BULL.SUB | 21 + CONTENT/RP/MODELS/BULLET.MOD | 15 + CONTENT/RP/MODELS/BUN.DMG | 1 + CONTENT/RP/MODELS/BUN.MOD | 1 + CONTENT/RP/MODELS/BURRO.BAK | 47 + CONTENT/RP/MODELS/BURRO.DMG | 2 + CONTENT/RP/MODELS/BURRO.MOD | 47 + CONTENT/RP/MODELS/BURRO.SUB | 16 + CONTENT/RP/MODELS/BURROL4.CTL | 137 + CONTENT/RP/MODELS/BURROTHR.CTL | 76 + CONTENT/RP/MODELS/BUS.DMG | 1 + CONTENT/RP/MODELS/BUS.MOD | 1 + CONTENT/RP/MODELS/BUS.SUB | 1 + CONTENT/RP/MODELS/BUSL4.CTL | 1 + CONTENT/RP/MODELS/BUSTHR.CTL | 1 + CONTENT/RP/MODELS/BUT.DMG | 1 + CONTENT/RP/MODELS/BUT.MOD | 1 + CONTENT/RP/MODELS/C8E.MOD | 8 + CONTENT/RP/MODELS/CAMERA.MOD | 17 + CONTENT/RP/MODELS/CAMPOS.MOD | 9 + CONTENT/RP/MODELS/CAP.MOD | 6 + CONTENT/RP/MODELS/CC1.MOD | 12 + CONTENT/RP/MODELS/CHIGGER.BAK | 47 + CONTENT/RP/MODELS/CHIGGER.DMG | 2 + CONTENT/RP/MODELS/CHIGGER.MOD | 47 + CONTENT/RP/MODELS/CHIGGER.SUB | 31 + CONTENT/RP/MODELS/CL1.MOD | 12 + CONTENT/RP/MODELS/CL2.MOD | 10 + CONTENT/RP/MODELS/CL3.MOD | 9 + CONTENT/RP/MODELS/CLD.MOD | 6 + CONTENT/RP/MODELS/CN1.MOD | 11 + CONTENT/RP/MODELS/CN2.MOD | 11 + CONTENT/RP/MODELS/CN3.MOD | 12 + CONTENT/RP/MODELS/CN3U.MOD | 12 + CONTENT/RP/MODELS/CN4.MOD | 12 + CONTENT/RP/MODELS/CN5.MOD | 11 + CONTENT/RP/MODELS/CN5N.MOD | 8 + CONTENT/RP/MODELS/CN5U.MOD | 11 + CONTENT/RP/MODELS/CN6.MOD | 11 + CONTENT/RP/MODELS/CN7.MOD | 12 + CONTENT/RP/MODELS/CN7U.MOD | 11 + CONTENT/RP/MODELS/CQ1.MOD | 12 + CONTENT/RP/MODELS/CQ1A.MOD | 12 + CONTENT/RP/MODELS/CQ2.MOD | 12 + CONTENT/RP/MODELS/CR1.MOD | 15 + CONTENT/RP/MODELS/CR1A.MOD | 15 + CONTENT/RP/MODELS/CR2.MOD | 15 + CONTENT/RP/MODELS/CR3.MOD | 15 + CONTENT/RP/MODELS/CR4.MOD | 12 + CONTENT/RP/MODELS/CR5.MOD | 12 + CONTENT/RP/MODELS/CR5U.MOD | 12 + CONTENT/RP/MODELS/CR6.MOD | 12 + CONTENT/RP/MODELS/CR7.MOD | 14 + CONTENT/RP/MODELS/CR8.MOD | 11 + CONTENT/RP/MODELS/CRE.MOD | 12 + CONTENT/RP/MODELS/CRP.MOD | 10 + CONTENT/RP/MODELS/CT1.MOD | 15 + CONTENT/RP/MODELS/D45.MOD | 9 + CONTENT/RP/MODELS/DARK.DMG | 2 + CONTENT/RP/MODELS/DARK.MOD | 47 + CONTENT/RP/MODELS/DARK.SUB | 36 + CONTENT/RP/MODELS/DARKL4.CTL | 206 + CONTENT/RP/MODELS/DARKTHR.CTL | 100 + CONTENT/RP/MODELS/DEMO2.BAK | 29 + CONTENT/RP/MODELS/DEMO2.MOD | 29 + CONTENT/RP/MODELS/DEMO3.MOD | 29 + CONTENT/RP/MODELS/DEMOPACK.MOD | 29 + CONTENT/RP/MODELS/DP2THR.CTL | 101 + CONTENT/RP/MODELS/DPEXP.MOD | 9 + CONTENT/RP/MODELS/DPL4.CTL | 206 + CONTENT/RP/MODELS/DPTHR.CTL | 86 + CONTENT/RP/MODELS/DR1.MOD | 12 + CONTENT/RP/MODELS/DR2.MOD | 12 + CONTENT/RP/MODELS/DRAGON.BAK | 50 + CONTENT/RP/MODELS/DRAGON.DMG | 2 + CONTENT/RP/MODELS/DRAGON.MOD | 50 + CONTENT/RP/MODELS/DRAGON.SUB | 64 + CONTENT/RP/MODELS/DRGNL4.CTL | 95 + CONTENT/RP/MODELS/DRGNTHR.CTL | 54 + CONTENT/RP/MODELS/DRW.MOD | 18 + CONTENT/RP/MODELS/DRW.SUB | 13 + CONTENT/RP/MODELS/DRW2.MOD | 18 + CONTENT/RP/MODELS/DRW2.SUB | 13 + CONTENT/RP/MODELS/DRW_1.BAK | 14 + CONTENT/RP/MODELS/DRW_1.MOD | 14 + CONTENT/RP/MODELS/EFFECT.MOD | 4 + CONTENT/RP/MODELS/EXPLODE.MOD | 2 + CONTENT/RP/MODELS/FLEA.BAK | 47 + CONTENT/RP/MODELS/FLEA.DMG | 2 + CONTENT/RP/MODELS/FLEA.MOD | 47 + CONTENT/RP/MODELS/FLEA.SUB | 30 + CONTENT/RP/MODELS/FT1.MOD | 15 + CONTENT/RP/MODELS/FT2.MOD | 16 + CONTENT/RP/MODELS/FT2U.MOD | 15 + CONTENT/RP/MODELS/GAR.MOD | 9 + CONTENT/RP/MODELS/GAR1.MOD | 9 + CONTENT/RP/MODELS/GAR2.MOD | 9 + CONTENT/RP/MODELS/GATOR.BAK | 47 + CONTENT/RP/MODELS/GATOR.MOD | 47 + CONTENT/RP/MODELS/GATOR.SUB | 40 + CONTENT/RP/MODELS/GATORTHR.CTL | 89 + CONTENT/RP/MODELS/GR1.MOD | 12 + CONTENT/RP/MODELS/GR2.MOD | 12 + CONTENT/RP/MODELS/GRUNT.BAK | 47 + CONTENT/RP/MODELS/GRUNT.DMG | 2 + CONTENT/RP/MODELS/GRUNT.MOD | 47 + CONTENT/RP/MODELS/GRUNT.SUB | 31 + CONTENT/RP/MODELS/HDOFF.MOD | 6 + CONTENT/RP/MODELS/HOME.MOD | 5 + CONTENT/RP/MODELS/HRIVET.MOD | 22 + CONTENT/RP/MODELS/HV1.MOD | 9 + CONTENT/RP/MODELS/HV2.MOD | 9 + CONTENT/RP/MODELS/HV4.MOD | 10 + CONTENT/RP/MODELS/HV5.MOD | 15 + CONTENT/RP/MODELS/HV6.MOD | 12 + CONTENT/RP/MODELS/HV7.MOD | 12 + CONTENT/RP/MODELS/HVA.MOD | 10 + CONTENT/RP/MODELS/HVB.MOD | 10 + CONTENT/RP/MODELS/HVC.MOD | 10 + CONTENT/RP/MODELS/HVE.MOD | 12 + CONTENT/RP/MODELS/LASEREXP.MOD | 10 + CONTENT/RP/MODELS/LASERL4.CTL | 202 + CONTENT/RP/MODELS/LASERTHR.CTL | 86 + CONTENT/RP/MODELS/LAZDRIL.MOD | 15 + CONTENT/RP/MODELS/LEPTON.BAK | 48 + CONTENT/RP/MODELS/LEPTON.DMG | 2 + CONTENT/RP/MODELS/LEPTON.MOD | 48 + CONTENT/RP/MODELS/LEPTON.SUB | 21 + CONTENT/RP/MODELS/LRIVET.MOD | 22 + CONTENT/RP/MODELS/LSREXPC.MOD | 9 + CONTENT/RP/MODELS/LSREXPI.MOD | 9 + CONTENT/RP/MODELS/MAN.DMG | 1 + CONTENT/RP/MODELS/MAN.MOD | 1 + CONTENT/RP/MODELS/MANTIS.BAK | 49 + CONTENT/RP/MODELS/MANTIS.DMG | 2 + CONTENT/RP/MODELS/MANTIS.MOD | 49 + CONTENT/RP/MODELS/MANTIS.SUB | 49 + CONTENT/RP/MODELS/MAS.CTL | 1 + CONTENT/RP/MODELS/MAS.DMG | 1 + CONTENT/RP/MODELS/MAS.MOD | 1 + CONTENT/RP/MODELS/MAS.SUB | 1 + CONTENT/RP/MODELS/MASL4.CTL | 1 + CONTENT/RP/MODELS/MASTHR.CTL | 1 + CONTENT/RP/MODELS/MAT.DMG | 1 + CONTENT/RP/MODELS/MAT.MOD | 1 + CONTENT/RP/MODELS/MB1.MOD | 9 + CONTENT/RP/MODELS/MB1A.MOD | 9 + CONTENT/RP/MODELS/MCS.MOD | 9 + CONTENT/RP/MODELS/MD1.MOD | 9 + CONTENT/RP/MODELS/MD2.MOD | 9 + CONTENT/RP/MODELS/MD3.MOD | 13 + CONTENT/RP/MODELS/MD4.MOD | 13 + CONTENT/RP/MODELS/MD5.MOD | 7 + CONTENT/RP/MODELS/MDD.MOD | 9 + CONTENT/RP/MODELS/ME1.MOD | 11 + CONTENT/RP/MODELS/ME2.MOD | 9 + CONTENT/RP/MODELS/ME3.MOD | 13 + CONTENT/RP/MODELS/ME4.MOD | 10 + CONTENT/RP/MODELS/MED.MOD | 9 + CONTENT/RP/MODELS/MI1.MOD | 9 + CONTENT/RP/MODELS/MISSILE.MOD | 7 + CONTENT/RP/MODELS/MRIVET.MOD | 22 + CONTENT/RP/MODELS/MS1.MOD | 1 + CONTENT/RP/MODELS/MS2.MOD | 1 + CONTENT/RP/MODELS/MULE.BAK | 47 + CONTENT/RP/MODELS/MULE.DMG | 2 + CONTENT/RP/MODELS/MULE.MOD | 47 + CONTENT/RP/MODELS/MULE.SUB | 21 + CONTENT/RP/MODELS/MUN.DMG | 1 + CONTENT/RP/MODELS/MUN.MOD | 1 + CONTENT/RP/MODELS/MUS.DMG | 1 + CONTENT/RP/MODELS/MUS.MOD | 1 + CONTENT/RP/MODELS/MUS.SUB | 1 + CONTENT/RP/MODELS/MUSL4.CTL | 1 + CONTENT/RP/MODELS/MUSTHR.CTL | 1 + CONTENT/RP/MODELS/MUT.DMG | 1 + CONTENT/RP/MODELS/MUT.MOD | 1 + CONTENT/RP/MODELS/OA1.MOD | 12 + CONTENT/RP/MODELS/OA1N.MOD | 6 + CONTENT/RP/MODELS/OA3.MOD | 12 + CONTENT/RP/MODELS/OAO.MOD | 9 + CONTENT/RP/MODELS/OAO1.MOD | 6 + CONTENT/RP/MODELS/OD1.MOD | 12 + CONTENT/RP/MODELS/OD2.MOD | 13 + CONTENT/RP/MODELS/OD3.MOD | 16 + CONTENT/RP/MODELS/ODC.MOD | 10 + CONTENT/RP/MODELS/PIT1.MOD | 9 + CONTENT/RP/MODELS/PIT2.MOD | 9 + CONTENT/RP/MODELS/PL1.MOD | 12 + CONTENT/RP/MODELS/PLAYER.MOD | 4 + CONTENT/RP/MODELS/PM1.MOD | 12 + CONTENT/RP/MODELS/PP1.MOD | 9 + CONTENT/RP/MODELS/PP2.MOD | 9 + CONTENT/RP/MODELS/PRESHOW.MOD | 13 + CONTENT/RP/MODELS/PROTON.BAK | 48 + CONTENT/RP/MODELS/PROTON.DMG | 2 + CONTENT/RP/MODELS/PROTON.MOD | 48 + CONTENT/RP/MODELS/PROTON.SUB | 31 + CONTENT/RP/MODELS/PUCK.DMG | 2 + CONTENT/RP/MODELS/PUCK.MOD | 47 + CONTENT/RP/MODELS/PUCK.SUB | 19 + CONTENT/RP/MODELS/PUCKL4.CTL | 133 + CONTENT/RP/MODELS/PUCKTHR.CTL | 72 + CONTENT/RP/MODELS/PZ1.MOD | 9 + CONTENT/RP/MODELS/PZ2.MOD | 9 + CONTENT/RP/MODELS/PZ3.MOD | 10 + CONTENT/RP/MODELS/PZ4.MOD | 10 + CONTENT/RP/MODELS/QUARK.BAK | 48 + CONTENT/RP/MODELS/QUARK.DMG | 2 + CONTENT/RP/MODELS/QUARK.MOD | 48 + CONTENT/RP/MODELS/QUARK.SUB | 11 + CONTENT/RP/MODELS/QUARKL4.CTL | 125 + CONTENT/RP/MODELS/QUARKTHR.CTL | 66 + CONTENT/RP/MODELS/RDBLKL4X.CTL | 1 + CONTENT/RP/MODELS/RDBLKTHR.CTL | 99 + CONTENT/RP/MODELS/RF1.MOD | 14 + CONTENT/RP/MODELS/RIPPER.BAK | 48 + CONTENT/RP/MODELS/RIPPER.DMG | 2 + CONTENT/RP/MODELS/RIPPER.MOD | 48 + CONTENT/RP/MODELS/RIPPER.SUB | 31 + CONTENT/RP/MODELS/RIVET.MOD | 19 + CONTENT/RP/MODELS/RIVETEXP.MOD | 10 + CONTENT/RP/MODELS/RIVETL4.CTL | 201 + CONTENT/RP/MODELS/RIVETTHR.CTL | 86 + CONTENT/RP/MODELS/RL1.MOD | 12 + CONTENT/RP/MODELS/RL2.MOD | 13 + CONTENT/RP/MODELS/RL3.MOD | 13 + CONTENT/RP/MODELS/ROACH.BAK | 47 + CONTENT/RP/MODELS/ROACH.DMG | 2 + CONTENT/RP/MODELS/ROACH.MOD | 47 + CONTENT/RP/MODELS/ROACH.SUB | 42 + CONTENT/RP/MODELS/ROADBLK.BAK | 55 + CONTENT/RP/MODELS/ROADBLK.DMG | 2 + CONTENT/RP/MODELS/ROADBLK.MOD | 48 + CONTENT/RP/MODELS/ROADBLK.SUB | 55 + CONTENT/RP/MODELS/RP0.MOD | 9 + CONTENT/RP/MODELS/RP1.MOD | 11 + CONTENT/RP/MODELS/RP2.MOD | 12 + CONTENT/RP/MODELS/RP3.MOD | 12 + CONTENT/RP/MODELS/RVTEXPC.MOD | 9 + CONTENT/RP/MODELS/RVTEXPI.MOD | 9 + CONTENT/RP/MODELS/SAN.DMG | 1 + CONTENT/RP/MODELS/SAN.MOD | 1 + CONTENT/RP/MODELS/SAS.DMG | 1 + CONTENT/RP/MODELS/SAS.MOD | 1 + CONTENT/RP/MODELS/SAS.SUB | 1 + CONTENT/RP/MODELS/SASL4.CTL | 1 + CONTENT/RP/MODELS/SASTHR.CTL | 1 + CONTENT/RP/MODELS/SAT.DMG | 1 + CONTENT/RP/MODELS/SAT.MOD | 1 + CONTENT/RP/MODELS/SC50.MOD | 11 + CONTENT/RP/MODELS/SC500.MOD | 8 + CONTENT/RP/MODELS/SC500A.MOD | 6 + CONTENT/RP/MODELS/SC50A.MOD | 6 + CONTENT/RP/MODELS/SKEETER.BAK | 49 + CONTENT/RP/MODELS/SKEETER.MOD | 49 + CONTENT/RP/MODELS/SKEETER.SUB | 35 + CONTENT/RP/MODELS/SKTRL4.CTL | 206 + CONTENT/RP/MODELS/SKTRTHR.CTL | 86 + CONTENT/RP/MODELS/SNAALE.MOD | 6 + CONTENT/RP/MODELS/SNACRANE.MOD | 7 + CONTENT/RP/MODELS/SNADOS.MOD | 7 + CONTENT/RP/MODELS/SNAENTER.MOD | 7 + CONTENT/RP/MODELS/SNAEVAC.MOD | 7 + CONTENT/RP/MODELS/SNAHAZ.MOD | 7 + CONTENT/RP/MODELS/SNAHEADM.MOD | 7 + CONTENT/RP/MODELS/SNALIMIT.MOD | 7 + CONTENT/RP/MODELS/SNALOXM.MOD | 7 + CONTENT/RP/MODELS/SNAMFAC.MOD | 7 + CONTENT/RP/MODELS/SNANORC.MOD | 7 + CONTENT/RP/MODELS/SNARADS.MOD | 7 + CONTENT/RP/MODELS/SNASPDS.MOD | 7 + CONTENT/RP/MODELS/SNATSPD.MOD | 7 + CONTENT/RP/MODELS/SNAWELC.MOD | 7 + CONTENT/RP/MODELS/SNAWORK.MOD | 7 + CONTENT/RP/MODELS/SPECK.BAK | 47 + CONTENT/RP/MODELS/SPECK.DMG | 2 + CONTENT/RP/MODELS/SPECK.MOD | 47 + CONTENT/RP/MODELS/SPECK.SUB | 21 + CONTENT/RP/MODELS/SPITTER.BAK | 48 + CONTENT/RP/MODELS/SPITTER.DMG | 2 + CONTENT/RP/MODELS/SPITTER.MOD | 48 + CONTENT/RP/MODELS/SPITTER.SUB | 41 + CONTENT/RP/MODELS/STAD.MOD | 1 + CONTENT/RP/MODELS/STATIC.ONL | 21 + CONTENT/RP/MODELS/STATIC.SCP | 1 + CONTENT/RP/MODELS/STL4.CTL | 206 + CONTENT/RP/MODELS/STTHR.CTL | 86 + CONTENT/RP/MODELS/SUN.DMG | 1 + CONTENT/RP/MODELS/SUN.MOD | 1 + CONTENT/RP/MODELS/SUS.DMG | 1 + CONTENT/RP/MODELS/SUS.MOD | 1 + CONTENT/RP/MODELS/SUS.SUB | 1 + CONTENT/RP/MODELS/SUSL4.CTL | 1 + CONTENT/RP/MODELS/SUSTHR.CTL | 1 + CONTENT/RP/MODELS/SUT.DMG | 1 + CONTENT/RP/MODELS/SUT.MOD | 1 + CONTENT/RP/MODELS/TARNTULA.BAK | 48 + CONTENT/RP/MODELS/TARNTULA.DMG | 2 + CONTENT/RP/MODELS/TARNTULA.MOD | 48 + CONTENT/RP/MODELS/TARNTULA.SUB | 27 + CONTENT/RP/MODELS/TRS.MOD | 12 + CONTENT/RP/MODELS/TS1.MOD | 9 + CONTENT/RP/MODELS/TUN1.MOD | 6 + CONTENT/RP/MODELS/VCS.CFG | 2 + CONTENT/RP/MODELS/VEHICLE.TBL | 56 + CONTENT/RP/MODELS/VM1.MOD | 12 + CONTENT/RP/MODELS/VOLE.BAK | 48 + CONTENT/RP/MODELS/VOLE.MOD | 48 + CONTENT/RP/MODELS/VOLE.SUB | 35 + CONTENT/RP/MODELS/WASP.BAK | 47 + CONTENT/RP/MODELS/WASP.DMG | 2 + CONTENT/RP/MODELS/WASP.MOD | 47 + CONTENT/RP/MODELS/WASP.SUB | 31 + CONTENT/RP/MODELS/WCIRCLE.MOD | 8 + CONTENT/RP/MODELS/WH1.MOD | 15 + CONTENT/RP/MODELS/WH2.MOD | 15 + CONTENT/RP/MODELS/WH4.MOD | 16 + CONTENT/RP/MODELS/WH5.MOD | 16 + CONTENT/RP/MODELS/WH6.MOD | 15 + CONTENT/RP/MODELS/WH6U.MOD | 15 + CONTENT/RP/MODELS/WH8.MOD | 10 + CONTENT/RP/MODELS/WH9.MOD | 14 + CONTENT/RP/MODELS/WHC.MOD | 12 + CONTENT/RP/MODELS/WINBOX.MOD | 6 + CONTENT/RP/MODELS/WT1.MOD | 15 + CONTENT/RP/MODELS/WT2.MOD | 11 + CONTENT/RP/NULL | 15 + CONTENT/RP/RESULT2.TXT | 23 + CONTENT/RP/RP.BAT | 24 + CONTENT/RP/RPCAM.BAT | 41 + CONTENT/RP/RPGO.BAT | 8 + CONTENT/RP/RPL4.BAK | 109 + CONTENT/RP/RPL4.BLD | 109 + CONTENT/RP/RPL4.BL_ | 70 + CONTENT/RP/RPL4.OPS | 157 + CONTENT/RP/RPL4.OP_ | 121 + CONTENT/RP/RPL4JM.BLD | 70 + CONTENT/RP/RPLOOK.BAT | 17 + CONTENT/RP/RPNET.BAT | 22 + CONTENT/RP/RPPREP.BAT | 53 + CONTENT/RP/RPSPL.BAT | 24 + CONTENT/RP/SCENES/CAM.BAT | 2 + CONTENT/RP/SCENES/DONTNEED.SPL | 4 + CONTENT/RP/SCENES/FRSTRM.CAM | 300 + CONTENT/RP/SCENES/GO.BAT | 4 + CONTENT/RP/SCENES/JOYSTICK.CAL | 6 + CONTENT/RP/SCENES/NEXT.BAT | 1 + CONTENT/RP/SCENES/ONETHING.SCN | 28 + CONTENT/RP/SCENES/OTTOCAM.SPL | 3 + CONTENT/RP/SCENES/RPFLY.BAT | 27 + CONTENT/RP/SCENES/SETNTSC.BAT | 1 + CONTENT/RP/SCENES/SETSVGA.BAT | 1 + CONTENT/RP/SCENES/SETSVGA6.BAT | 1 + CONTENT/RP/SHOWENV.BAT | 14 + CONTENT/RP/SOLIDS/BA_CV.SLD | 29 + CONTENT/RP/SOLIDS/BLADE.XST | 71 + CONTENT/RP/SOLIDS/BLANK.XST | 89 + CONTENT/RP/SOLIDS/BN1_CV.SLD | 29 + CONTENT/RP/SOLIDS/BP1_CV.SLD | 113 + CONTENT/RP/SOLIDS/BR1A_CV.SLD | 49 + CONTENT/RP/SOLIDS/BR1B_CV.SLD | 49 + CONTENT/RP/SOLIDS/BR1_CV.SLD | 92 + CONTENT/RP/SOLIDS/BR3_CV.SLD | 29 + CONTENT/RP/SOLIDS/BRE1_CV.SLD | 268 + CONTENT/RP/SOLIDS/BREWERS.XST | 168 + CONTENT/RP/SOLIDS/BREW_CV.SLD | 292 + CONTENT/RP/SOLIDS/BURNT.BAK | 32 + CONTENT/RP/SOLIDS/BURNT.XST | 32 + CONTENT/RP/SOLIDS/BU_CV.SLD | 29 + CONTENT/RP/SOLIDS/C8E_CV.SLD | 176 + CONTENT/RP/SOLIDS/CAP_CV.SLD | 28 + CONTENT/RP/SOLIDS/CC1_CV.SLD | 154 + CONTENT/RP/SOLIDS/CHG_CV.SLD | 29 + CONTENT/RP/SOLIDS/CHOICE2.XST | 1 + CONTENT/RP/SOLIDS/CL1_CV.SLD | 29 + CONTENT/RP/SOLIDS/CL2_CV.SLD | 50 + CONTENT/RP/SOLIDS/CL3_CV.SLD | 29 + CONTENT/RP/SOLIDS/CN1_CV.SLD | 155 + CONTENT/RP/SOLIDS/CN2_CV.SLD | 134 + CONTENT/RP/SOLIDS/CN3U_CV.SLD | 48 + CONTENT/RP/SOLIDS/CN3_CV.SLD | 50 + CONTENT/RP/SOLIDS/CN4_CV.SLD | 134 + CONTENT/RP/SOLIDS/CN5U_CV.ORG | 113 + CONTENT/RP/SOLIDS/CN5U_CV.SLD | 113 + CONTENT/RP/SOLIDS/CN5_CV.SLD | 155 + CONTENT/RP/SOLIDS/CN7U_CV.SLD | 71 + CONTENT/RP/SOLIDS/CN7_CV.SLD | 71 + CONTENT/RP/SOLIDS/CQ1_CV.SLD | 197 + CONTENT/RP/SOLIDS/CQ2_CV.SLD | 71 + CONTENT/RP/SOLIDS/CR2_CV.SLD | 386 + CONTENT/RP/SOLIDS/CR4_CV.SLD | 92 + CONTENT/RP/SOLIDS/CR5U_CV.SLD | 92 + CONTENT/RP/SOLIDS/CR5_CV.SLD | 92 + CONTENT/RP/SOLIDS/CR6_CV.SLD | 92 + CONTENT/RP/SOLIDS/CR8_CV.SLD | 92 + CONTENT/RP/SOLIDS/CRE_CV.SLD | 239 + CONTENT/RP/SOLIDS/CRP_CV.SLD | 302 + CONTENT/RP/SOLIDS/CT1_CV.SLD | 197 + CONTENT/RP/SOLIDS/D45.XST | 17 + CONTENT/RP/SOLIDS/D45_CV.SLD | 129 + CONTENT/RP/SOLIDS/DR1_CV.SLD | 134 + CONTENT/RP/SOLIDS/DR2_CV.SLD | 176 + CONTENT/RP/SOLIDS/DU_CV.SLD | 29 + CONTENT/RP/SOLIDS/EASY.XST | 1 + CONTENT/RP/SOLIDS/ED009100.$$$ | 0 CONTENT/RP/SOLIDS/ED009101.$$$ | 0 CONTENT/RP/SOLIDS/FRSTRM.XST | 143 + CONTENT/RP/SOLIDS/FT1_CV.SLD | 50 + CONTENT/RP/SOLIDS/FT2U_CV.SLD | 50 + CONTENT/RP/SOLIDS/FT2_CV.SLD | 50 + CONTENT/RP/SOLIDS/GAR1_CV.SLD | 48 + CONTENT/RP/SOLIDS/GAR2_CV.SLD | 48 + CONTENT/RP/SOLIDS/GAR_CV.SLD | 248 + CONTENT/RP/SOLIDS/HDOFF_CV.SLD | 88 + CONTENT/RP/SOLIDS/HEADMF.XST | 49 + CONTENT/RP/SOLIDS/HEADOFF.BAK | 41 + CONTENT/RP/SOLIDS/HEADOFF.XST | 49 + CONTENT/RP/SOLIDS/HV2_CV.SLD | 218 + CONTENT/RP/SOLIDS/HV4_CV.SLD | 218 + CONTENT/RP/SOLIDS/HV6_CV.SLD | 197 + CONTENT/RP/SOLIDS/HV7_CV.SLD | 197 + CONTENT/RP/SOLIDS/HVA_CV.SLD | 29 + CONTENT/RP/SOLIDS/HVB_CV.SLD | 29 + CONTENT/RP/SOLIDS/LU_CV.SLD | 29 + CONTENT/RP/SOLIDS/LYZLANE.XST | 404 + CONTENT/RP/SOLIDS/MA_CV.SLD | 29 + CONTENT/RP/SOLIDS/MB1_CV.SLD | 29 + CONTENT/RP/SOLIDS/MD1_CV.SLD | 175 + CONTENT/RP/SOLIDS/MD2_CV.SLD | 175 + CONTENT/RP/SOLIDS/MD3_CV.SLD | 92 + CONTENT/RP/SOLIDS/MD4_CV.SLD | 92 + CONTENT/RP/SOLIDS/ME1_CV.SLD | 217 + CONTENT/RP/SOLIDS/ME2_CV.SLD | 260 + CONTENT/RP/SOLIDS/ME4_CV.SLD | 134 + CONTENT/RP/SOLIDS/MED_CV.SLD | 29 + CONTENT/RP/SOLIDS/MU_CV.SLD | 29 + CONTENT/RP/SOLIDS/OA1_CV.SLD | 29 + CONTENT/RP/SOLIDS/OAO_CV.SLD | 155 + CONTENT/RP/SOLIDS/ODC_CV.SLD | 29 + CONTENT/RP/SOLIDS/OTTO.XST | 149 + CONTENT/RP/SOLIDS/PAIN.XST | 116 + CONTENT/RP/SOLIDS/PIT1_CV.SLD | 308 + CONTENT/RP/SOLIDS/PIT2_CV.SLD | 327 + CONTENT/RP/SOLIDS/PM1_CV.SLD | 113 + CONTENT/RP/SOLIDS/PO_CV.SLD | 29 + CONTENT/RP/SOLIDS/PP1_CV.SLD | 92 + CONTENT/RP/SOLIDS/PP2_CV.SLD | 29 + CONTENT/RP/SOLIDS/PUCKLAND.XST | 1 + CONTENT/RP/SOLIDS/PZ1_CV.SLD | 29 + CONTENT/RP/SOLIDS/PZ2_CV.SLD | 29 + CONTENT/RP/SOLIDS/PZ3_CV.SLD | 29 + CONTENT/RP/SOLIDS/PZ4_CV.SLD | 29 + CONTENT/RP/SOLIDS/RL1_CV.SLD | 50 + CONTENT/RP/SOLIDS/RL2_CV.SLD | 50 + CONTENT/RP/SOLIDS/RL3_CV.SLD | 50 + CONTENT/RP/SOLIDS/RP0_CV.SLD | 29 + CONTENT/RP/SOLIDS/RP1_CV.SLD | 50 + CONTENT/RP/SOLIDS/RP2_CV.SLD | 50 + CONTENT/RP/SOLIDS/RP3_CV.SLD | 50 + CONTENT/RP/SOLIDS/SA_CV.SLD | 29 + CONTENT/RP/SOLIDS/SC500_CV.SLD | 29 + CONTENT/RP/SOLIDS/SC50_CV.SLD | 29 + CONTENT/RP/SOLIDS/SHOOT.XST | 17 + CONTENT/RP/SOLIDS/SIG.XST | 17 + CONTENT/RP/SOLIDS/SU_CV.SLD | 29 + CONTENT/RP/SOLIDS/TEST.XST | 16 + CONTENT/RP/SOLIDS/TOUGH.XST | 1 + CONTENT/RP/SOLIDS/TRS_CV.SLD | 29 + CONTENT/RP/SOLIDS/TUN1_CV.SLD | 87 + CONTENT/RP/SOLIDS/VCS.CFG | 1 + CONTENT/RP/SOLIDS/WHC_CV.SLD | 176 + CONTENT/RP/SOLIDS/WISE.XST | 89 + CONTENT/RP/SOLIDS/WT2_CV.SLD | 197 + CONTENT/RP/SOLIDS/YIP.XST | 161 + CONTENT/RP/TOOLOPT.BAT | 2 + CONTENT/RP/VCS.CFG | 1 + CONTENT/RP/VIDEO/BMAP.BMF | Bin 0 -> 480 bytes CONTENT/RP/VIDEO/BN1L.BGF | Bin 0 -> 182 bytes CONTENT/RP/VIDEO/BOOST.PFX | 32 + CONTENT/RP/VIDEO/BP1.BGF | Bin 0 -> 1468 bytes CONTENT/RP/VIDEO/BR1L.BGF | Bin 0 -> 202 bytes CONTENT/RP/VIDEO/BR2L.BGF | Bin 0 -> 654 bytes CONTENT/RP/VIDEO/BR3.BGF | Bin 0 -> 867 bytes CONTENT/RP/VIDEO/BST.BGF | Bin 0 -> 1577 bytes CONTENT/RP/VIDEO/BUA.BGF | Bin 0 -> 1713 bytes CONTENT/RP/VIDEO/BUB.BGF | Bin 0 -> 1709 bytes CONTENT/RP/VIDEO/BUB.SKL | 228 + CONTENT/RP/VIDEO/BUC.BGF | Bin 0 -> 1709 bytes CONTENT/RP/VIDEO/C8EL.BGF | Bin 0 -> 451 bytes CONTENT/RP/VIDEO/CAMPOS.BGF | Bin 0 -> 1226 bytes CONTENT/RP/VIDEO/CENTER.BGF | Bin 0 -> 1010 bytes CONTENT/RP/VIDEO/CH1.BGF | Bin 0 -> 395 bytes CONTENT/RP/VIDEO/CH2.BGF | Bin 0 -> 327 bytes CONTENT/RP/VIDEO/CHG.BGF | Bin 0 -> 926 bytes CONTENT/RP/VIDEO/CHT.BGF | Bin 0 -> 2075 bytes CONTENT/RP/VIDEO/CL2.BGF | Bin 0 -> 1019 bytes CONTENT/RP/VIDEO/CL3.BGF | Bin 0 -> 1455 bytes CONTENT/RP/VIDEO/CLD.BGF | Bin 0 -> 1681 bytes CONTENT/RP/VIDEO/CN2L.BGF | Bin 0 -> 483 bytes CONTENT/RP/VIDEO/CN3.BGF | Bin 0 -> 1477 bytes CONTENT/RP/VIDEO/CN3U.BGF | Bin 0 -> 1477 bytes CONTENT/RP/VIDEO/CQ2.BGF | Bin 0 -> 1626 bytes CONTENT/RP/VIDEO/CR1L.BGF | Bin 0 -> 1221 bytes CONTENT/RP/VIDEO/CR2L.BGF | Bin 0 -> 789 bytes CONTENT/RP/VIDEO/CR3L.BGF | Bin 0 -> 933 bytes CONTENT/RP/VIDEO/CR4.BGF | Bin 0 -> 1109 bytes CONTENT/RP/VIDEO/CR5.BGF | Bin 0 -> 1006 bytes CONTENT/RP/VIDEO/CR6.BGF | Bin 0 -> 1131 bytes CONTENT/RP/VIDEO/CR8.BGF | Bin 0 -> 1109 bytes CONTENT/RP/VIDEO/CRC.BGF | Bin 0 -> 546 bytes CONTENT/RP/VIDEO/CREL.BGF | Bin 0 -> 383 bytes CONTENT/RP/VIDEO/CT1L.BGF | Bin 0 -> 368 bytes CONTENT/RP/VIDEO/CTF.BGF | Bin 0 -> 1361 bytes CONTENT/RP/VIDEO/DEMOBOOM.PFX | 32 + CONTENT/RP/VIDEO/DEMOBURN.PFX | 32 + CONTENT/RP/VIDEO/DEMOFUSE.PFX | 32 + CONTENT/RP/VIDEO/DR1L.BGF | Bin 0 -> 411 bytes CONTENT/RP/VIDEO/DR2.BG_ | 0 CONTENT/RP/VIDEO/DR2L.BGF | Bin 0 -> 475 bytes CONTENT/RP/VIDEO/DRWL.BGF | Bin 0 -> 266 bytes CONTENT/RP/VIDEO/DUA.BGF | Bin 0 -> 1881 bytes CONTENT/RP/VIDEO/DUB.BGF | Bin 0 -> 1933 bytes CONTENT/RP/VIDEO/DUC.BGF | Bin 0 -> 1933 bytes CONTENT/RP/VIDEO/DUMMY.BMF | Bin 0 -> 128 bytes CONTENT/RP/VIDEO/DUMMYENG.BGF | Bin 0 -> 155 bytes CONTENT/RP/VIDEO/FT1L.BGF | Bin 0 -> 155 bytes CONTENT/RP/VIDEO/GR1L.BGF | Bin 0 -> 498 bytes CONTENT/RP/VIDEO/GR2L.BGF | Bin 0 -> 398 bytes CONTENT/RP/VIDEO/HV1L.BGF | Bin 0 -> 278 bytes CONTENT/RP/VIDEO/HVA.BGF | Bin 0 -> 531 bytes CONTENT/RP/VIDEO/HVB.BGF | Bin 0 -> 531 bytes CONTENT/RP/VIDEO/HVEL.BGF | Bin 0 -> 278 bytes CONTENT/RP/VIDEO/LAA.BGF | Bin 0 -> 2370 bytes CONTENT/RP/VIDEO/LAA.SKL | 134 + CONTENT/RP/VIDEO/LAB.BGF | Bin 0 -> 2370 bytes CONTENT/RP/VIDEO/LAB.SKL | 134 + CONTENT/RP/VIDEO/LAC.BGF | Bin 0 -> 2370 bytes CONTENT/RP/VIDEO/LAC.SKL | 134 + CONTENT/RP/VIDEO/LAN.SKL | 136 + CONTENT/RP/VIDEO/LAS.SKL | 136 + CONTENT/RP/VIDEO/LASER.PFX | 28 + CONTENT/RP/VIDEO/LAT.SKL | 136 + CONTENT/RP/VIDEO/LAZDRIL.BGF | Bin 0 -> 1361 bytes CONTENT/RP/VIDEO/LSABER.BGF | Bin 0 -> 2298 bytes CONTENT/RP/VIDEO/LUA.BGF | Bin 0 -> 2370 bytes CONTENT/RP/VIDEO/LUA.SKL | 114 + CONTENT/RP/VIDEO/LUB.BGF | Bin 0 -> 2370 bytes CONTENT/RP/VIDEO/LUB.SKL | 114 + CONTENT/RP/VIDEO/LUC.BGF | Bin 0 -> 2370 bytes CONTENT/RP/VIDEO/LUC.SKL | 114 + CONTENT/RP/VIDEO/LUN.SKL | 116 + CONTENT/RP/VIDEO/LUS.SKL | 116 + CONTENT/RP/VIDEO/LUT.SKL | 116 + CONTENT/RP/VIDEO/MB1.BGF | Bin 0 -> 907 bytes CONTENT/RP/VIDEO/MINE.BGF | Bin 0 -> 376 bytes CONTENT/RP/VIDEO/MISSILE.BGF | Bin 0 -> 1813 bytes CONTENT/RP/VIDEO/MUA.BGF | Bin 0 -> 2353 bytes CONTENT/RP/VIDEO/MUA.SKL | 172 + CONTENT/RP/VIDEO/MUB.BGF | Bin 0 -> 2434 bytes CONTENT/RP/VIDEO/MUB.SKL | 172 + CONTENT/RP/VIDEO/MUC.BGF | Bin 0 -> 2354 bytes CONTENT/RP/VIDEO/MUC.SKL | 172 + CONTENT/RP/VIDEO/MUN.SKL | 174 + CONTENT/RP/VIDEO/MUS.SKL | 174 + CONTENT/RP/VIDEO/MUT.SKL | 174 + CONTENT/RP/VIDEO/OA3L.BGF | Bin 0 -> 575 bytes CONTENT/RP/VIDEO/OD1L.BGF | Bin 0 -> 611 bytes CONTENT/RP/VIDEO/OD3L.BGF | Bin 0 -> 627 bytes CONTENT/RP/VIDEO/OS1.BGF | Bin 0 -> 803 bytes CONTENT/RP/VIDEO/PL1L.BGF | Bin 0 -> 888 bytes CONTENT/RP/VIDEO/PLACE1.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PLACE2.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PLACE3.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PLACE4.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PLACE5.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PLACE6.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PLACE7.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PLACE8.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/PM1L.BGF | Bin 0 -> 182 bytes CONTENT/RP/VIDEO/PNAME1.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/PNAME2.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/PNAME3.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/PNAME4.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/PNAME5.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/PNAME6.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/PNAME7.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/PNAME8.BGF | Bin 0 -> 235 bytes CONTENT/RP/VIDEO/POA.SKL | 157 + CONTENT/RP/VIDEO/POB.SKL | 157 + CONTENT/RP/VIDEO/POC.SKL | 157 + CONTENT/RP/VIDEO/PON.SKL | 157 + CONTENT/RP/VIDEO/POS.SKL | 157 + CONTENT/RP/VIDEO/POT.SKL | 157 + CONTENT/RP/VIDEO/RF1L.BGF | Bin 0 -> 1484 bytes CONTENT/RP/VIDEO/RIVET.BGF | Bin 0 -> 250 bytes CONTENT/RP/VIDEO/RL1L.BGF | Bin 0 -> 270 bytes CONTENT/RP/VIDEO/RL2L.BGF | Bin 0 -> 302 bytes CONTENT/RP/VIDEO/RL3L.BGF | Bin 0 -> 302 bytes CONTENT/RP/VIDEO/RP0.BGF | Bin 0 -> 252 bytes CONTENT/RP/VIDEO/RP1L.BGF | Bin 0 -> 270 bytes CONTENT/RP/VIDEO/RP2L.BGF | Bin 0 -> 302 bytes CONTENT/RP/VIDEO/RP3L.BGF | Bin 0 -> 302 bytes CONTENT/RP/VIDEO/RPFX.BMF | Bin 0 -> 1749 bytes CONTENT/RP/VIDEO/SAA.BGF | Bin 0 -> 1879 bytes CONTENT/RP/VIDEO/SAA.SKL | 204 + CONTENT/RP/VIDEO/SAB.BGF | Bin 0 -> 1926 bytes CONTENT/RP/VIDEO/SAB.SKL | 204 + CONTENT/RP/VIDEO/SAC.BGF | Bin 0 -> 1926 bytes CONTENT/RP/VIDEO/SAC.SKL | 204 + CONTENT/RP/VIDEO/SAN.SKL | 206 + CONTENT/RP/VIDEO/SAS.SKL | 206 + CONTENT/RP/VIDEO/SAT.SKL | 206 + CONTENT/RP/VIDEO/SC500L.BGF | Bin 0 -> 447 bytes CONTENT/RP/VIDEO/SMOKE.PFX | 32 + CONTENT/RP/VIDEO/SNAALE.BGF | Bin 0 -> 239 bytes CONTENT/RP/VIDEO/SNACRANE.BGF | Bin 0 -> 240 bytes CONTENT/RP/VIDEO/SNADOS.BGF | Bin 0 -> 239 bytes CONTENT/RP/VIDEO/SNAENTER.BGF | Bin 0 -> 242 bytes CONTENT/RP/VIDEO/SNAEVAC.BGF | Bin 0 -> 239 bytes CONTENT/RP/VIDEO/SNAHAZ.BGF | Bin 0 -> 237 bytes CONTENT/RP/VIDEO/SNAHEADM.BGF | Bin 0 -> 240 bytes CONTENT/RP/VIDEO/SNALIMIT.BGF | Bin 0 -> 239 bytes CONTENT/RP/VIDEO/SNALOXM.BGF | Bin 0 -> 238 bytes CONTENT/RP/VIDEO/SNAMFAC.BGF | Bin 0 -> 242 bytes CONTENT/RP/VIDEO/SNANORC.BGF | Bin 0 -> 234 bytes CONTENT/RP/VIDEO/SNARADS.BGF | Bin 0 -> 234 bytes CONTENT/RP/VIDEO/SNASPDS.BGF | Bin 0 -> 234 bytes CONTENT/RP/VIDEO/SNATSPD.BGF | Bin 0 -> 234 bytes CONTENT/RP/VIDEO/SNAWELC.BGF | Bin 0 -> 234 bytes CONTENT/RP/VIDEO/SNAWORK.BGF | Bin 0 -> 239 bytes CONTENT/RP/VIDEO/SPARKS.PFX | 28 + CONTENT/RP/VIDEO/SUA.BGF | Bin 0 -> 2211 bytes CONTENT/RP/VIDEO/SUA.SKL | 114 + CONTENT/RP/VIDEO/SUB.BGF | Bin 0 -> 2211 bytes CONTENT/RP/VIDEO/SUB.SKL | 114 + CONTENT/RP/VIDEO/SUC.BGF | Bin 0 -> 2211 bytes CONTENT/RP/VIDEO/SUC.SKL | 114 + CONTENT/RP/VIDEO/SUN.SKL | 116 + CONTENT/RP/VIDEO/SUS.SKL | 116 + CONTENT/RP/VIDEO/SUT.SKL | 116 + CONTENT/RP/VIDEO/TEST.PFX | 32 + CONTENT/RP/VIDEO/TEST.TXT | 44 + CONTENT/RP/VIDEO/TSPHERE.BGF | Bin 0 -> 2085 bytes CONTENT/RP/VIDEO/VLA.BGF | Bin 0 -> 2383 bytes CONTENT/RP/VIDEO/VLC.BGF | Bin 0 -> 2419 bytes CONTENT/RP/VIDEO/VM1L.BGF | Bin 0 -> 547 bytes CONTENT/RP/VIDEO/VRA.BGF | Bin 0 -> 2383 bytes CONTENT/RP/VIDEO/VRC.BGF | Bin 0 -> 2419 bytes CONTENT/RP/VIDEO/VTVBURN.PFX | 32 + CONTENT/RP/VIDEO/WH1L.BGF | Bin 0 -> 1011 bytes CONTENT/RP/VIDEO/WH2L.BGF | Bin 0 -> 752 bytes CONTENT/RP/VIDEO/WH4L.BGF | Bin 0 -> 1011 bytes CONTENT/RP/VIDEO/WH5L.BGF | Bin 0 -> 1331 bytes CONTENT/RP/VIDEO/WH9L.BGF | Bin 0 -> 560 bytes CONTENT/RP/VIDEO/WINBOX.BGF | Bin 0 -> 771 bytes CONTENT/RP/VIDEO/WINSIGNS.BGF | Bin 0 -> 1019 bytes CONTENT/RP/VIDEO/WT1L.BGF | Bin 0 -> 1090 bytes CONTENT/RP/VIDEO/WT2L.BGF | Bin 0 -> 202 bytes CONTENT/RP/WATTCP.CFG | 4 + CONTENT/TAISATAP.SYS | Bin 0 -> 17961 bytes HEADOFF/HEADMF.BAK | 49 + HEADOFF/HEADMF.CAM | 254 + HEADOFF/HEADMF.XST | 49 + HEADOFF/HEADOFF.BAK | 49 + HEADOFF/HEADOFF.XST | 49 + README.md | 130 + 8682 files changed, 419927 insertions(+) create mode 100644 .gitattributes create mode 100644 ARTTOOLS/.gitkeep create mode 100644 BORLAND/.gitkeep create mode 100644 CODE/BT/32RTM.EXE create mode 100644 CODE/BT/32STUB.EXE create mode 100644 CODE/BT/ARCBT.BAT create mode 100644 CODE/BT/ARCFILES.LST create mode 100644 CODE/BT/BT/AMMOBIN.TCP create mode 100644 CODE/BT/BT/BT.HPP create mode 100644 CODE/BT/BT/BT.MAK create mode 100644 CODE/BT/BT/BTCNSL.CPP create mode 100644 CODE/BT/BT/BTDIRECT.HPP create mode 100644 CODE/BT/BT/BTMSSN.CPP create mode 100644 CODE/BT/BT/BTMSSN.HPP create mode 100644 CODE/BT/BT/BTREG.CPP create mode 100644 CODE/BT/BT/BTREG.HPP create mode 100644 CODE/BT/BT/BTSCNRL.CPP create mode 100644 CODE/BT/BT/BTTEAM.CPP create mode 100644 CODE/BT/BT/BTTEAM.HPP create mode 100644 CODE/BT/BT/BTTOOL.CPP create mode 100644 CODE/BT/BT/BTTOOL.HPP create mode 100644 CODE/BT/BT/EMITTER.TCP create mode 100644 CODE/BT/BT/GAUSS.CPP create mode 100644 CODE/BT/BT/GAUSS.HPP create mode 100644 CODE/BT/BT/GNRATOR.TCP create mode 100644 CODE/BT/BT/HEAT.TCP create mode 100644 CODE/BT/BT/MECHDMG.HPP create mode 100644 CODE/BT/BT/MECHTECH.HPP create mode 100644 CODE/BT/BT/MESSMGR.HPP create mode 100644 CODE/BT/BT/MISLANCH.HPP create mode 100644 CODE/BT/BT/MISSILE.TCP create mode 100644 CODE/BT/BT/MISTHRST.HPP create mode 100644 CODE/BT/BT/MSSCCPRJ.SCC create mode 100644 CODE/BT/BT/PPC.CPP create mode 100644 CODE/BT/BT/PPC.HPP create mode 100644 CODE/BT/BT/PROJTILE.TCP create mode 100644 CODE/BT/BT/PROJWEAP.TCP create mode 100644 CODE/BT/BT/SEEKER.HPP create mode 100644 CODE/BT/BT/SENSOR.HPP create mode 100644 CODE/BT/BT/TESTBT.HPP create mode 100644 CODE/BT/BT/TURRET.HPP create mode 100644 CODE/BT/BT/VSSVER.SCC create mode 100644 CODE/BT/BTL4.BLD create mode 100644 CODE/BT/BTL4.PTH create mode 100644 CODE/BT/BT_L4/BTL4.HPP create mode 100644 CODE/BT/BT_L4/BTL4.MAK create mode 100644 CODE/BT/BT_L4/BTL4APP.HPP create mode 100644 CODE/BT/BT_L4/BTL4ARND.CPP create mode 100644 CODE/BT/BT_L4/BTL4ARND.HPP create mode 100644 CODE/BT/BT_L4/BTL4GALM.HPP create mode 100644 CODE/BT/BT_L4/BTL4GRND.HPP create mode 100644 CODE/BT/BT_L4/BTL4MODE.CPP create mode 100644 CODE/BT/BT_L4/BTL4MODE.HPP create mode 100644 CODE/BT/BT_L4/BTL4MSSN.HPP create mode 100644 CODE/BT/BT_L4/BTL4PB.HPP create mode 100644 CODE/BT/BT_L4/BTL4RDR.HPP create mode 100644 CODE/BT/BT_L4/BTL4VER.HPP create mode 100644 CODE/BT/BT_L4/MSSCCPRJ.SCC create mode 100644 CODE/BT/BT_L4/VSSVER.SCC create mode 100644 CODE/BT/BUILDRES.BAT create mode 100644 CODE/BT/C0X32.OBJ create mode 100644 CODE/BT/D0.MAK create mode 100644 CODE/BT/D1.MAK create mode 100644 CODE/BT/D2S.MAK create mode 100644 CODE/BT/D3S.MAK create mode 100644 CODE/BT/DEARCBT.BAT create mode 100644 CODE/BT/DPMI32VM.OVL create mode 100644 CODE/BT/EXAMPLE.BAT create mode 100644 CODE/BT/EXAMPLE.CFG create mode 100644 CODE/BT/EXCLUDE.LST create mode 100644 CODE/BT/HMIDET.386 create mode 100644 CODE/BT/HMIDRV.386 create mode 100644 CODE/BT/MSSCCPRJ.SCC create mode 100644 CODE/BT/MUNGA/AFFNMTRX.TCP create mode 100644 CODE/BT/MUNGA/ANGLE.TCP create mode 100644 CODE/BT/MUNGA/APP.THP create mode 100644 CODE/BT/MUNGA/APPMGR.HPP create mode 100644 CODE/BT/MUNGA/AUDTIME.CPP create mode 100644 CODE/BT/MUNGA/AUDTOOLS.HPP create mode 100644 CODE/BT/MUNGA/AUDWGT.CPP create mode 100644 CODE/BT/MUNGA/AVERAGE.CPP create mode 100644 CODE/BT/MUNGA/BOXLIST.HPP create mode 100644 CODE/BT/MUNGA/CMPNNT.HPP create mode 100644 CODE/BT/MUNGA/COLOR.CPP create mode 100644 CODE/BT/MUNGA/COLOR.HPP create mode 100644 CODE/BT/MUNGA/CSTR.TCP create mode 100644 CODE/BT/MUNGA/DEBUGOFF.HPP create mode 100644 CODE/BT/MUNGA/DEBUGOLD.HPP create mode 100644 CODE/BT/MUNGA/EVTSTAT.CPP create mode 100644 CODE/BT/MUNGA/EVTSTAT.HPP create mode 100644 CODE/BT/MUNGA/FILESTRM.CPP create mode 100644 CODE/BT/MUNGA/FILESTRM.HPP create mode 100644 CODE/BT/MUNGA/FILESTRM.TCP create mode 100644 CODE/BT/MUNGA/FILESTUB.CPP create mode 100644 CODE/BT/MUNGA/HEAP.HPP create mode 100644 CODE/BT/MUNGA/HOST.TCP create mode 100644 CODE/BT/MUNGA/HOSTID.HPP create mode 100644 CODE/BT/MUNGA/LINE.CPP create mode 100644 CODE/BT/MUNGA/LINE.HPP create mode 100644 CODE/BT/MUNGA/LINK.CPP create mode 100644 CODE/BT/MUNGA/LINMTRX.TCP create mode 100644 CODE/BT/MUNGA/MATRIX.TCP create mode 100644 CODE/BT/MUNGA/MEMBLOCK.TCP create mode 100644 CODE/BT/MUNGA/MODE.CPP create mode 100644 CODE/BT/MUNGA/MOTION.HPP create mode 100644 CODE/BT/MUNGA/MSSCCPRJ.SCC create mode 100644 CODE/BT/MUNGA/MTRXSTK.CPP create mode 100644 CODE/BT/MUNGA/MUNGA.HPP create mode 100644 CODE/BT/MUNGA/NODE.CPP create mode 100644 CODE/BT/MUNGA/NORMAL.CPP create mode 100644 CODE/BT/MUNGA/NORMAL.TCP create mode 100644 CODE/BT/MUNGA/ORIGIN.TCP create mode 100644 CODE/BT/MUNGA/POINT2D.HPP create mode 100644 CODE/BT/MUNGA/RANDOM.HPP create mode 100644 CODE/BT/MUNGA/RANDOM.TCP create mode 100644 CODE/BT/MUNGA/RAY.HPP create mode 100644 CODE/BT/MUNGA/RAY.TCP create mode 100644 CODE/BT/MUNGA/RECT2D.HPP create mode 100644 CODE/BT/MUNGA/RENDERER.TCP create mode 100644 CODE/BT/MUNGA/RENDERER.THP create mode 100644 CODE/BT/MUNGA/RESVER.HPP create mode 100644 CODE/BT/MUNGA/SCALAR.CPP create mode 100644 CODE/BT/MUNGA/SCALAR.HPP create mode 100644 CODE/BT/MUNGA/SCNROLE.HPP create mode 100644 CODE/BT/MUNGA/SET.CPP create mode 100644 CODE/BT/MUNGA/SFESKT.HPP create mode 100644 CODE/BT/MUNGA/SPHERE.CPP create mode 100644 CODE/BT/MUNGA/SPHERE.HPP create mode 100644 CODE/BT/MUNGA/SPLINE.HPP create mode 100644 CODE/BT/MUNGA/SPOOLER.HPP create mode 100644 CODE/BT/MUNGA/SRTSKT.CPP create mode 100644 CODE/BT/MUNGA/SRTSKT.HPP create mode 100644 CODE/BT/MUNGA/TEAM.HPP create mode 100644 CODE/BT/MUNGA/TESTCLAS.HPP create mode 100644 CODE/BT/MUNGA/TIME.TCP create mode 100644 CODE/BT/MUNGA/TIMESTUB.CPP create mode 100644 CODE/BT/MUNGA/TRACSTUB.CPP create mode 100644 CODE/BT/MUNGA/UNITVEC.CPP create mode 100644 CODE/BT/MUNGA/UNITVEC.TCP create mode 100644 CODE/BT/MUNGA/VECTOR4D.HPP create mode 100644 CODE/BT/MUNGA/VERIFY.HPP create mode 100644 CODE/BT/MUNGA/VIDREND.TCP create mode 100644 CODE/BT/MUNGA_L4/L4APP.THP create mode 100644 CODE/BT/MUNGA_L4/L4AUDTUL.CPP create mode 100644 CODE/BT/MUNGA_L4/L4CTLTUL.CPP create mode 100644 CODE/BT/MUNGA_L4/L4DPLMEM.CPP create mode 100644 CODE/BT/MUNGA_L4/L4GAUIMM.HPP create mode 100644 CODE/BT/MUNGA_L4/L4HOST.CPP create mode 100644 CODE/BT/MUNGA_L4/L4KEYBD.CPP create mode 100644 CODE/BT/MUNGA_L4/L4MOUSE.HPP create mode 100644 CODE/BT/MUNGA_L4/L4MSSN.HPP create mode 100644 CODE/BT/MUNGA_L4/L4PLASMA.HPP create mode 100644 CODE/BT/MUNGA_L4/L4TIME.HPP create mode 100644 CODE/BT/MUNGA_L4/L4VIDEO.TCP create mode 100644 CODE/BT/MUNGA_L4/L4VIDTUL.CPP create mode 100644 CODE/BT/MUNGA_L4/L4WRHOUS.CPP create mode 100644 CODE/BT/MUNGA_L4/L4WRHOUS.HPP create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/MATRIX.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL2DTAG.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL_MEM.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/MATRIX.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/TRICODER.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VR_PROT.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DPL/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.DEF create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVVERS.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/DP.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/DS.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/GETPARAM.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/MAPFILE.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/PFPARSER.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DSYS/__PTOOL.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DVS/DM.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DVS/VCBODAPP.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DVS/VCERROR.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DVS/VCINPDEF.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DVS/VCMACROS.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DVS/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/DVS/_VCTYPES.H create mode 100644 CODE/BT/MUNGA_L4/LIBDPL/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/MSSCCPRJ.SCC create mode 100644 CODE/BT/MUNGA_L4/MUNGAL4.HPP create mode 100644 CODE/BT/MUNGA_L4/NETNUB/ANALYSIS.HPP create mode 100644 CODE/BT/MUNGA_L4/NETNUB/INCLUDE/BOOTP.H create mode 100644 CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ELIB.H create mode 100644 CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ETHDEV.H create mode 100644 CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ICMP.H create mode 100644 CODE/BT/MUNGA_L4/NETNUB/INCLUDE/STATE.RST create mode 100644 CODE/BT/MUNGA_L4/NETNUB/INCLUDE/TCP.H create mode 100644 CODE/BT/MUNGA_L4/NETNUB/INCLUDE/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/NETNUB/LIB/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/NETNUB/MAKEFILE.MAK create mode 100644 CODE/BT/MUNGA_L4/NETNUB/MSSCCPRJ.SCC create mode 100644 CODE/BT/MUNGA_L4/NETNUB/NOPAUSE.CPP create mode 100644 CODE/BT/MUNGA_L4/NETNUB/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/PCPIC.INC create mode 100644 CODE/BT/MUNGA_L4/SOS/BC4/SOSDEFS.H create mode 100644 CODE/BT/MUNGA_L4/SOS/BC4/SOSMAWE.H create mode 100644 CODE/BT/MUNGA_L4/SOS/BC4/SOSRES.H create mode 100644 CODE/BT/MUNGA_L4/SOS/BC4/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/SOS/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/SOS/WC/SOSDEFS.H create mode 100644 CODE/BT/MUNGA_L4/SOS/WC/SOSRES.H create mode 100644 CODE/BT/MUNGA_L4/SOS/WC/VSSVER.SCC create mode 100644 CODE/BT/MUNGA_L4/SOSMAWE.H create mode 100644 CODE/BT/MUNGA_L4/SPEAKER.HPP create mode 100644 CODE/BT/MUNGA_L4/VSSVER.SCC create mode 100644 CODE/BT/NEWSTUFF.BLD create mode 100644 CODE/BT/OPT.MAK create mode 100644 CODE/BT/SETENV.BAT create mode 100644 CODE/BT/VSSVER.SCC create mode 100644 CODE/RP/32STUB.EXE create mode 100644 CODE/RP/C0X32.OBJ create mode 100644 CODE/RP/CW32.LIB create mode 100644 CODE/RP/D0.mak create mode 100644 CODE/RP/DPMI32.LIB create mode 100644 CODE/RP/MUNGA/AFFNMTRX.CPP create mode 100644 CODE/RP/MUNGA/AFFNMTRX.HPP create mode 100644 CODE/RP/MUNGA/AFFNMTRX.TCP create mode 100644 CODE/RP/MUNGA/ANGLE.CPP create mode 100644 CODE/RP/MUNGA/ANGLE.HPP create mode 100644 CODE/RP/MUNGA/ANGLE.TCP create mode 100644 CODE/RP/MUNGA/APP.TCP create mode 100644 CODE/RP/MUNGA/APP.THP create mode 100644 CODE/RP/MUNGA/APPMGR.CPP create mode 100644 CODE/RP/MUNGA/APPMGR.HPP create mode 100644 CODE/RP/MUNGA/APPMSG.CPP create mode 100644 CODE/RP/MUNGA/APPMSG.HPP create mode 100644 CODE/RP/MUNGA/APPTASK.CPP create mode 100644 CODE/RP/MUNGA/APPTASK.HPP create mode 100644 CODE/RP/MUNGA/AUDCMP.HPP create mode 100644 CODE/RP/MUNGA/AUDENT.CPP create mode 100644 CODE/RP/MUNGA/AUDENT.HPP create mode 100644 CODE/RP/MUNGA/AUDIO.CPP create mode 100644 CODE/RP/MUNGA/AUDIO.HPP create mode 100644 CODE/RP/MUNGA/AUDLOC.CPP create mode 100644 CODE/RP/MUNGA/AUDLOC.HPP create mode 100644 CODE/RP/MUNGA/AUDLVL.CPP create mode 100644 CODE/RP/MUNGA/AUDLVL.HPP create mode 100644 CODE/RP/MUNGA/AUDMIDI.CPP create mode 100644 CODE/RP/MUNGA/AUDMIDI.HPP create mode 100644 CODE/RP/MUNGA/AUDSEQ.CPP create mode 100644 CODE/RP/MUNGA/AUDSEQ.HPP create mode 100644 CODE/RP/MUNGA/AUDSRC.CPP create mode 100644 CODE/RP/MUNGA/AUDSRC.HPP create mode 100644 CODE/RP/MUNGA/AUDTIME.CPP create mode 100644 CODE/RP/MUNGA/AUDTIME.HPP create mode 100644 CODE/RP/MUNGA/AUDTOOLS.CPP create mode 100644 CODE/RP/MUNGA/AUDTOOLS.HPP create mode 100644 CODE/RP/MUNGA/AUDWGT.CPP create mode 100644 CODE/RP/MUNGA/AUDWGT.HPP create mode 100644 CODE/RP/MUNGA/AUDWTHR.CPP create mode 100644 CODE/RP/MUNGA/AUDWTHR.HPP create mode 100644 CODE/RP/MUNGA/AVERAGE.CPP create mode 100644 CODE/RP/MUNGA/AVERAGE.HPP create mode 100644 CODE/RP/MUNGA/BNDGBOX.CPP create mode 100644 CODE/RP/MUNGA/BNDGBOX.HPP create mode 100644 CODE/RP/MUNGA/BOXCONE.CPP create mode 100644 CODE/RP/MUNGA/BOXDISKS.CPP create mode 100644 CODE/RP/MUNGA/BOXIRAMP.CPP create mode 100644 CODE/RP/MUNGA/BOXLIST.CPP create mode 100644 CODE/RP/MUNGA/BOXLIST.HPP create mode 100644 CODE/RP/MUNGA/BOXRAMP.CPP create mode 100644 CODE/RP/MUNGA/BOXSOLID.CPP create mode 100644 CODE/RP/MUNGA/BOXSOLID.HPP create mode 100644 CODE/RP/MUNGA/BOXSOLID.TCP create mode 100644 CODE/RP/MUNGA/BOXSORT.CPP create mode 100644 CODE/RP/MUNGA/BOXSPHR.CPP create mode 100644 CODE/RP/MUNGA/BOXTILE.CPP create mode 100644 CODE/RP/MUNGA/BOXTREE.CPP create mode 100644 CODE/RP/MUNGA/BOXWEDGE.CPP create mode 100644 CODE/RP/MUNGA/CAMINST.CPP create mode 100644 CODE/RP/MUNGA/CAMINST.HPP create mode 100644 CODE/RP/MUNGA/CAMMGR.CPP create mode 100644 CODE/RP/MUNGA/CAMMGR.HPP create mode 100644 CODE/RP/MUNGA/CAMMPPR.CPP create mode 100644 CODE/RP/MUNGA/CAMMPPR.HPP create mode 100644 CODE/RP/MUNGA/CAMSHIP.CPP create mode 100644 CODE/RP/MUNGA/CAMSHIP.HPP create mode 100644 CODE/RP/MUNGA/CHAIN.CPP create mode 100644 CODE/RP/MUNGA/CHAIN.HPP create mode 100644 CODE/RP/MUNGA/CMPNNT.CPP create mode 100644 CODE/RP/MUNGA/CMPNNT.HPP create mode 100644 CODE/RP/MUNGA/COLLASST.CPP create mode 100644 CODE/RP/MUNGA/COLLASST.HPP create mode 100644 CODE/RP/MUNGA/COLLORGN.CPP create mode 100644 CODE/RP/MUNGA/COLLORGN.HPP create mode 100644 CODE/RP/MUNGA/COLOR.CPP create mode 100644 CODE/RP/MUNGA/COLOR.HPP create mode 100644 CODE/RP/MUNGA/CONFIG.HPP create mode 100644 CODE/RP/MUNGA/CONSOLE.CPP create mode 100644 CODE/RP/MUNGA/CONSOLE.HPP create mode 100644 CODE/RP/MUNGA/CONTROLS.CPP create mode 100644 CODE/RP/MUNGA/CONTROLS.HPP create mode 100644 CODE/RP/MUNGA/CONTROLS.TCP create mode 100644 CODE/RP/MUNGA/CONTROLS.THP create mode 100644 CODE/RP/MUNGA/CSTR.HPP create mode 100644 CODE/RP/MUNGA/CSTR.TCP create mode 100644 CODE/RP/MUNGA/CULTURAL.HPP create mode 100644 CODE/RP/MUNGA/DAMAGE.CPP create mode 100644 CODE/RP/MUNGA/DAMAGE.HPP create mode 100644 CODE/RP/MUNGA/DEBUG1ON.HPP create mode 100644 CODE/RP/MUNGA/DEBUG2ON.HPP create mode 100644 CODE/RP/MUNGA/DEBUGOFF.HPP create mode 100644 CODE/RP/MUNGA/DEBUGOLD.HPP create mode 100644 CODE/RP/MUNGA/DIRECTOR.CPP create mode 100644 CODE/RP/MUNGA/DIRECTOR.HPP create mode 100644 CODE/RP/MUNGA/DOOR.CPP create mode 100644 CODE/RP/MUNGA/DOOR.HPP create mode 100644 CODE/RP/MUNGA/DOORFRAM.CPP create mode 100644 CODE/RP/MUNGA/DOORFRAM.HPP create mode 100644 CODE/RP/MUNGA/DROPZONE.HPP create mode 100644 CODE/RP/MUNGA/ENTITY.CPP create mode 100644 CODE/RP/MUNGA/ENTITY.HPP create mode 100644 CODE/RP/MUNGA/ENTITY.TCP create mode 100644 CODE/RP/MUNGA/ENTITY.THP create mode 100644 CODE/RP/MUNGA/ENTITY2.CPP create mode 100644 CODE/RP/MUNGA/ENTITY2.HPP create mode 100644 CODE/RP/MUNGA/ENTITY3.HPP create mode 100644 CODE/RP/MUNGA/ENTITYID.CPP create mode 100644 CODE/RP/MUNGA/ENTITYID.HPP create mode 100644 CODE/RP/MUNGA/ENVIRNMT.CPP create mode 100644 CODE/RP/MUNGA/ENVIRNMT.HPP create mode 100644 CODE/RP/MUNGA/EVENT.CPP create mode 100644 CODE/RP/MUNGA/EVENT.HPP create mode 100644 CODE/RP/MUNGA/EVENT.TCP create mode 100644 CODE/RP/MUNGA/EVTSTAT.CPP create mode 100644 CODE/RP/MUNGA/EVTSTAT.HPP create mode 100644 CODE/RP/MUNGA/EXPLODE.HPP create mode 100644 CODE/RP/MUNGA/EXPTBL.HPP create mode 100644 CODE/RP/MUNGA/EXTNTBOX.CPP create mode 100644 CODE/RP/MUNGA/EXTNTBOX.HPP create mode 100644 CODE/RP/MUNGA/EYECANDY.CPP create mode 100644 CODE/RP/MUNGA/EYECANDY.HPP create mode 100644 CODE/RP/MUNGA/FILESTRM.CPP create mode 100644 CODE/RP/MUNGA/FILESTRM.HPP create mode 100644 CODE/RP/MUNGA/FILESTUB.CPP create mode 100644 CODE/RP/MUNGA/FILEUTIL.HPP create mode 100644 CODE/RP/MUNGA/GAUGALRM.CPP create mode 100644 CODE/RP/MUNGA/GAUGALRM.HPP create mode 100644 CODE/RP/MUNGA/GAUGE.TCP create mode 100644 CODE/RP/MUNGA/GAUGMAP.HPP create mode 100644 CODE/RP/MUNGA/GRAPH2D.HPP create mode 100644 CODE/RP/MUNGA/HASH.CPP create mode 100644 CODE/RP/MUNGA/HASH.HPP create mode 100644 CODE/RP/MUNGA/HASH.TCP create mode 100644 CODE/RP/MUNGA/HEAP.HPP create mode 100644 CODE/RP/MUNGA/HOST.CPP create mode 100644 CODE/RP/MUNGA/HOST.HPP create mode 100644 CODE/RP/MUNGA/HOST.TCP create mode 100644 CODE/RP/MUNGA/HOSTID.HPP create mode 100644 CODE/RP/MUNGA/HOSTMGR.CPP create mode 100644 CODE/RP/MUNGA/HOSTMGR.HPP create mode 100644 CODE/RP/MUNGA/ICOM.CPP create mode 100644 CODE/RP/MUNGA/ICOM.HPP create mode 100644 CODE/RP/MUNGA/INTEREST.CPP create mode 100644 CODE/RP/MUNGA/INTEREST.HPP create mode 100644 CODE/RP/MUNGA/INTORGN.CPP create mode 100644 CODE/RP/MUNGA/INTORGN.HPP create mode 100644 CODE/RP/MUNGA/ITERATOR.CPP create mode 100644 CODE/RP/MUNGA/ITERATOR.HPP create mode 100644 CODE/RP/MUNGA/JMOVER.CPP create mode 100644 CODE/RP/MUNGA/JMOVER.HPP create mode 100644 CODE/RP/MUNGA/JOINT.CPP create mode 100644 CODE/RP/MUNGA/JOINT.HPP create mode 100644 CODE/RP/MUNGA/LAMP.CPP create mode 100644 CODE/RP/MUNGA/LATTICE.CPP create mode 100644 CODE/RP/MUNGA/LATTICE.HPP create mode 100644 CODE/RP/MUNGA/LINE.CPP create mode 100644 CODE/RP/MUNGA/LINE.HPP create mode 100644 CODE/RP/MUNGA/LINK.CPP create mode 100644 CODE/RP/MUNGA/LINK.HPP create mode 100644 CODE/RP/MUNGA/LINMTRX.CPP create mode 100644 CODE/RP/MUNGA/LINMTRX.HPP create mode 100644 CODE/RP/MUNGA/LINMTRX.TCP create mode 100644 CODE/RP/MUNGA/MATRIX.CPP create mode 100644 CODE/RP/MUNGA/MATRIX.HPP create mode 100644 CODE/RP/MUNGA/MATRIX.TCP create mode 100644 CODE/RP/MUNGA/MEMBLOCK.CPP create mode 100644 CODE/RP/MUNGA/MEMBLOCK.HPP create mode 100644 CODE/RP/MUNGA/MEMBLOCK.TCP create mode 100644 CODE/RP/MUNGA/MEMREG.HPP create mode 100644 CODE/RP/MUNGA/MEMSTRM.CPP create mode 100644 CODE/RP/MUNGA/MEMSTRM.HPP create mode 100644 CODE/RP/MUNGA/MISSION.CPP create mode 100644 CODE/RP/MUNGA/MISSION.HPP create mode 100644 CODE/RP/MUNGA/MODE.CPP create mode 100644 CODE/RP/MUNGA/MODE.HPP create mode 100644 CODE/RP/MUNGA/MOTION.CPP create mode 100644 CODE/RP/MUNGA/MOTION.HPP create mode 100644 CODE/RP/MUNGA/MOVER.CPP create mode 100644 CODE/RP/MUNGA/MOVER.HPP create mode 100644 CODE/RP/MUNGA/MTRXSTK.CPP create mode 100644 CODE/RP/MUNGA/MTRXSTK.HPP create mode 100644 CODE/RP/MUNGA/MUNGA.HPP create mode 100644 CODE/RP/MUNGA/MUNGA.MAK create mode 100644 CODE/RP/MUNGA/NAMELIST.CPP create mode 100644 CODE/RP/MUNGA/NAMELIST.HPP create mode 100644 CODE/RP/MUNGA/NAMELIST.TCP create mode 100644 CODE/RP/MUNGA/NETWORK.HPP create mode 100644 CODE/RP/MUNGA/NODE.CPP create mode 100644 CODE/RP/MUNGA/NODE.HPP create mode 100644 CODE/RP/MUNGA/NORMAL.CPP create mode 100644 CODE/RP/MUNGA/NORMAL.HPP create mode 100644 CODE/RP/MUNGA/NORMAL.TCP create mode 100644 CODE/RP/MUNGA/NOTATION.CPP create mode 100644 CODE/RP/MUNGA/NOTATION.HPP create mode 100644 CODE/RP/MUNGA/NOTATION.TCP create mode 100644 CODE/RP/MUNGA/NTTMGR.CPP create mode 100644 CODE/RP/MUNGA/NTTMGR.HPP create mode 100644 CODE/RP/MUNGA/OBJSTRM.HPP create mode 100644 CODE/RP/MUNGA/ORIGIN.CPP create mode 100644 CODE/RP/MUNGA/ORIGIN.HPP create mode 100644 CODE/RP/MUNGA/ORIGIN.TCP create mode 100644 CODE/RP/MUNGA/PLANE.CPP create mode 100644 CODE/RP/MUNGA/PLANE.HPP create mode 100644 CODE/RP/MUNGA/PLAYER.HPP create mode 100644 CODE/RP/MUNGA/PLUG.CPP create mode 100644 CODE/RP/MUNGA/PLUG.HPP create mode 100644 CODE/RP/MUNGA/POINT2D.HPP create mode 100644 CODE/RP/MUNGA/POINT3D.CPP create mode 100644 CODE/RP/MUNGA/POINT3D.HPP create mode 100644 CODE/RP/MUNGA/POINT3D.TCP create mode 100644 CODE/RP/MUNGA/RANDOM.HPP create mode 100644 CODE/RP/MUNGA/RANDOM.TCP create mode 100644 CODE/RP/MUNGA/RAY.HPP create mode 100644 CODE/RP/MUNGA/RAY.TCP create mode 100644 CODE/RP/MUNGA/RECEIVER.HPP create mode 100644 CODE/RP/MUNGA/RECEIVER.TCP create mode 100644 CODE/RP/MUNGA/RECEIVER.THP create mode 100644 CODE/RP/MUNGA/RECT2D.CPP create mode 100644 CODE/RP/MUNGA/RECT2D.HPP create mode 100644 CODE/RP/MUNGA/RECT2D.TCP create mode 100644 CODE/RP/MUNGA/REGISTRY.CPP create mode 100644 CODE/RP/MUNGA/REGISTRY.HPP create mode 100644 CODE/RP/MUNGA/RENDERER.CPP create mode 100644 CODE/RP/MUNGA/RENDERER.HPP create mode 100644 CODE/RP/MUNGA/RENDERER.TCP create mode 100644 CODE/RP/MUNGA/RENDERER.THP create mode 100644 CODE/RP/MUNGA/RESOURCE.HPP create mode 100644 CODE/RP/MUNGA/RESOURCE.TCP create mode 100644 CODE/RP/MUNGA/RESVER.HPP create mode 100644 CODE/RP/MUNGA/RETICLE.CPP create mode 100644 CODE/RP/MUNGA/RETICLE.HPP create mode 100644 CODE/RP/MUNGA/RNDORGN.CPP create mode 100644 CODE/RP/MUNGA/RNDORGN.HPP create mode 100644 CODE/RP/MUNGA/ROTATION.TCP create mode 100644 CODE/RP/MUNGA/SCALAR.CPP create mode 100644 CODE/RP/MUNGA/SCALAR.HPP create mode 100644 CODE/RP/MUNGA/SCHAIN.CPP create mode 100644 CODE/RP/MUNGA/SCHAIN.HPP create mode 100644 CODE/RP/MUNGA/SCHAIN.TCP create mode 100644 CODE/RP/MUNGA/SCNROLE.HPP create mode 100644 CODE/RP/MUNGA/SEGMENT.CPP create mode 100644 CODE/RP/MUNGA/SEGMENT.HPP create mode 100644 CODE/RP/MUNGA/SET.CPP create mode 100644 CODE/RP/MUNGA/SFESKT.CPP create mode 100644 CODE/RP/MUNGA/SFESKT.HPP create mode 100644 CODE/RP/MUNGA/SIMULATE.CPP create mode 100644 CODE/RP/MUNGA/SIMULATE.HPP create mode 100644 CODE/RP/MUNGA/SIMULATE.TCP create mode 100644 CODE/RP/MUNGA/SLOT.CPP create mode 100644 CODE/RP/MUNGA/SLOT.HPP create mode 100644 CODE/RP/MUNGA/SOCKET.CPP create mode 100644 CODE/RP/MUNGA/SOCKET.HPP create mode 100644 CODE/RP/MUNGA/SPHERE.CPP create mode 100644 CODE/RP/MUNGA/SPHERE.HPP create mode 100644 CODE/RP/MUNGA/SPLINE.CPP create mode 100644 CODE/RP/MUNGA/SPLINE.HPP create mode 100644 CODE/RP/MUNGA/SPOOLER.CPP create mode 100644 CODE/RP/MUNGA/SPOOLER.HPP create mode 100644 CODE/RP/MUNGA/SRTSKT.CPP create mode 100644 CODE/RP/MUNGA/SRTSKT.HPP create mode 100644 CODE/RP/MUNGA/STATE.HPP create mode 100644 CODE/RP/MUNGA/STYLE.HPP create mode 100644 CODE/RP/MUNGA/SUBSYSTM.HPP create mode 100644 CODE/RP/MUNGA/TABLE.CPP create mode 100644 CODE/RP/MUNGA/TABLE.HPP create mode 100644 CODE/RP/MUNGA/TABLE.TCP create mode 100644 CODE/RP/MUNGA/TEAM.HPP create mode 100644 CODE/RP/MUNGA/TERRAIN.HPP create mode 100644 CODE/RP/MUNGA/TESTALL.CPP create mode 100644 CODE/RP/MUNGA/TESTCLAS.HPP create mode 100644 CODE/RP/MUNGA/TIME.CPP create mode 100644 CODE/RP/MUNGA/TIME.HPP create mode 100644 CODE/RP/MUNGA/TIME.TCP create mode 100644 CODE/RP/MUNGA/TIMESTUB.CPP create mode 100644 CODE/RP/MUNGA/TOOL.CPP create mode 100644 CODE/RP/MUNGA/TOOL.HPP create mode 100644 CODE/RP/MUNGA/TRACE.CPP create mode 100644 CODE/RP/MUNGA/TRACE.HPP create mode 100644 CODE/RP/MUNGA/TRACSTUB.CPP create mode 100644 CODE/RP/MUNGA/TREE.CPP create mode 100644 CODE/RP/MUNGA/TREE.HPP create mode 100644 CODE/RP/MUNGA/TREE.TCP create mode 100644 CODE/RP/MUNGA/UNITVEC.CPP create mode 100644 CODE/RP/MUNGA/UNITVEC.HPP create mode 100644 CODE/RP/MUNGA/UNITVEC.TCP create mode 100644 CODE/RP/MUNGA/UPDATE.CPP create mode 100644 CODE/RP/MUNGA/UPDATE.HPP create mode 100644 CODE/RP/MUNGA/VCHAIN.CPP create mode 100644 CODE/RP/MUNGA/VCHAIN.HPP create mode 100644 CODE/RP/MUNGA/VCHAIN.TCP create mode 100644 CODE/RP/MUNGA/VDATA.CPP create mode 100644 CODE/RP/MUNGA/VECTOR3D.CPP create mode 100644 CODE/RP/MUNGA/VECTOR3D.HPP create mode 100644 CODE/RP/MUNGA/VECTOR3D.TCP create mode 100644 CODE/RP/MUNGA/VECTOR4D.CPP create mode 100644 CODE/RP/MUNGA/VECTOR4D.HPP create mode 100644 CODE/RP/MUNGA/VECTOR4D.TCP create mode 100644 CODE/RP/MUNGA/VERIFY.HPP create mode 100644 CODE/RP/MUNGA/VIDREND.CPP create mode 100644 CODE/RP/MUNGA/VIDREND.HPP create mode 100644 CODE/RP/MUNGA/VIDREND.TCP create mode 100644 CODE/RP/MUNGA/WATCHER.CPP create mode 100644 CODE/RP/MUNGA/WATCHER.HPP create mode 100644 CODE/RP/MUNGA/WATCHER.TCP create mode 100644 CODE/RP/MUNGA/WRHOUS.CPP create mode 100644 CODE/RP/MUNGA/WRHOUS.HPP create mode 100644 CODE/RP/MUNGA/mssccprj.scc create mode 100644 CODE/RP/MUNGA/opt/ANGLE.obj create mode 100644 CODE/RP/MUNGA/opt/APPMSG.obj create mode 100644 CODE/RP/MUNGA/opt/AUDWGT.obj create mode 100644 CODE/RP/MUNGA/opt/BOXLIST.obj create mode 100644 CODE/RP/MUNGA/opt/BOXSORT.obj create mode 100644 CODE/RP/MUNGA/opt/BOXSPHR.obj create mode 100644 CODE/RP/MUNGA/opt/CMPNNT.obj create mode 100644 CODE/RP/MUNGA/opt/COLOR.obj create mode 100644 CODE/RP/MUNGA/opt/CONSOLE.obj create mode 100644 CODE/RP/MUNGA/opt/ENTITYID.obj create mode 100644 CODE/RP/MUNGA/opt/ENVIRNMT.obj create mode 100644 CODE/RP/MUNGA/opt/FILESTRM.obj create mode 100644 CODE/RP/MUNGA/opt/FILESTUB.obj create mode 100644 CODE/RP/MUNGA/opt/INTORGN.obj create mode 100644 CODE/RP/MUNGA/opt/ITERATOR.obj create mode 100644 CODE/RP/MUNGA/opt/LINE.obj create mode 100644 CODE/RP/MUNGA/opt/LINK.obj create mode 100644 CODE/RP/MUNGA/opt/LINMTRX.obj create mode 100644 CODE/RP/MUNGA/opt/MEMBLOCK.obj create mode 100644 CODE/RP/MUNGA/opt/MEMSTRM.obj create mode 100644 CODE/RP/MUNGA/opt/MODE.obj create mode 100644 CODE/RP/MUNGA/opt/MOTION.obj create mode 100644 CODE/RP/MUNGA/opt/MTRXSTK.obj create mode 100644 CODE/RP/MUNGA/opt/NAMELIST.obj create mode 100644 CODE/RP/MUNGA/opt/NODE.obj create mode 100644 CODE/RP/MUNGA/opt/NORMAL.obj create mode 100644 CODE/RP/MUNGA/opt/ORIGIN.obj create mode 100644 CODE/RP/MUNGA/opt/PLANE.obj create mode 100644 CODE/RP/MUNGA/opt/POINT3D.obj create mode 100644 CODE/RP/MUNGA/opt/RANDOM.obj create mode 100644 CODE/RP/MUNGA/opt/RAY.obj create mode 100644 CODE/RP/MUNGA/opt/RECT2D.obj create mode 100644 CODE/RP/MUNGA/opt/RETICLE.obj create mode 100644 CODE/RP/MUNGA/opt/SCALAR.obj create mode 100644 CODE/RP/MUNGA/opt/SFESKT.obj create mode 100644 CODE/RP/MUNGA/opt/SLOT.obj create mode 100644 CODE/RP/MUNGA/opt/SOCKET.obj create mode 100644 CODE/RP/MUNGA/opt/SPHERE.obj create mode 100644 CODE/RP/MUNGA/opt/SPLINE.obj create mode 100644 CODE/RP/MUNGA/opt/SRTSKT.obj create mode 100644 CODE/RP/MUNGA/opt/TESTALL.obj create mode 100644 CODE/RP/MUNGA/opt/TIME.obj create mode 100644 CODE/RP/MUNGA/opt/TIMESTUB.obj create mode 100644 CODE/RP/MUNGA/opt/TRACE.obj create mode 100644 CODE/RP/MUNGA/opt/TRACSTUB.obj create mode 100644 CODE/RP/MUNGA/opt/UNITVEC.obj create mode 100644 CODE/RP/MUNGA/opt/opt.cfg create mode 100644 CODE/RP/MUNGA_L4/JOYSTICK.ASM create mode 100644 CODE/RP/MUNGA_L4/L4APP.HPP create mode 100644 CODE/RP/MUNGA_L4/L4APP.TCP create mode 100644 CODE/RP/MUNGA_L4/L4APP.THP create mode 100644 CODE/RP/MUNGA_L4/L4ASM.INC create mode 100644 CODE/RP/MUNGA_L4/L4AUDHDW.CPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDHDW.HPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDHDW.TCP create mode 100644 CODE/RP/MUNGA_L4/L4AUDIO.CPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDIO.HPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDLVL.CPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDLVL.HPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDRES.CPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDRES.HPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDRND.CPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDRND.HPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDTUL.CPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDWTR.CPP create mode 100644 CODE/RP/MUNGA_L4/L4AUDWTR.HPP create mode 100644 CODE/RP/MUNGA_L4/L4CTLTUL.CPP create mode 100644 CODE/RP/MUNGA_L4/L4CTRL.CPP create mode 100644 CODE/RP/MUNGA_L4/L4CTRL.HPP create mode 100644 CODE/RP/MUNGA_L4/L4CTRL.TCP create mode 100644 CODE/RP/MUNGA_L4/L4CTRL.THP create mode 100644 CODE/RP/MUNGA_L4/L4DPLMEM.CPP create mode 100644 CODE/RP/MUNGA_L4/L4FILE.CPP create mode 100644 CODE/RP/MUNGA_L4/L4GAUIMA.CPP create mode 100644 CODE/RP/MUNGA_L4/L4GAUIMA.HPP create mode 100644 CODE/RP/MUNGA_L4/L4GAUIMM.HPP create mode 100644 CODE/RP/MUNGA_L4/L4GAUTUL.CPP create mode 100644 CODE/RP/MUNGA_L4/L4GREND.CPP create mode 100644 CODE/RP/MUNGA_L4/L4GREND.HPP create mode 100644 CODE/RP/MUNGA_L4/L4HOST.CPP create mode 100644 CODE/RP/MUNGA_L4/L4HOST.HPP create mode 100644 CODE/RP/MUNGA_L4/L4ICOM.CPP create mode 100644 CODE/RP/MUNGA_L4/L4ICOM.HPP create mode 100644 CODE/RP/MUNGA_L4/L4JOYSTK.HPP create mode 100644 CODE/RP/MUNGA_L4/L4KEYBD.CPP create mode 100644 CODE/RP/MUNGA_L4/L4KEYBD.HPP create mode 100644 CODE/RP/MUNGA_L4/L4LAMP.CPP create mode 100644 CODE/RP/MUNGA_L4/L4LAMP.HPP create mode 100644 CODE/RP/MUNGA_L4/L4MOUSE.CPP create mode 100644 CODE/RP/MUNGA_L4/L4MOUSE.HPP create mode 100644 CODE/RP/MUNGA_L4/L4MPPR.CPP create mode 100644 CODE/RP/MUNGA_L4/L4MPPR.HPP create mode 100644 CODE/RP/MUNGA_L4/L4MSSN.CPP create mode 100644 CODE/RP/MUNGA_L4/L4MSSN.HPP create mode 100644 CODE/RP/MUNGA_L4/L4NET.HPP create mode 100644 CODE/RP/MUNGA_L4/L4NET.TCP create mode 100644 CODE/RP/MUNGA_L4/L4PCSPAK.HPP create mode 100644 CODE/RP/MUNGA_L4/L4PLASMA.CPP create mode 100644 CODE/RP/MUNGA_L4/L4PLASMA.HPP create mode 100644 CODE/RP/MUNGA_L4/L4RIO.CPP create mode 100644 CODE/RP/MUNGA_L4/L4RIO.HPP create mode 100644 CODE/RP/MUNGA_L4/L4SERIAL.ASM create mode 100644 CODE/RP/MUNGA_L4/L4SERIAL.HPP create mode 100644 CODE/RP/MUNGA_L4/L4SPLR.HPP create mode 100644 CODE/RP/MUNGA_L4/L4SVGA16.ASM create mode 100644 CODE/RP/MUNGA_L4/L4TIME.CPP create mode 100644 CODE/RP/MUNGA_L4/L4TIME.HPP create mode 100644 CODE/RP/MUNGA_L4/L4TOOL.HPP create mode 100644 CODE/RP/MUNGA_L4/L4TRACE.CPP create mode 100644 CODE/RP/MUNGA_L4/L4TSTALL.CPP create mode 100644 CODE/RP/MUNGA_L4/L4VB16.CPP create mode 100644 CODE/RP/MUNGA_L4/L4VB16.HPP create mode 100644 CODE/RP/MUNGA_L4/L4VB8.CPP create mode 100644 CODE/RP/MUNGA_L4/L4VB8.HPP create mode 100644 CODE/RP/MUNGA_L4/L4VIDEO.CPP create mode 100644 CODE/RP/MUNGA_L4/L4VIDEO.HPP create mode 100644 CODE/RP/MUNGA_L4/L4VIDEO.TCP create mode 100644 CODE/RP/MUNGA_L4/L4VIDPER.CPP create mode 100644 CODE/RP/MUNGA_L4/L4VIDPER.HPP create mode 100644 CODE/RP/MUNGA_L4/L4VIDRND.CPP create mode 100644 CODE/RP/MUNGA_L4/L4VIDRND.HPP create mode 100644 CODE/RP/MUNGA_L4/L4VIDTUL.CPP create mode 100644 CODE/RP/MUNGA_L4/L4WRHOUS.CPP create mode 100644 CODE/RP/MUNGA_L4/L4WRHOUS.HPP create mode 100644 CODE/RP/MUNGA_L4/MUNGAL4.HPP create mode 100644 CODE/RP/MUNGA_L4/NETSHARE.ASM create mode 100644 CODE/RP/MUNGA_L4/NetNub/ANALYSIS.CPP create mode 100644 CODE/RP/MUNGA_L4/NetNub/ANALYSIS.HPP create mode 100644 CODE/RP/MUNGA_L4/NetNub/NETNUB.HPP create mode 100644 CODE/RP/MUNGA_L4/NetNub/NOPAUSE.CPP create mode 100644 CODE/RP/MUNGA_L4/NetNub/PROFILE.HPP create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/BOOTP.H create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/COPYRIGH.H create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/ELIB.H create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/ETHDEV.H create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/ICMP.H create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/STATE.RST create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/TCP.H create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/TCP.MOD create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/WATTCP.H create mode 100644 CODE/RP/MUNGA_L4/NetNub/include/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/NetNub/lib/WATTCPLG.LIB create mode 100644 CODE/RP/MUNGA_L4/NetNub/lib/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/NetNub/mssccprj.scc create mode 100644 CODE/RP/MUNGA_L4/NetNub/netnub.mak create mode 100644 CODE/RP/MUNGA_L4/NetNub/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/PCDPMI.INC create mode 100644 CODE/RP/MUNGA_L4/PCPIC.INC create mode 100644 CODE/RP/MUNGA_L4/PCSERIAL.INC create mode 100644 CODE/RP/MUNGA_L4/PCSPAK.ASM create mode 100644 CODE/RP/MUNGA_L4/SOSMAWE.C create mode 100644 CODE/RP/MUNGA_L4/SOSMAWE.H create mode 100644 CODE/RP/MUNGA_L4/SPEAKER.HPP create mode 100644 CODE/RP/MUNGA_L4/STARTDPL.C create mode 100644 CODE/RP/MUNGA_L4/joystick.OBJ create mode 100644 CODE/RP/MUNGA_L4/l4serial.OBJ create mode 100644 CODE/RP/MUNGA_L4/l4svga16.OBJ create mode 100644 CODE/RP/MUNGA_L4/libDPL/LIBDPL.LIB create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND.MNG create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND2.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND3.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND4.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND5.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND6.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND7.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND8.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VREND9.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VRENDMON.BTL create mode 100644 CODE/RP/MUNGA_L4/libDPL/VRNOSTEX.MNG create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/DPL.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/DPLTYPES.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/DPLUTILS.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/DPL_2D.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/DPL_PRIV.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/DPL_VPX.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/MATRIX.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/vpx/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/libDPL/dpl/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DIVTYPES.DEF create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DIVTYPES.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DIVVERS.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DLINK.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DM.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DP.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DS.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DTCP.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/DU.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/FILELIB.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/GETPARAM.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/MAPFILE.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/PARSER.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/PFBIZTAG.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/PFILE.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/PFPARSER.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/PGENERAL.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/PIMAGE.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/PTOOL.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/VDIFILE.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/__PFILE.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/__PTOOL.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dsys/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/DM.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/DMELEM.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VC.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCBODAPP.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCDATA.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCDEFS.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCDTYPES.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCDYNAM.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCELEMEN.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCELTYPE.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCERROR.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCINPDEF.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCMACROS.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCOBJECT.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCSTRUCT.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCTYPES.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VCVBOSE.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VL.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/VLTYPES.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/_VCSTRUC.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/_VCTYPES.H create mode 100644 CODE/RP/MUNGA_L4/libDPL/dvs/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/libDPL/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/mssccprj.scc create mode 100644 CODE/RP/MUNGA_L4/mungal4.mak create mode 100644 CODE/RP/MUNGA_L4/netshare.OBJ create mode 100644 CODE/RP/MUNGA_L4/opt/L4DPLMEM.obj create mode 100644 CODE/RP/MUNGA_L4/opt/L4HOST.obj create mode 100644 CODE/RP/MUNGA_L4/opt/L4KEYBD.obj create mode 100644 CODE/RP/MUNGA_L4/opt/L4MOUSE.obj create mode 100644 CODE/RP/MUNGA_L4/opt/L4TIME.obj create mode 100644 CODE/RP/MUNGA_L4/opt/L4TRACE.obj create mode 100644 CODE/RP/MUNGA_L4/opt/L4TSTALL.obj create mode 100644 CODE/RP/MUNGA_L4/opt/SOSMAWE.obj create mode 100644 CODE/RP/MUNGA_L4/opt/STARTDPL.obj create mode 100644 CODE/RP/MUNGA_L4/opt/joystick.OBJ create mode 100644 CODE/RP/MUNGA_L4/opt/l4serial.OBJ create mode 100644 CODE/RP/MUNGA_L4/opt/l4svga16.OBJ create mode 100644 CODE/RP/MUNGA_L4/opt/netshare.OBJ create mode 100644 CODE/RP/MUNGA_L4/opt/opt.cfg create mode 100644 CODE/RP/MUNGA_L4/pcspak.OBJ create mode 100644 CODE/RP/MUNGA_L4/sos/HMIMDRV.386 create mode 100644 CODE/RP/MUNGA_L4/sos/SOSDBXC.LIB create mode 100644 CODE/RP/MUNGA_L4/sos/SOSDWXCR.LIB create mode 100644 CODE/RP/MUNGA_L4/sos/SOSDWXCS.LIB create mode 100644 CODE/RP/MUNGA_L4/sos/SOSMAWE.C create mode 100644 CODE/RP/MUNGA_L4/sos/SOSMBXC.LIB create mode 100644 CODE/RP/MUNGA_L4/sos/SOSMW1CR.LIB create mode 100644 CODE/RP/MUNGA_L4/sos/SOSMWXCR.LIB create mode 100644 CODE/RP/MUNGA_L4/sos/SOSMWXCS.LIB create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOS.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOS.INC create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSDATA.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSDEFS.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSFNCT.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSM.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSMAWE.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSMDATA.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSMFNCT.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/SOSRES.H create mode 100644 CODE/RP/MUNGA_L4/sos/bc4/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/sos/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOS.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOSDATA.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOSDEFS.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOSFNCT.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOSM.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOSMDATA.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOSMFNCT.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/SOSRES.H create mode 100644 CODE/RP/MUNGA_L4/sos/wc/vssver.scc create mode 100644 CODE/RP/MUNGA_L4/vssver.scc create mode 100644 CODE/RP/OPT.mak create mode 100644 CODE/RP/RP/BLOCKER.HPP create mode 100644 CODE/RP/RP/BOOSTER.HPP create mode 100644 CODE/RP/RP/CRUSHER.HPP create mode 100644 CODE/RP/RP/DEMOPACK.HPP create mode 100644 CODE/RP/RP/DEMOPACK.bak create mode 100644 CODE/RP/RP/RP.HPP create mode 100644 CODE/RP/RP/RPCNSL.CPP create mode 100644 CODE/RP/RP/RPDIRECT.HPP create mode 100644 CODE/RP/RP/RPMSSN.CPP create mode 100644 CODE/RP/RP/RPMSSN.HPP create mode 100644 CODE/RP/RP/RPREG.HPP create mode 100644 CODE/RP/RP/RPTOOL.CPP create mode 100644 CODE/RP/RP/RPTOOL.HPP create mode 100644 CODE/RP/RP/RUNNER.HPP create mode 100644 CODE/RP/RP/THRUSTER.HPP create mode 100644 CODE/RP/RP/VTVPWR.CPP create mode 100644 CODE/RP/RP/VTVPWR.HPP create mode 100644 CODE/RP/RP/VTVSUB.CPP create mode 100644 CODE/RP/RP/VTVSUB.HPP create mode 100644 CODE/RP/RP/mssccprj.scc create mode 100644 CODE/RP/RP/opt/opt.cfg create mode 100644 CODE/RP/RP/rp.mak create mode 100644 CODE/RP/RP/vssver.scc create mode 100644 CODE/RP/RPL4.PTH create mode 100644 CODE/RP/RP_L4/RPL4.HPP create mode 100644 CODE/RP/RP_L4/RPL4APP.HPP create mode 100644 CODE/RP/RP_L4/RPL4ARND.CPP create mode 100644 CODE/RP/RP_L4/RPL4ARND.HPP create mode 100644 CODE/RP/RP_L4/RPL4GRND.HPP create mode 100644 CODE/RP/RP_L4/RPL4MODE.CPP create mode 100644 CODE/RP/RP_L4/RPL4MODE.HPP create mode 100644 CODE/RP/RP_L4/RPL4MSSN.HPP create mode 100644 CODE/RP/RP_L4/RPL4PB.HPP create mode 100644 CODE/RP/RP_L4/RPL4TOOL.CPP create mode 100644 CODE/RP/RP_L4/RPL4VER.HPP create mode 100644 CODE/RP/RP_L4/RPL4VID.HPP create mode 100644 CODE/RP/RP_L4/mssccprj.scc create mode 100644 CODE/RP/RP_L4/opt/opt.cfg create mode 100644 CODE/RP/RP_L4/rpL4.mak create mode 100644 CODE/RP/RP_L4/vssver.scc create mode 100644 CODE/RP/clropt.bat create mode 100644 CODE/RP/d1.mak create mode 100644 CODE/RP/d2s.mak create mode 100644 CODE/RP/d3s.mak create mode 100644 CODE/RP/example.cfg create mode 100644 CODE/RP/make.cfg create mode 100644 CODE/RP/mssccprj.scc create mode 100644 CODE/RP/opt.bat create mode 100644 CODE/RP/opt.cfg create mode 100644 CODE/RP/transfr.bat create mode 100644 CODE/RP/vssver.scc create mode 100644 CONTENT/BT/32STUB.EXE create mode 100644 CONTENT/BT/ANIM.BAT create mode 100644 CONTENT/BT/ANIM1.BAT create mode 100644 CONTENT/BT/ANIMCAM.BAT create mode 100644 CONTENT/BT/ANIMS/AVABMP.ANI create mode 100644 CONTENT/BT/ANIMS/AVAGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/AVAGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/BATBMP.ANI create mode 100644 CONTENT/BT/ANIMS/BATGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/BATGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/BATSQUI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHBBLI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHBBRI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHBMP.ANI create mode 100644 CONTENT/BT/ANIMS/BLHBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHRRL.ANI create mode 100644 CONTENT/BT/ANIMS/BLHRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHRRR.ANI create mode 100644 CONTENT/BT/ANIMS/BLHRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHSQI.ANI create mode 100644 CONTENT/BT/ANIMS/BLHSQT.ANI create mode 100644 CONTENT/BT/ANIMS/BLHWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBBL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBBLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBBR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBBRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBMP.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBSL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBSLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBSR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRBSRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRGGL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRGGLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRGGR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRGGRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRRL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRRR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRWL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRWR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSBL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSBLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSBR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSBRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSWL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSWLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSWR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRSWRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRTRN.ANI create mode 100644 CONTENT/BT/ANIMS/FIRTRNI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWGL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWGLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWGR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWGRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWRL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWRLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWRR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWRRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWSL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWSLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWSR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWSRI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWWL.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWWR.ANI create mode 100644 CONTENT/BT/ANIMS/FIRWWRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBBL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBBLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBBR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBBRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBMP.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBSL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBSLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBSR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKBSRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKFB.ANI create mode 100644 CONTENT/BT/ANIMS/JAKFF.ANI create mode 100644 CONTENT/BT/ANIMS/JAKFL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKFR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKGGL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKGGLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKGGR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKGGRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRRL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRRR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRWL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRWR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKSBL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKSBR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKSWL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKSWLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKSWR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKSWRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKTRN.ANI create mode 100644 CONTENT/BT/ANIMS/JAKTRNI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWGL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWGLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWGR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWGRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWRL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWRLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWRR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWRRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWSL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWSLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWSR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWSRI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWWL.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWWR.ANI create mode 100644 CONTENT/BT/ANIMS/JAKWWRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBBL.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBBLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBBR.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBBRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBMP.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBSLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKBSRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKGGL.ANI create mode 100644 CONTENT/BT/ANIMS/LOKGGLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKGGR.ANI create mode 100644 CONTENT/BT/ANIMS/LOKGGRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRRL.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRRR.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRWL.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRWR.ANI create mode 100644 CONTENT/BT/ANIMS/LOKRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKSBLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKSBRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKSWLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKSWRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKTRN.ANI create mode 100644 CONTENT/BT/ANIMS/LOKTRNI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWGL.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWGLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWGR.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWGRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWRL.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWRLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWRR.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWRRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWSLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWSRI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWWL.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWWR.ANI create mode 100644 CONTENT/BT/ANIMS/LOKWWRI.ANI create mode 100644 CONTENT/BT/ANIMS/MADBMP.ANI create mode 100644 CONTENT/BT/ANIMS/MADGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/MADGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNBMP.ANI create mode 100644 CONTENT/BT/ANIMS/OWNBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNBSLI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNBSRI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNRRL.ANI create mode 100644 CONTENT/BT/ANIMS/OWNRRR.ANI create mode 100644 CONTENT/BT/ANIMS/OWNRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNSQI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNSQT.ANI create mode 100644 CONTENT/BT/ANIMS/OWNSWLI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNSWRI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNWGL.ANI create mode 100644 CONTENT/BT/ANIMS/OWNWGR.ANI create mode 100644 CONTENT/BT/ANIMS/OWNWSL.ANI create mode 100644 CONTENT/BT/ANIMS/OWNWSLI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNWSR.ANI create mode 100644 CONTENT/BT/ANIMS/OWNWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/OWNWWRI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPBBL.ANI create mode 100644 CONTENT/BT/ANIMS/RAPBBR.ANI create mode 100644 CONTENT/BT/ANIMS/RAPBMP.ANI create mode 100644 CONTENT/BT/ANIMS/RAPBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRRL.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRRR.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRWL.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRWR.ANI create mode 100644 CONTENT/BT/ANIMS/RAPRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSBL.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSBLI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSBR.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSBRI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSQDI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSQUI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSWL.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSWLI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSWR.ANI create mode 100644 CONTENT/BT/ANIMS/RAPSWRI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPWRL.ANI create mode 100644 CONTENT/BT/ANIMS/RAPWRLI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPWRR.ANI create mode 100644 CONTENT/BT/ANIMS/RAPWRRI.ANI create mode 100644 CONTENT/BT/ANIMS/RAPWWL.ANI create mode 100644 CONTENT/BT/ANIMS/RAPWWR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBBL.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBBLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBBR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBBRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBMP.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBSLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDBSRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDGGL.ANI create mode 100644 CONTENT/BT/ANIMS/SNDGGLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDGGR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDGGRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRRL.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRRR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRWL.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRWR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDSBLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDSBRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDSWLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDSWRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDTRN.ANI create mode 100644 CONTENT/BT/ANIMS/SNDTRNI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWGL.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWGLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWGR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWGRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWRL.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWRLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWRR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWRRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWSLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWSRI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWWL.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWWR.ANI create mode 100644 CONTENT/BT/ANIMS/SNDWWRI.ANI create mode 100644 CONTENT/BT/ANIMS/STIBBLI.ANI create mode 100644 CONTENT/BT/ANIMS/STIBBR.ANI create mode 100644 CONTENT/BT/ANIMS/STIBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/STIBSLI.ANI create mode 100644 CONTENT/BT/ANIMS/STIBSRI.ANI create mode 100644 CONTENT/BT/ANIMS/STIRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/STIRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/STIRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/STIRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/STISBLI.ANI create mode 100644 CONTENT/BT/ANIMS/STISBRI.ANI create mode 100644 CONTENT/BT/ANIMS/STISQDI.ANI create mode 100644 CONTENT/BT/ANIMS/STISWLI.ANI create mode 100644 CONTENT/BT/ANIMS/STISWRI.ANI create mode 100644 CONTENT/BT/ANIMS/STIWRLI.ANI create mode 100644 CONTENT/BT/ANIMS/STIWRRI.ANI create mode 100644 CONTENT/BT/ANIMS/STIWSLI.ANI create mode 100644 CONTENT/BT/ANIMS/STIWSRI.ANI create mode 100644 CONTENT/BT/ANIMS/STIWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/STIWWRI.ANI create mode 100644 CONTENT/BT/ANIMS/THR4JERR.ANI create mode 100644 CONTENT/BT/ANIMS/THRBBL.ANI create mode 100644 CONTENT/BT/ANIMS/THRBBLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRBBR.ANI create mode 100644 CONTENT/BT/ANIMS/THRBBRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRBMP.ANI create mode 100644 CONTENT/BT/ANIMS/THRBMPI.ANI create mode 100644 CONTENT/BT/ANIMS/THRBSLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRBSRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRCLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRCLS.ANI create mode 100644 CONTENT/BT/ANIMS/THRGGL.ANI create mode 100644 CONTENT/BT/ANIMS/THRGGLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRGGR.ANI create mode 100644 CONTENT/BT/ANIMS/THRGGRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRGSLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRGSRI.ANI create mode 100644 CONTENT/BT/ANIMS/THROPI.ANI create mode 100644 CONTENT/BT/ANIMS/THRRRL.ANI create mode 100644 CONTENT/BT/ANIMS/THRRRLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRRRR.ANI create mode 100644 CONTENT/BT/ANIMS/THRRRRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRRWL.ANI create mode 100644 CONTENT/BT/ANIMS/THRRWLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRRWR.ANI create mode 100644 CONTENT/BT/ANIMS/THRRWRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRSBLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRSBRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRSQT.ANI create mode 100644 CONTENT/BT/ANIMS/THRSWLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRSWRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRTRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRTRN.ANI create mode 100644 CONTENT/BT/ANIMS/THRTRNI.ANI create mode 100644 CONTENT/BT/ANIMS/THRTSI.ANI create mode 100644 CONTENT/BT/ANIMS/THRTST.ANI create mode 100644 CONTENT/BT/ANIMS/THRWGL.ANI create mode 100644 CONTENT/BT/ANIMS/THRWGLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRWGR.ANI create mode 100644 CONTENT/BT/ANIMS/THRWGRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRWRL.ANI create mode 100644 CONTENT/BT/ANIMS/THRWRLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRWRR.ANI create mode 100644 CONTENT/BT/ANIMS/THRWRRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRWSLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRWSRI.ANI create mode 100644 CONTENT/BT/ANIMS/THRWWL.ANI create mode 100644 CONTENT/BT/ANIMS/THRWWLI.ANI create mode 100644 CONTENT/BT/ANIMS/THRWWR.ANI create mode 100644 CONTENT/BT/ANIMS/THRWWRI.ANI create mode 100644 CONTENT/BT/ARCBT.BAT create mode 100644 CONTENT/BT/ARCFILES.LST create mode 100644 CONTENT/BT/AUDIO/ABFWRN01.MID create mode 100644 CONTENT/BT/AUDIO/ABNCMP.SCP create mode 100644 CONTENT/BT/AUDIO/ABNTRG.SCP create mode 100644 CONTENT/BT/AUDIO/ACNCMP.SCP create mode 100644 CONTENT/BT/AUDIO/ACNCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/ACNTRG.SCP create mode 100644 CONTENT/BT/AUDIO/ACNTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/ALMINT.SCP create mode 100644 CONTENT/BT/AUDIO/AUDIO.INI create mode 100644 CONTENT/BT/AUDIO/AUDIOMR.INI create mode 100644 CONTENT/BT/AUDIO/AVA1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/AVA1INT.SCP create mode 100644 CONTENT/BT/AUDIO/AVA2.SCP create mode 100644 CONTENT/BT/AUDIO/AVAEXT.SCP create mode 100644 CONTENT/BT/AUDIO/AVAINT.SCP create mode 100644 CONTENT/BT/AUDIO/BATEXT.SCP create mode 100644 CONTENT/BT/AUDIO/BATINT.SCP create mode 100644 CONTENT/BT/AUDIO/BBNEXP.SCP create mode 100644 CONTENT/BT/AUDIO/BHK1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/BHK1INT.SCP create mode 100644 CONTENT/BT/AUDIO/BIGEXP.SCP create mode 100644 CONTENT/BT/AUDIO/BIGEXP01.MID create mode 100644 CONTENT/BT/AUDIO/BLKEXT.SCP create mode 100644 CONTENT/BT/AUDIO/BLKINT.SCP create mode 100644 CONTENT/BT/AUDIO/BRNEXT.SCP create mode 100644 CONTENT/BT/AUDIO/BRNINT.SCP create mode 100644 CONTENT/BT/AUDIO/BUTCMP.SCP create mode 100644 CONTENT/BT/AUDIO/BUTTRG.SCP create mode 100644 CONTENT/BT/AUDIO/CALEXT.SCP create mode 100644 CONTENT/BT/AUDIO/CALINT.SCP create mode 100644 CONTENT/BT/AUDIO/CLKWRN01.MID create mode 100644 CONTENT/BT/AUDIO/CLTCMP.SCP create mode 100644 CONTENT/BT/AUDIO/CLTTRG.SCP create mode 100644 CONTENT/BT/AUDIO/CNDCMP.SCP create mode 100644 CONTENT/BT/AUDIO/CNDTRG.SCP create mode 100644 CONTENT/BT/AUDIO/COLEXT.SCP create mode 100644 CONTENT/BT/AUDIO/COLINT.SCP create mode 100644 CONTENT/BT/AUDIO/CRNEXP.SCP create mode 100644 CONTENT/BT/AUDIO/CTMIX.CFG create mode 100644 CONTENT/BT/AUDIO/DGAEXP.SCP create mode 100644 CONTENT/BT/AUDIO/DGBEXP.SCP create mode 100644 CONTENT/BT/AUDIO/DGCEXP.SCP create mode 100644 CONTENT/BT/AUDIO/DSTCMP.SCP create mode 100644 CONTENT/BT/AUDIO/DSTRD01.MID create mode 100644 CONTENT/BT/AUDIO/DSTRD02.MID create mode 100644 CONTENT/BT/AUDIO/DSTTRG.SCP create mode 100644 CONTENT/BT/AUDIO/EPCCMP.SCP create mode 100644 CONTENT/BT/AUDIO/EPPCMP.SCP create mode 100644 CONTENT/BT/AUDIO/EPPCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/EPPTRG.SCP create mode 100644 CONTENT/BT/AUDIO/EPPTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/ERLCMP.SCP create mode 100644 CONTENT/BT/AUDIO/ERLCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/ERLTRG.SCP create mode 100644 CONTENT/BT/AUDIO/ERLTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/ERMCMP.SCP create mode 100644 CONTENT/BT/AUDIO/ERMCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/ERMTRG.SCP create mode 100644 CONTENT/BT/AUDIO/ERMTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/ERSCMP.SCP create mode 100644 CONTENT/BT/AUDIO/ERSCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/ERSTRG.SCP create mode 100644 CONTENT/BT/AUDIO/ERSTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/FIND.TXT create mode 100644 CONTENT/BT/AUDIO/FIREXT.SCP create mode 100644 CONTENT/BT/AUDIO/FIRINT.SCP create mode 100644 CONTENT/BT/AUDIO/FOTEXT.SCP create mode 100644 CONTENT/BT/AUDIO/FOTINT.SCP create mode 100644 CONTENT/BT/AUDIO/GENCMP.SCP create mode 100644 CONTENT/BT/AUDIO/GENTRG.SCP create mode 100644 CONTENT/BT/AUDIO/GENWRN01.MID create mode 100644 CONTENT/BT/AUDIO/GENWRN02.MID create mode 100644 CONTENT/BT/AUDIO/GLRCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/GLRTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/HETEXT.SCP create mode 100644 CONTENT/BT/AUDIO/HETINT.SCP create mode 100644 CONTENT/BT/AUDIO/ICOM.CFG create mode 100644 CONTENT/BT/AUDIO/INCARM01.MID create mode 100644 CONTENT/BT/AUDIO/JAKEXT.SCP create mode 100644 CONTENT/BT/AUDIO/JAKINT.SCP create mode 100644 CONTENT/BT/AUDIO/LACCMP.SCP create mode 100644 CONTENT/BT/AUDIO/LACTRG.SCP create mode 100644 CONTENT/BT/AUDIO/LEGWRN01.MID create mode 100644 CONTENT/BT/AUDIO/LLRCMP.SCP create mode 100644 CONTENT/BT/AUDIO/LLRCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/LLRTRG.SCP create mode 100644 CONTENT/BT/AUDIO/LLRTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/LO1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/LO1INT.SCP create mode 100644 CONTENT/BT/AUDIO/LOK1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/LOK1INT.SCP create mode 100644 CONTENT/BT/AUDIO/LOK2EXT.SCP create mode 100644 CONTENT/BT/AUDIO/LOK2INT.SCP create mode 100644 CONTENT/BT/AUDIO/LOKEXT.SCP create mode 100644 CONTENT/BT/AUDIO/LOKINT.SCP create mode 100644 CONTENT/BT/AUDIO/LRMCMP.SCP create mode 100644 CONTENT/BT/AUDIO/LRMTRG.SCP create mode 100644 CONTENT/BT/AUDIO/LSRCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/LSREXP.SCP create mode 100644 CONTENT/BT/AUDIO/LSREXPI.SCP create mode 100644 CONTENT/BT/AUDIO/LSRLDD01.MID create mode 100644 CONTENT/BT/AUDIO/LSRTRG.SCP create mode 100644 CONTENT/BT/AUDIO/LSRTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/MACCMP.SCP create mode 100644 CONTENT/BT/AUDIO/MACROS.SCP create mode 100644 CONTENT/BT/AUDIO/MACTRG.SCP create mode 100644 CONTENT/BT/AUDIO/MAD1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/MAD1INT.SCP create mode 100644 CONTENT/BT/AUDIO/MAD2EXT.SCP create mode 100644 CONTENT/BT/AUDIO/MAD2INT.SCP create mode 100644 CONTENT/BT/AUDIO/MADEXT.SCP create mode 100644 CONTENT/BT/AUDIO/MADINT.SCP create mode 100644 CONTENT/BT/AUDIO/MBNEXP.SCP create mode 100644 CONTENT/BT/AUDIO/MCHEXP03.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXP04.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXP05.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXP06.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXP07.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXPI1.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXPI2.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXPI3.MID create mode 100644 CONTENT/BT/AUDIO/MCHEXT.SCP create mode 100644 CONTENT/BT/AUDIO/MCHFRE01.MID create mode 100644 CONTENT/BT/AUDIO/MCHINT.SCP create mode 100644 CONTENT/BT/AUDIO/MCTINT.SCP create mode 100644 CONTENT/BT/AUDIO/MEDEXP.SCP create mode 100644 CONTENT/BT/AUDIO/MEDEXP01.MID create mode 100644 CONTENT/BT/AUDIO/MGNCMP.SCP create mode 100644 CONTENT/BT/AUDIO/MGNEXP.SCP create mode 100644 CONTENT/BT/AUDIO/MGNEXPC.SCP create mode 100644 CONTENT/BT/AUDIO/MGNTRG.SCP create mode 100644 CONTENT/BT/AUDIO/MLRCMP.SCP create mode 100644 CONTENT/BT/AUDIO/MLRCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/MLRTRG.SCP create mode 100644 CONTENT/BT/AUDIO/MLRTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/MSLCMP.SCP create mode 100644 CONTENT/BT/AUDIO/MSLEXP.SCP create mode 100644 CONTENT/BT/AUDIO/MSLEXPI.SCP create mode 100644 CONTENT/BT/AUDIO/MSLJAM01.MID create mode 100644 CONTENT/BT/AUDIO/MSLLDD01.MID create mode 100644 CONTENT/BT/AUDIO/MSLMFR01.MID create mode 100644 CONTENT/BT/AUDIO/MSLTRG.SCP create mode 100644 CONTENT/BT/AUDIO/MSLTVL.SCP create mode 100644 CONTENT/BT/AUDIO/MYRCMP.SCP create mode 100644 CONTENT/BT/AUDIO/MYRTRG.SCP create mode 100644 CONTENT/BT/AUDIO/OWN1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/OWN1INT.SCP create mode 100644 CONTENT/BT/AUDIO/OWNEXT.SCP create mode 100644 CONTENT/BT/AUDIO/OWNINT.SCP create mode 100644 CONTENT/BT/AUDIO/PLYINT.SCP create mode 100644 CONTENT/BT/AUDIO/PPCCMP.SCP create mode 100644 CONTENT/BT/AUDIO/PPCCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/PPCEXP.SCP create mode 100644 CONTENT/BT/AUDIO/PPCEXPI.SCP create mode 100644 CONTENT/BT/AUDIO/PPCTRG.SCP create mode 100644 CONTENT/BT/AUDIO/PPCTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/PRGBUT01.MID create mode 100644 CONTENT/BT/AUDIO/PRJCMP.SCP create mode 100644 CONTENT/BT/AUDIO/PRJCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/PRJEXP.SCP create mode 100644 CONTENT/BT/AUDIO/PRJEXPI.SCP create mode 100644 CONTENT/BT/AUDIO/PRJJAM01.MID create mode 100644 CONTENT/BT/AUDIO/PRJLDD01.MID create mode 100644 CONTENT/BT/AUDIO/PRJMFR01.MID create mode 100644 CONTENT/BT/AUDIO/PRJTRG.SCP create mode 100644 CONTENT/BT/AUDIO/PRJTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/PRJTVL.SCP create mode 100644 CONTENT/BT/AUDIO/RAPEXT.SCP create mode 100644 CONTENT/BT/AUDIO/RAPINT.SCP create mode 100644 CONTENT/BT/AUDIO/SACCMP.SCP create mode 100644 CONTENT/BT/AUDIO/SACTRG.SCP create mode 100644 CONTENT/BT/AUDIO/SBNEXP.SCP create mode 100644 CONTENT/BT/AUDIO/SHFEXT.SCP create mode 100644 CONTENT/BT/AUDIO/SLRCMP.SCP create mode 100644 CONTENT/BT/AUDIO/SLRCMPE.SCP create mode 100644 CONTENT/BT/AUDIO/SLRTRG.SCP create mode 100644 CONTENT/BT/AUDIO/SLRTRGE.SCP create mode 100644 CONTENT/BT/AUDIO/SMLEXP.SCP create mode 100644 CONTENT/BT/AUDIO/SND1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/SND1INT.SCP create mode 100644 CONTENT/BT/AUDIO/SND2EXT.SCP create mode 100644 CONTENT/BT/AUDIO/SND2INT.SCP create mode 100644 CONTENT/BT/AUDIO/SNDEXT.SCP create mode 100644 CONTENT/BT/AUDIO/SNDINT.SCP create mode 100644 CONTENT/BT/AUDIO/SNRTRG.SCP create mode 100644 CONTENT/BT/AUDIO/SRMCMP.SCP create mode 100644 CONTENT/BT/AUDIO/SRMTRG.SCP create mode 100644 CONTENT/BT/AUDIO/STATIC.SCP create mode 100644 CONTENT/BT/AUDIO/STIEXT.SCP create mode 100644 CONTENT/BT/AUDIO/STIINT.SCP create mode 100644 CONTENT/BT/AUDIO/SYMBOLS.SCP create mode 100644 CONTENT/BT/AUDIO/THR1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/THR1INT.SCP create mode 100644 CONTENT/BT/AUDIO/THR6EXT.SCP create mode 100644 CONTENT/BT/AUDIO/THR6INT.SCP create mode 100644 CONTENT/BT/AUDIO/THREXT.SCP create mode 100644 CONTENT/BT/AUDIO/THRINT.SCP create mode 100644 CONTENT/BT/AUDIO/TRSEXT.SCP create mode 100644 CONTENT/BT/AUDIO/TRSINT.SCP create mode 100644 CONTENT/BT/AUDIO/VUL1EXT.SCP create mode 100644 CONTENT/BT/AUDIO/VUL1INT.SCP create mode 100644 CONTENT/BT/AUDIO/VUL2EXT.SCP create mode 100644 CONTENT/BT/AUDIO/VUL2INT.SCP create mode 100644 CONTENT/BT/AUDIO/VULEXT.SCP create mode 100644 CONTENT/BT/AUDIO/VULINT.SCP create mode 100644 CONTENT/BT/AUDIO/WNDEXT01.SCP create mode 100644 CONTENT/BT/AUDIO/WPNINT.SCP create mode 100644 CONTENT/BT/AUTOEXEC.BAT create mode 100644 CONTENT/BT/BLDTEST.SCN create mode 100644 CONTENT/BT/BT.BAT create mode 100644 CONTENT/BT/BTCAM.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM01.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM02.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM03.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM04.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM05.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM06.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM07.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM08.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM09.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM10.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM11.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM12.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM13.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM14.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM15.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM16.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM17.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM18.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM19.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM20.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM21.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM22.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM23.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM24.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM25.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM26.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM27.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM28.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM29.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM30.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM31.BAT create mode 100644 CONTENT/BT/BTCAM/BTCAM32.BAT create mode 100644 CONTENT/BT/BTGO.BAT create mode 100644 CONTENT/BT/BTL4.BLD create mode 100644 CONTENT/BT/BTL4.OPS create mode 100644 CONTENT/BT/BTL4.ORG create mode 100644 CONTENT/BT/BTL4BU.BLD create mode 100644 CONTENT/BT/BTLOOK.BAT create mode 100644 CONTENT/BT/BTNET.BAT create mode 100644 CONTENT/BT/BTPREP.BAT create mode 100644 CONTENT/BT/BUILD.BAT create mode 100644 CONTENT/BT/BUILD1.BAT create mode 100644 CONTENT/BT/BUILDRES.BAT create mode 100644 CONTENT/BT/DEARCBT.BAT create mode 100644 CONTENT/BT/EXCLUDE.LST create mode 100644 CONTENT/BT/FAILURE.LOG create mode 100644 CONTENT/BT/FILELIST create mode 100644 CONTENT/BT/GAUGE/AB01_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB02_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB03_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB04_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB05_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB06_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB07_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB08_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB09_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AB10_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AD01_GA.GIM create mode 100644 CONTENT/BT/GAUGE/ADPAL.PCC create mode 100644 CONTENT/BT/GAUGE/ADPAL2.PCC create mode 100644 CONTENT/BT/GAUGE/APC.GIM create mode 100644 CONTENT/BT/GAUGE/AR01_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AR02_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AR03_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AR04_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AR05_GA.GIM create mode 100644 CONTENT/BT/GAUGE/ARENA_GA.GIM create mode 100644 CONTENT/BT/GAUGE/ARMRMOVR.GIM create mode 100644 CONTENT/BT/GAUGE/AVA2DAMA.PCC create mode 100644 CONTENT/BT/GAUGE/AVA_MR.PCC create mode 100644 CONTENT/BT/GAUGE/AW01_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AW02_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AW03_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AW04_GA.GIM create mode 100644 CONTENT/BT/GAUGE/AW05_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BDUCK.PCC create mode 100644 CONTENT/BT/GAUGE/BLAMP.PCC create mode 100644 CONTENT/BT/GAUGE/BLD03_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLD04_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLD06_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLD08_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLD08_GA.ORG create mode 100644 CONTENT/BT/GAUGE/BLD20_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLD24_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLD26_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLD27_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BLHHT.PCC create mode 100644 CONTENT/BT/GAUGE/BLH_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BNK_GA.GIM create mode 100644 CONTENT/BT/GAUGE/BTEBUS.PCC create mode 100644 CONTENT/BT/GAUGE/BTECMODE.PCC create mode 100644 CONTENT/BT/GAUGE/BTEEJTM.PCC create mode 100644 CONTENT/BT/GAUGE/BTEFIRE.PCC create mode 100644 CONTENT/BT/GAUGE/BTEHFAIL.PCC create mode 100644 CONTENT/BT/GAUGE/BTEJAM.PCC create mode 100644 CONTENT/BT/GAUGE/BTELOOP.PCC create mode 100644 CONTENT/BT/GAUGE/BTEMODE.PCC create mode 100644 CONTENT/BT/GAUGE/BTEPFAIL.PCC create mode 100644 CONTENT/BT/GAUGE/BTESFAIL.PCC create mode 100644 CONTENT/BT/GAUGE/BTESLEV.PCC create mode 100644 CONTENT/BT/GAUGE/BTESRNGE.PCC create mode 100644 CONTENT/BT/GAUGE/BTEUNJM.PCC create mode 100644 CONTENT/BT/GAUGE/BTJOY.PCC create mode 100644 CONTENT/BT/GAUGE/BTOPAL.PCC create mode 100644 CONTENT/BT/GAUGE/BTPBUS.PCC create mode 100644 CONTENT/BT/GAUGE/BTPLOOP.PCC create mode 100644 CONTENT/BT/GAUGE/BTSPAL.PCC create mode 100644 CONTENT/BT/GAUGE/BTWARN.PCC create mode 100644 CONTENT/BT/GAUGE/BULLDOG.GIM create mode 100644 CONTENT/BT/GAUGE/BUTTEA_G.GIM create mode 100644 CONTENT/BT/GAUGE/BUTTEB_G.GIM create mode 100644 CONTENT/BT/GAUGE/BUTTEC_G.GIM create mode 100644 CONTENT/BT/GAUGE/BUTTED_G.GIM create mode 100644 CONTENT/BT/GAUGE/BUTTEE_G.GIM create mode 100644 CONTENT/BT/GAUGE/CALPB_GA.GIM create mode 100644 CONTENT/BT/GAUGE/CALP_GA.GIM create mode 100644 CONTENT/BT/GAUGE/CM_BOTH.PCC create mode 100644 CONTENT/BT/GAUGE/CM_OFF.PCC create mode 100644 CONTENT/BT/GAUGE/CM_ONLY.PCC create mode 100644 CONTENT/BT/GAUGE/CM_OTHER.PCC create mode 100644 CONTENT/BT/GAUGE/COMTRUCK.GIM create mode 100644 CONTENT/BT/GAUGE/COOLANT.GIM create mode 100644 CONTENT/BT/GAUGE/DISH_GA.GIM create mode 100644 CONTENT/BT/GAUGE/DOZER.GIM create mode 100644 CONTENT/BT/GAUGE/EAFC10.PCC create mode 100644 CONTENT/BT/GAUGE/EAFC100.PCC create mode 100644 CONTENT/BT/GAUGE/EAFC25.PCC create mode 100644 CONTENT/BT/GAUGE/EAFC5.PCC create mode 100644 CONTENT/BT/GAUGE/EAFC50.PCC create mode 100644 CONTENT/BT/GAUGE/EDESTRYD.PCC create mode 100644 CONTENT/BT/GAUGE/EDMG.PCC create mode 100644 CONTENT/BT/GAUGE/EERLLAS.PCC create mode 100644 CONTENT/BT/GAUGE/EERPPC.PCC create mode 100644 CONTENT/BT/GAUGE/EERSLAS.PCC create mode 100644 CONTENT/BT/GAUGE/ELBX10.PCC create mode 100644 CONTENT/BT/GAUGE/ELBX100.PCC create mode 100644 CONTENT/BT/GAUGE/ELBX25.PCC create mode 100644 CONTENT/BT/GAUGE/ELBX5.PCC create mode 100644 CONTENT/BT/GAUGE/ELEAK.PCC create mode 100644 CONTENT/BT/GAUGE/ELLAS.PCC create mode 100644 CONTENT/BT/GAUGE/ELRM10.PCC create mode 100644 CONTENT/BT/GAUGE/ELRM15.PCC create mode 100644 CONTENT/BT/GAUGE/ELRM20.PCC create mode 100644 CONTENT/BT/GAUGE/ELRM5.PCC create mode 100644 CONTENT/BT/GAUGE/EMG.PCC create mode 100644 CONTENT/BT/GAUGE/ENRK10.PCC create mode 100644 CONTENT/BT/GAUGE/ENRK15.PCC create mode 100644 CONTENT/BT/GAUGE/ENRK20.PCC create mode 100644 CONTENT/BT/GAUGE/ENRK5.PCC create mode 100644 CONTENT/BT/GAUGE/EPPC.PCC create mode 100644 CONTENT/BT/GAUGE/ESCND.PCC create mode 100644 CONTENT/BT/GAUGE/ESENSORS.PCC create mode 100644 CONTENT/BT/GAUGE/ESPEED.PCC create mode 100644 CONTENT/BT/GAUGE/ESRM2.PCC create mode 100644 CONTENT/BT/GAUGE/ESRM4.PCC create mode 100644 CONTENT/BT/GAUGE/ESRM6.PCC create mode 100644 CONTENT/BT/GAUGE/ESTRK2.PCC create mode 100644 CONTENT/BT/GAUGE/ESTRK4.PCC create mode 100644 CONTENT/BT/GAUGE/ESTRK6.PCC create mode 100644 CONTENT/BT/GAUGE/EVOLT.PCC create mode 100644 CONTENT/BT/GAUGE/FP1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/FP2_GA.GIM create mode 100644 CONTENT/BT/GAUGE/FT1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/FT2_GA.GIM create mode 100644 CONTENT/BT/GAUGE/GAUGE.GAT create mode 100644 CONTENT/BT/GAUGE/GNR_GA.GIM create mode 100644 CONTENT/BT/GAUGE/HARASSER.GIM create mode 100644 CONTENT/BT/GAUGE/HEATPAL.PCC create mode 100644 CONTENT/BT/GAUGE/HEATPAL2.PCC create mode 100644 CONTENT/BT/GAUGE/HELV15.PCC create mode 100644 CONTENT/BT/GAUGE/HELV18.PCC create mode 100644 CONTENT/BT/GAUGE/HELV42.PCC create mode 100644 CONTENT/BT/GAUGE/HILLG1_G.GIM create mode 100644 CONTENT/BT/GAUGE/HILLG2_G.GIM create mode 100644 CONTENT/BT/GAUGE/HILLG3_G.GIM create mode 100644 CONTENT/BT/GAUGE/HL1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/HL2_GA.GIM create mode 100644 CONTENT/BT/GAUGE/HN1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/HUMMER.GIM create mode 100644 CONTENT/BT/GAUGE/HUT_GA.GIM create mode 100644 CONTENT/BT/GAUGE/HWZ_GA.GIM create mode 100644 CONTENT/BT/GAUGE/JAKCRIT.PCC create mode 100644 CONTENT/BT/GAUGE/JAKHEAT.PCC create mode 100644 CONTENT/BT/GAUGE/JAK_GA.GIM create mode 100644 CONTENT/BT/GAUGE/L4GAUGE.INI create mode 100644 CONTENT/BT/GAUGE/LOKIHT.PCC create mode 100644 CONTENT/BT/GAUGE/LOKI_MR.PCC create mode 100644 CONTENT/BT/GAUGE/LRMCARRY.GIM create mode 100644 CONTENT/BT/GAUGE/MAD2HT.PCC create mode 100644 CONTENT/BT/GAUGE/MADHT.PCC create mode 100644 CONTENT/BT/GAUGE/MECHMOVR.GIM create mode 100644 CONTENT/BT/GAUGE/MRPAL.PCC create mode 100644 CONTENT/BT/GAUGE/MSLG_GA.GIM create mode 100644 CONTENT/BT/GAUGE/MSLR_GA.GIM create mode 100644 CONTENT/BT/GAUGE/PDSH_GA.GIM create mode 100644 CONTENT/BT/GAUGE/PGN_GA.GIM create mode 100644 CONTENT/BT/GAUGE/QAFC10.PCC create mode 100644 CONTENT/BT/GAUGE/QAFC100.PCC create mode 100644 CONTENT/BT/GAUGE/QAFC25.PCC create mode 100644 CONTENT/BT/GAUGE/QAFC5.PCC create mode 100644 CONTENT/BT/GAUGE/QAFC50.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA0.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA1.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA2.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA23.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA24.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA25.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA26.PCC create mode 100644 CONTENT/BT/GAUGE/QAVA27.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH0.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH1.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH2.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH3.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH4.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH5.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH6.PCC create mode 100644 CONTENT/BT/GAUGE/QBLH7.PCC create mode 100644 CONTENT/BT/GAUGE/QCIRCLE.PCC create mode 100644 CONTENT/BT/GAUGE/QCIRCR.PCC create mode 100644 CONTENT/BT/GAUGE/QERLLAS.PCC create mode 100644 CONTENT/BT/GAUGE/QERMLAS.PCC create mode 100644 CONTENT/BT/GAUGE/QERPPC.PCC create mode 100644 CONTENT/BT/GAUGE/QERSLAS.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR0.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR1.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR2.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR3.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR4.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR5.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR6.PCC create mode 100644 CONTENT/BT/GAUGE/QFIR7.PCC create mode 100644 CONTENT/BT/GAUGE/QFIRI.PCC create mode 100644 CONTENT/BT/GAUGE/QGAUSS.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK0.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK1.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK2.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK3.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK4.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK5.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK6.PCC create mode 100644 CONTENT/BT/GAUGE/QJAK7.PCC create mode 100644 CONTENT/BT/GAUGE/QLBX10.PCC create mode 100644 CONTENT/BT/GAUGE/QLBX100.PCC create mode 100644 CONTENT/BT/GAUGE/QLBX25.PCC create mode 100644 CONTENT/BT/GAUGE/QLBX5.PCC create mode 100644 CONTENT/BT/GAUGE/QLBX50.PCC create mode 100644 CONTENT/BT/GAUGE/QLLAS.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK10.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK11.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK12.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK13.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK14.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK15.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK16.PCC create mode 100644 CONTENT/BT/GAUGE/QLOK17.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI0.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI1.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI2.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI3.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI4.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI5.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI6.PCC create mode 100644 CONTENT/BT/GAUGE/QLOKI7.PCC create mode 100644 CONTENT/BT/GAUGE/QLRM10.PCC create mode 100644 CONTENT/BT/GAUGE/QLRM15.PCC create mode 100644 CONTENT/BT/GAUGE/QLRM20.PCC create mode 100644 CONTENT/BT/GAUGE/QLRM5.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD0.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD1.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD10.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD11.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD12.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD13.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD14.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD15.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD16.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD17.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD2.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD20.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD21.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD22.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD23.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD24.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD25.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD26.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD27.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD3.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD4.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD5.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD6.PCC create mode 100644 CONTENT/BT/GAUGE/QMAD7.PCC create mode 100644 CONTENT/BT/GAUGE/QMG.PCC create mode 100644 CONTENT/BT/GAUGE/QMLAS.PCC create mode 100644 CONTENT/BT/GAUGE/QMYOMERS.PCC create mode 100644 CONTENT/BT/GAUGE/QNRK15.PCC create mode 100644 CONTENT/BT/GAUGE/QNRK5.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN0.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN1.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN2.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN3.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN4.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN5.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN6.PCC create mode 100644 CONTENT/BT/GAUGE/QOWEN7.PCC create mode 100644 CONTENT/BT/GAUGE/QPPC.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP0.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP1.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP2.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP3.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP4.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP5.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP6.PCC create mode 100644 CONTENT/BT/GAUGE/QRAP7.PCC create mode 100644 CONTENT/BT/GAUGE/QRAPI.PCC create mode 100644 CONTENT/BT/GAUGE/QSENSORS.PCC create mode 100644 CONTENT/BT/GAUGE/QSLAS.PCC create mode 100644 CONTENT/BT/GAUGE/QSLASER.PCC create mode 100644 CONTENT/BT/GAUGE/QSRM2.PCC create mode 100644 CONTENT/BT/GAUGE/QSRM4.PCC create mode 100644 CONTENT/BT/GAUGE/QSRM6.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI0.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI1.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI2.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI3.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI4.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI5.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI6.PCC create mode 100644 CONTENT/BT/GAUGE/QSTI7.PCC create mode 100644 CONTENT/BT/GAUGE/QSTII.PCC create mode 100644 CONTENT/BT/GAUGE/QSTRK2.PCC create mode 100644 CONTENT/BT/GAUGE/QSTRK4.PCC create mode 100644 CONTENT/BT/GAUGE/QSTRK6.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN0.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN1.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN2.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN3.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN4.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN5.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN6.PCC create mode 100644 CONTENT/BT/GAUGE/QSUN7.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR0.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR1.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR2.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR3.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR4.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR5.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR6.PCC create mode 100644 CONTENT/BT/GAUGE/QTHOR7.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL10.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL11.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL12.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL13.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL14.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL15.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL16.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL17.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL20.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL21.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL22.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL23.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL24.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL25.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL26.PCC create mode 100644 CONTENT/BT/GAUGE/QVUL27.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT0.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT1.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT2.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT3.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT4.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT5.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT6.PCC create mode 100644 CONTENT/BT/GAUGE/QVULT7.PCC create mode 100644 CONTENT/BT/GAUGE/RAP_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RESULT2.TXT create mode 100644 CONTENT/BT/GAUGE/RIVET_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RK1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RK2_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RK3_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RK4_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RK5_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RK6_GA.GIM create mode 100644 CONTENT/BT/GAUGE/RK7_GA.GIM create mode 100644 CONTENT/BT/GAUGE/ROMMEL.GIM create mode 100644 CONTENT/BT/GAUGE/SB1E_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SB1N_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SB1S_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SB1W_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SB3S_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SDSPMOD.PCC create mode 100644 CONTENT/BT/GAUGE/SEMI.GIM create mode 100644 CONTENT/BT/GAUGE/SEMIRIG.GIM create mode 100644 CONTENT/BT/GAUGE/SGEN1.PCC create mode 100644 CONTENT/BT/GAUGE/SGEN2.PCC create mode 100644 CONTENT/BT/GAUGE/SGEN3.PCC create mode 100644 CONTENT/BT/GAUGE/SGEN4.PCC create mode 100644 CONTENT/BT/GAUGE/SGEN5.PCC create mode 100644 CONTENT/BT/GAUGE/SGEN6.PCC create mode 100644 CONTENT/BT/GAUGE/SGENA.PCC create mode 100644 CONTENT/BT/GAUGE/SGENB.PCC create mode 100644 CONTENT/BT/GAUGE/SGENBG.PCC create mode 100644 CONTENT/BT/GAUGE/SGENC.PCC create mode 100644 CONTENT/BT/GAUGE/SGEND.PCC create mode 100644 CONTENT/BT/GAUGE/SGENLEAK.PCC create mode 100644 CONTENT/BT/GAUGE/SGENTEMP.PCC create mode 100644 CONTENT/BT/GAUGE/SGENVOLT.PCC create mode 100644 CONTENT/BT/GAUGE/SIZUMIN.PCC create mode 100644 CONTENT/BT/GAUGE/SIZUMOUT.PCC create mode 100644 CONTENT/BT/GAUGE/SMLFONT.PCC create mode 100644 CONTENT/BT/GAUGE/SND2DAMA.PCC create mode 100644 CONTENT/BT/GAUGE/SND2_MR.PCC create mode 100644 CONTENT/BT/GAUGE/SR1E_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SR1N_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SR1S_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SR1W_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SRMCARRY.GIM create mode 100644 CONTENT/BT/GAUGE/ST1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/STB_GA.GIM create mode 100644 CONTENT/BT/GAUGE/STF_GA.GIM create mode 100644 CONTENT/BT/GAUGE/STH_GA.GIM create mode 100644 CONTENT/BT/GAUGE/STICRIT.PCC create mode 100644 CONTENT/BT/GAUGE/STIHEAT.PCC create mode 100644 CONTENT/BT/GAUGE/STIHT.PCC create mode 100644 CONTENT/BT/GAUGE/STIMFD.PCC create mode 100644 CONTENT/BT/GAUGE/STI_GA.GIM create mode 100644 CONTENT/BT/GAUGE/STRIKER.GIM create mode 100644 CONTENT/BT/GAUGE/STS_GA.GIM create mode 100644 CONTENT/BT/GAUGE/STT_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SVISION.PCC create mode 100644 CONTENT/BT/GAUGE/SW1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SW2_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SW3_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SW4_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SW5_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SW6_GA.GIM create mode 100644 CONTENT/BT/GAUGE/SWIFTWND.GIM create mode 100644 CONTENT/BT/GAUGE/THOR.PCX create mode 100644 CONTENT/BT/GAUGE/THORHT.PCC create mode 100644 CONTENT/BT/GAUGE/THOR_GA.GIM create mode 100644 CONTENT/BT/GAUGE/TINYFONT.PCC create mode 100644 CONTENT/BT/GAUGE/TMC1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/TMC2_GA.GIM create mode 100644 CONTENT/BT/GAUGE/TNT_GA.GIM create mode 100644 CONTENT/BT/GAUGE/TREE_GA.GIM create mode 100644 CONTENT/BT/GAUGE/TWR_GA.GIM create mode 100644 CONTENT/BT/GAUGE/VULTHT.PCC create mode 100644 CONTENT/BT/GAUGE/WALL1_GA.GIM create mode 100644 CONTENT/BT/GAUGE/WALL2_GA.GIM create mode 100644 CONTENT/BT/GAUGE/WALL3_GA.GIM create mode 100644 CONTENT/BT/GAUGE/WST_GA.GIM create mode 100644 CONTENT/BT/GAUGE/X_GA.GIM create mode 100644 CONTENT/BT/GO.BAT create mode 100644 CONTENT/BT/JOYSTICK.INI create mode 100644 CONTENT/BT/LAST.EGG create mode 100644 CONTENT/BT/MAKEEGG.BAK create mode 100644 CONTENT/BT/MAKEEGG.BAT create mode 100644 CONTENT/BT/MAPS/ADROP.MAP create mode 100644 CONTENT/BT/MAPS/ALL.ZNE create mode 100644 CONTENT/BT/MAPS/ARENA1.MAP create mode 100644 CONTENT/BT/MAPS/ARENA2.MAP create mode 100644 CONTENT/BT/MAPS/ARTRUCBU.MAP create mode 100644 CONTENT/BT/MAPS/ARTRUCKS.MAP create mode 100644 CONTENT/BT/MAPS/BLANK.MAP create mode 100644 CONTENT/BT/MAPS/DES.MAP create mode 100644 CONTENT/BT/MAPS/PDROP.MAP create mode 100644 CONTENT/BT/MAPS/POL3SFX.MAP create mode 100644 CONTENT/BT/MAPS/POL4DROP.MAP create mode 100644 CONTENT/BT/MAPS/POL4SFX.MAP create mode 100644 CONTENT/BT/MAPS/RAVBU.MAP create mode 100644 CONTENT/BT/MAPS/RAVTEST.SCN create mode 100644 CONTENT/BT/MAPS/TEST.MAP create mode 100644 CONTENT/BT/MAPS/TEST1.MAP create mode 100644 CONTENT/BT/MAPS/TEST5.MAP create mode 100644 CONTENT/BT/MENU.BAT create mode 100644 CONTENT/BT/MODELS/AB01.MOD create mode 100644 CONTENT/BT/MODELS/AB02.MOD create mode 100644 CONTENT/BT/MODELS/AB03.MOD create mode 100644 CONTENT/BT/MODELS/AB04.MOD create mode 100644 CONTENT/BT/MODELS/AB05.MOD create mode 100644 CONTENT/BT/MODELS/AB06.MOD create mode 100644 CONTENT/BT/MODELS/AB06D.MOD create mode 100644 CONTENT/BT/MODELS/AB07.MOD create mode 100644 CONTENT/BT/MODELS/AB08.MOD create mode 100644 CONTENT/BT/MODELS/AB09.MOD create mode 100644 CONTENT/BT/MODELS/AB09D.MOD create mode 100644 CONTENT/BT/MODELS/AB10.MOD create mode 100644 CONTENT/BT/MODELS/AB10D.MOD create mode 100644 CONTENT/BT/MODELS/ACT01.MOD create mode 100644 CONTENT/BT/MODELS/ACT02.MOD create mode 100644 CONTENT/BT/MODELS/ACT03.MOD create mode 100644 CONTENT/BT/MODELS/ACT04.MOD create mode 100644 CONTENT/BT/MODELS/ACT05.MOD create mode 100644 CONTENT/BT/MODELS/AD01.MOD create mode 100644 CONTENT/BT/MODELS/ADSUP1.MOD create mode 100644 CONTENT/BT/MODELS/ADSUP2.MOD create mode 100644 CONTENT/BT/MODELS/ADWLK1.MOD create mode 100644 CONTENT/BT/MODELS/ADWLK2.MOD create mode 100644 CONTENT/BT/MODELS/ADWLK3.MOD create mode 100644 CONTENT/BT/MODELS/AFC100.SUB create mode 100644 CONTENT/BT/MODELS/AFC25.SUB create mode 100644 CONTENT/BT/MODELS/AFC5.SUB create mode 100644 CONTENT/BT/MODELS/AFC50.SUB create mode 100644 CONTENT/BT/MODELS/AFLOOR.MOD create mode 100644 CONTENT/BT/MODELS/AMAFC100.SUB create mode 100644 CONTENT/BT/MODELS/AMBSSDOR.MOD create mode 100644 CONTENT/BT/MODELS/AMLBX100.SUB create mode 100644 CONTENT/BT/MODELS/AMMAFC25.SUB create mode 100644 CONTENT/BT/MODELS/AMMAFC5.SUB create mode 100644 CONTENT/BT/MODELS/AMMAFC50.SUB create mode 100644 CONTENT/BT/MODELS/AMMLBX25.SUB create mode 100644 CONTENT/BT/MODELS/AMMLBX5.SUB create mode 100644 CONTENT/BT/MODELS/AMMLBX50.SUB create mode 100644 CONTENT/BT/MODELS/AMMLRM10.SUB create mode 100644 CONTENT/BT/MODELS/AMMLRM15.SUB create mode 100644 CONTENT/BT/MODELS/AMMLRM20.SUB create mode 100644 CONTENT/BT/MODELS/AMMLRM5.SUB create mode 100644 CONTENT/BT/MODELS/AMMNRK10.SUB create mode 100644 CONTENT/BT/MODELS/AMMNRK15.SUB create mode 100644 CONTENT/BT/MODELS/AMMNRK20.SUB create mode 100644 CONTENT/BT/MODELS/AMMNRK5.SUB create mode 100644 CONTENT/BT/MODELS/AMMOAC.SUB create mode 100644 CONTENT/BT/MODELS/AMMOAC10.SUB create mode 100644 CONTENT/BT/MODELS/AMMOGAUS.SUB create mode 100644 CONTENT/BT/MODELS/AMMOMG.SUB create mode 100644 CONTENT/BT/MODELS/AMMSRM2.SUB create mode 100644 CONTENT/BT/MODELS/AMMSRM25.SUB create mode 100644 CONTENT/BT/MODELS/AMMSRM30.SUB create mode 100644 CONTENT/BT/MODELS/AMMSRM4.SUB create mode 100644 CONTENT/BT/MODELS/AMMSRM6.SUB create mode 100644 CONTENT/BT/MODELS/AMMSTRK2.SUB create mode 100644 CONTENT/BT/MODELS/AMMSTRK4.SUB create mode 100644 CONTENT/BT/MODELS/AMMSTRK6.SUB create mode 100644 CONTENT/BT/MODELS/APC.MOD create mode 100644 CONTENT/BT/MODELS/AR01.MOD create mode 100644 CONTENT/BT/MODELS/AR02.MOD create mode 100644 CONTENT/BT/MODELS/AR03.MOD create mode 100644 CONTENT/BT/MODELS/AR04.MOD create mode 100644 CONTENT/BT/MODELS/AR05.MOD create mode 100644 CONTENT/BT/MODELS/ARBAN1.MOD create mode 100644 CONTENT/BT/MODELS/ARBAN2.MOD create mode 100644 CONTENT/BT/MODELS/ARBAN3.MOD create mode 100644 CONTENT/BT/MODELS/ARBAN4.MOD create mode 100644 CONTENT/BT/MODELS/ARBAN5.MOD create mode 100644 CONTENT/BT/MODELS/ARBAN6.MOD create mode 100644 CONTENT/BT/MODELS/ARCLD.MOD create mode 100644 CONTENT/BT/MODELS/ARENA.MOD create mode 100644 CONTENT/BT/MODELS/ARHORIZ.MOD create mode 100644 CONTENT/BT/MODELS/ARLID.MOD create mode 100644 CONTENT/BT/MODELS/ARMOR1.DMG create mode 100644 CONTENT/BT/MODELS/ARMRMOVR.MOD create mode 100644 CONTENT/BT/MODELS/ARWC.MOD create mode 100644 CONTENT/BT/MODELS/ATTACKER.MOD create mode 100644 CONTENT/BT/MODELS/AUDIO.BLD create mode 100644 CONTENT/BT/MODELS/AVA1.DMG create mode 100644 CONTENT/BT/MODELS/AVA1.MOD create mode 100644 CONTENT/BT/MODELS/AVA1.SUB create mode 100644 CONTENT/BT/MODELS/AVA1DEAD.MOD create mode 100644 CONTENT/BT/MODELS/AVA1DMG.EXP create mode 100644 CONTENT/BT/MODELS/AVA1DMG.TBL create mode 100644 CONTENT/BT/MODELS/AVA1L4.CTL create mode 100644 CONTENT/BT/MODELS/AVA1THR.CTL create mode 100644 CONTENT/BT/MODELS/AVA2.MOD create mode 100644 CONTENT/BT/MODELS/AVA2DEAD.MOD create mode 100644 CONTENT/BT/MODELS/AVA2DMG.EXP create mode 100644 CONTENT/BT/MODELS/AVA2THR.CTL create mode 100644 CONTENT/BT/MODELS/AVADEAD.MOD create mode 100644 CONTENT/BT/MODELS/AVADMG.EXP create mode 100644 CONTENT/BT/MODELS/AVAL4.CTL create mode 100644 CONTENT/BT/MODELS/AVATAR.DMG create mode 100644 CONTENT/BT/MODELS/AVATAR.MOD create mode 100644 CONTENT/BT/MODELS/AVATAR.SUB create mode 100644 CONTENT/BT/MODELS/AVATHR.CTL create mode 100644 CONTENT/BT/MODELS/AW01.MOD create mode 100644 CONTENT/BT/MODELS/AW02.MOD create mode 100644 CONTENT/BT/MODELS/AW03.MOD create mode 100644 CONTENT/BT/MODELS/AW04.MOD create mode 100644 CONTENT/BT/MODELS/AW05.MOD create mode 100644 CONTENT/BT/MODELS/AWBOX1.MOD create mode 100644 CONTENT/BT/MODELS/AWWLK1.MOD create mode 100644 CONTENT/BT/MODELS/BAC1.MOD create mode 100644 CONTENT/BT/MODELS/BAT.MOD create mode 100644 CONTENT/BT/MODELS/BAT.SUB create mode 100644 CONTENT/BT/MODELS/BATDMG.EXP create mode 100644 CONTENT/BT/MODELS/BATDMG.TBL create mode 100644 CONTENT/BT/MODELS/BATTHR.CTL create mode 100644 CONTENT/BT/MODELS/BCOR1.MOD create mode 100644 CONTENT/BT/MODELS/BCOR2.MOD create mode 100644 CONTENT/BT/MODELS/BDET1.MOD create mode 100644 CONTENT/BT/MODELS/BDET2.MOD create mode 100644 CONTENT/BT/MODELS/BDET3.MOD create mode 100644 CONTENT/BT/MODELS/BDET4.MOD create mode 100644 CONTENT/BT/MODELS/BDET6.MOD create mode 100644 CONTENT/BT/MODELS/BHK1.DMG create mode 100644 CONTENT/BT/MODELS/BHK1.MOD create mode 100644 CONTENT/BT/MODELS/BHK1.SUB create mode 100644 CONTENT/BT/MODELS/BHK1DEAD.MOD create mode 100644 CONTENT/BT/MODELS/BHK1DMG.EXP create mode 100644 CONTENT/BT/MODELS/BHK1DMG.TBL create mode 100644 CONTENT/BT/MODELS/BHK1L4.CTL create mode 100644 CONTENT/BT/MODELS/BHK1THR.CTL create mode 100644 CONTENT/BT/MODELS/BIGDEAD.MOD create mode 100644 CONTENT/BT/MODELS/BLD.MOD create mode 100644 CONTENT/BT/MODELS/BLD01.MOD create mode 100644 CONTENT/BT/MODELS/BLD02.MOD create mode 100644 CONTENT/BT/MODELS/BLD03.MOD create mode 100644 CONTENT/BT/MODELS/BLD04.MOD create mode 100644 CONTENT/BT/MODELS/BLD05.MOD create mode 100644 CONTENT/BT/MODELS/BLD06.MOD create mode 100644 CONTENT/BT/MODELS/BLD08.MOD create mode 100644 CONTENT/BT/MODELS/BLD20.MOD create mode 100644 CONTENT/BT/MODELS/BLD24.MOD create mode 100644 CONTENT/BT/MODELS/BLD26.MOD create mode 100644 CONTENT/BT/MODELS/BLD27.MOD create mode 100644 CONTENT/BT/MODELS/BLHDEAD.MOD create mode 100644 CONTENT/BT/MODELS/BLHDMG.EXP create mode 100644 CONTENT/BT/MODELS/BLHL4.CTL create mode 100644 CONTENT/BT/MODELS/BLHTHR.CTL create mode 100644 CONTENT/BT/MODELS/BLKHAWK.DMG create mode 100644 CONTENT/BT/MODELS/BLKHAWK.MOD create mode 100644 CONTENT/BT/MODELS/BLKHAWK.SUB create mode 100644 CONTENT/BT/MODELS/BLKJACK.MOD create mode 100644 CONTENT/BT/MODELS/BLKJACK.SUB create mode 100644 CONTENT/BT/MODELS/BNK.MOD create mode 100644 CONTENT/BT/MODELS/BPIP1.MOD create mode 100644 CONTENT/BT/MODELS/BULLDOG.MOD create mode 100644 CONTENT/BT/MODELS/BUTTEA.MOD create mode 100644 CONTENT/BT/MODELS/BUTTEB.MOD create mode 100644 CONTENT/BT/MODELS/BUTTEC.MOD create mode 100644 CONTENT/BT/MODELS/BUTTED.MOD create mode 100644 CONTENT/BT/MODELS/BUTTEE.MOD create mode 100644 CONTENT/BT/MODELS/BUTTEEU.MOD create mode 100644 CONTENT/BT/MODELS/BUTTEF.MOD create mode 100644 CONTENT/BT/MODELS/BWLK1.MOD create mode 100644 CONTENT/BT/MODELS/CAL.SUB create mode 100644 CONTENT/BT/MODELS/CALP.DMG create mode 100644 CONTENT/BT/MODELS/CALP.MOD create mode 100644 CONTENT/BT/MODELS/CALPB.MOD create mode 100644 CONTENT/BT/MODELS/CAMERA.MOD create mode 100644 CONTENT/BT/MODELS/CAMPOS.MOD create mode 100644 CONTENT/BT/MODELS/CANHIT.MOD create mode 100644 CONTENT/BT/MODELS/CANHITI.MOD create mode 100644 CONTENT/BT/MODELS/CB1.MOD create mode 100644 CONTENT/BT/MODELS/CLD.MOD create mode 100644 CONTENT/BT/MODELS/COMTRUCK.MOD create mode 100644 CONTENT/BT/MODELS/CONDENSR.SUB create mode 100644 CONTENT/BT/MODELS/CONVOY.MOD create mode 100644 CONTENT/BT/MODELS/COOLANT.MOD create mode 100644 CONTENT/BT/MODELS/CRT.MOD create mode 100644 CONTENT/BT/MODELS/CTARMAC.MOD create mode 100644 CONTENT/BT/MODELS/DAM1HIT.MOD create mode 100644 CONTENT/BT/MODELS/DAM1HITI.MOD create mode 100644 CONTENT/BT/MODELS/DAM2HIT.MOD create mode 100644 CONTENT/BT/MODELS/DAM2HITI.MOD create mode 100644 CONTENT/BT/MODELS/DAM3EXP.MOD create mode 100644 CONTENT/BT/MODELS/DAM3HIT.MOD create mode 100644 CONTENT/BT/MODELS/DAM3HITI.MOD create mode 100644 CONTENT/BT/MODELS/DAM4EXP.MOD create mode 100644 CONTENT/BT/MODELS/DAM4EXPI.MOD create mode 100644 CONTENT/BT/MODELS/DAM4HIT.MOD create mode 100644 CONTENT/BT/MODELS/DAM4HITI.MOD create mode 100644 CONTENT/BT/MODELS/DAVION.MOD create mode 100644 CONTENT/BT/MODELS/DECOY.MOD create mode 100644 CONTENT/BT/MODELS/DEFENDER.MOD create mode 100644 CONTENT/BT/MODELS/DESTHIT.MOD create mode 100644 CONTENT/BT/MODELS/DESTHITI.MOD create mode 100644 CONTENT/BT/MODELS/DFLTROLE.MOD create mode 100644 CONTENT/BT/MODELS/DG100.MOD create mode 100644 CONTENT/BT/MODELS/DG100A.MOD create mode 100644 CONTENT/BT/MODELS/DHILLG1.MOD create mode 100644 CONTENT/BT/MODELS/DHILLG2.MOD create mode 100644 CONTENT/BT/MODELS/DHILLG3.MOD create mode 100644 CONTENT/BT/MODELS/DISH.MOD create mode 100644 CONTENT/BT/MODELS/DMG.BLD create mode 100644 CONTENT/BT/MODELS/DOZER.MOD create mode 100644 CONTENT/BT/MODELS/DRESF.MOD create mode 100644 CONTENT/BT/MODELS/DSKY.MOD create mode 100644 CONTENT/BT/MODELS/DTARMAC.MOD create mode 100644 CONTENT/BT/MODELS/DUMB.MOD create mode 100644 CONTENT/BT/MODELS/DUMB2.SUB create mode 100644 CONTENT/BT/MODELS/DUMB4.SUB create mode 100644 CONTENT/BT/MODELS/DUMB6.SUB create mode 100644 CONTENT/BT/MODELS/ERLLASER.SUB create mode 100644 CONTENT/BT/MODELS/ERMLASER.SUB create mode 100644 CONTENT/BT/MODELS/ERPPC.SUB create mode 100644 CONTENT/BT/MODELS/ERSLASER.SUB create mode 100644 CONTENT/BT/MODELS/EXPLODE.MOD create mode 100644 CONTENT/BT/MODELS/EXPLODE.ONL create mode 100644 CONTENT/BT/MODELS/FD1.MOD create mode 100644 CONTENT/BT/MODELS/FD2.MOD create mode 100644 CONTENT/BT/MODELS/FD3.MOD create mode 100644 CONTENT/BT/MODELS/FD4.MOD create mode 100644 CONTENT/BT/MODELS/FIND.TXT create mode 100644 CONTENT/BT/MODELS/FIRDMG.EXP create mode 100644 CONTENT/BT/MODELS/FIRDMG.TBL create mode 100644 CONTENT/BT/MODELS/FIRSTRTR.MOD create mode 100644 CONTENT/BT/MODELS/FIRSTRTR.SUB create mode 100644 CONTENT/BT/MODELS/FIRTHR.CTL create mode 100644 CONTENT/BT/MODELS/FL1.MOD create mode 100644 CONTENT/BT/MODELS/FP0.MOD create mode 100644 CONTENT/BT/MODELS/FP0D.MOD create mode 100644 CONTENT/BT/MODELS/FP1.MOD create mode 100644 CONTENT/BT/MODELS/FP2.MOD create mode 100644 CONTENT/BT/MODELS/FP2D.MOD create mode 100644 CONTENT/BT/MODELS/FP3.MOD create mode 100644 CONTENT/BT/MODELS/FT1.MOD create mode 100644 CONTENT/BT/MODELS/FT2.MOD create mode 100644 CONTENT/BT/MODELS/GAUSSRFL.SUB create mode 100644 CONTENT/BT/MODELS/GD1.MOD create mode 100644 CONTENT/BT/MODELS/GD2.MOD create mode 100644 CONTENT/BT/MODELS/GD3.MOD create mode 100644 CONTENT/BT/MODELS/GD4.MOD create mode 100644 CONTENT/BT/MODELS/GD5.MOD create mode 100644 CONTENT/BT/MODELS/GENRATOR.SUB create mode 100644 CONTENT/BT/MODELS/GNDHIT.MOD create mode 100644 CONTENT/BT/MODELS/GNR.MOD create mode 100644 CONTENT/BT/MODELS/GRND100.MOD create mode 100644 CONTENT/BT/MODELS/GTARMAC.MOD create mode 100644 CONTENT/BT/MODELS/GYRO.SUB create mode 100644 CONTENT/BT/MODELS/HARASSER.MOD create mode 100644 CONTENT/BT/MODELS/HC1.MOD create mode 100644 CONTENT/BT/MODELS/HC2.MOD create mode 100644 CONTENT/BT/MODELS/HEATSNK.SUB create mode 100644 CONTENT/BT/MODELS/HILLA.MOD create mode 100644 CONTENT/BT/MODELS/HILLC.MOD create mode 100644 CONTENT/BT/MODELS/HILLG1.MOD create mode 100644 CONTENT/BT/MODELS/HILLG2.MOD create mode 100644 CONTENT/BT/MODELS/HILLG3.MOD create mode 100644 CONTENT/BT/MODELS/HL1.MOD create mode 100644 CONTENT/BT/MODELS/HL2.MOD create mode 100644 CONTENT/BT/MODELS/HN1.MOD create mode 100644 CONTENT/BT/MODELS/HOSTAGE.MOD create mode 100644 CONTENT/BT/MODELS/HUD.SUB create mode 100644 CONTENT/BT/MODELS/HUMMER.MOD create mode 100644 CONTENT/BT/MODELS/HUT.MOD create mode 100644 CONTENT/BT/MODELS/HWZ.MOD create mode 100644 CONTENT/BT/MODELS/ICONBLH.MOD create mode 100644 CONTENT/BT/MODELS/ICONJAK.MOD create mode 100644 CONTENT/BT/MODELS/ICONLOK.MOD create mode 100644 CONTENT/BT/MODELS/ICONOWN.MOD create mode 100644 CONTENT/BT/MODELS/ICONTHR.DMG create mode 100644 CONTENT/BT/MODELS/ICONTHR.MOD create mode 100644 CONTENT/BT/MODELS/ICONTHRD.MOD create mode 100644 CONTENT/BT/MODELS/ICONVUL.DMG create mode 100644 CONTENT/BT/MODELS/ICONVUL.MOD create mode 100644 CONTENT/BT/MODELS/JAKDMG.EXP create mode 100644 CONTENT/BT/MODELS/JAKDMG.TBL create mode 100644 CONTENT/BT/MODELS/JAKTHR.CTL create mode 100644 CONTENT/BT/MODELS/KURITA.MOD create mode 100644 CONTENT/BT/MODELS/LASER.MOD create mode 100644 CONTENT/BT/MODELS/LLASER.SUB create mode 100644 CONTENT/BT/MODELS/LNTRK1.MOD create mode 100644 CONTENT/BT/MODELS/LO1DMG.TBL create mode 100644 CONTENT/BT/MODELS/LOK1.DMG create mode 100644 CONTENT/BT/MODELS/LOK1.MOD create mode 100644 CONTENT/BT/MODELS/LOK1.SUB create mode 100644 CONTENT/BT/MODELS/LOK1DMG.EXP create mode 100644 CONTENT/BT/MODELS/LOK1DMG.TBL create mode 100644 CONTENT/BT/MODELS/LOK1L4.CTL create mode 100644 CONTENT/BT/MODELS/LOK1THR.CTL create mode 100644 CONTENT/BT/MODELS/LOK2.DMG create mode 100644 CONTENT/BT/MODELS/LOK2.MOD create mode 100644 CONTENT/BT/MODELS/LOK2.SUB create mode 100644 CONTENT/BT/MODELS/LOK2DMG.EXP create mode 100644 CONTENT/BT/MODELS/LOK2L4.CTL create mode 100644 CONTENT/BT/MODELS/LOK2THR.CTL create mode 100644 CONTENT/BT/MODELS/LOKDEAD.MOD create mode 100644 CONTENT/BT/MODELS/LOKDMG.EXP create mode 100644 CONTENT/BT/MODELS/LOKI.MOD create mode 100644 CONTENT/BT/MODELS/LOKI.SUB create mode 100644 CONTENT/BT/MODELS/LOKI1.MOD create mode 100644 CONTENT/BT/MODELS/LOKI1.SUB create mode 100644 CONTENT/BT/MODELS/LOKL4.CTL create mode 100644 CONTENT/BT/MODELS/LOKTHR.CTL create mode 100644 CONTENT/BT/MODELS/LRM.MOD create mode 100644 CONTENT/BT/MODELS/LRM10.SUB create mode 100644 CONTENT/BT/MODELS/LRM15.SUB create mode 100644 CONTENT/BT/MODELS/LRM20.SUB create mode 100644 CONTENT/BT/MODELS/LRM5.SUB create mode 100644 CONTENT/BT/MODELS/LRMCARRY.MOD create mode 100644 CONTENT/BT/MODELS/LRMLANCH.SUB create mode 100644 CONTENT/BT/MODELS/LZRHIT.MOD create mode 100644 CONTENT/BT/MODELS/LZRHITI.MOD create mode 100644 CONTENT/BT/MODELS/MACHGUN.SUB create mode 100644 CONTENT/BT/MODELS/MAD.DMG create mode 100644 CONTENT/BT/MODELS/MAD1.DMG create mode 100644 CONTENT/BT/MODELS/MAD1.MOD create mode 100644 CONTENT/BT/MODELS/MAD1.SUB create mode 100644 CONTENT/BT/MODELS/MAD1DMG.EXP create mode 100644 CONTENT/BT/MODELS/MAD1DMG.TBL create mode 100644 CONTENT/BT/MODELS/MAD1L4.CTL create mode 100644 CONTENT/BT/MODELS/MAD1THR.CTL create mode 100644 CONTENT/BT/MODELS/MAD2.DMG create mode 100644 CONTENT/BT/MODELS/MAD2.MOD create mode 100644 CONTENT/BT/MODELS/MAD2.SUB create mode 100644 CONTENT/BT/MODELS/MAD2DMG.EXP create mode 100644 CONTENT/BT/MODELS/MAD2L4.CTL create mode 100644 CONTENT/BT/MODELS/MAD2THR.CTL create mode 100644 CONTENT/BT/MODELS/MADCAT.DMG create mode 100644 CONTENT/BT/MODELS/MADCAT.MOD create mode 100644 CONTENT/BT/MODELS/MADCAT.SUB create mode 100644 CONTENT/BT/MODELS/MADDEAD.MOD create mode 100644 CONTENT/BT/MODELS/MADDMG.EXP create mode 100644 CONTENT/BT/MODELS/MADL4.CTL create mode 100644 CONTENT/BT/MODELS/MADTHR.CTL create mode 100644 CONTENT/BT/MODELS/MAJHIT.MOD create mode 100644 CONTENT/BT/MODELS/MECHALRM.MOD create mode 100644 CONTENT/BT/MODELS/MECHDEAD.MOD create mode 100644 CONTENT/BT/MODELS/MECHMOVR.MOD create mode 100644 CONTENT/BT/MODELS/MED.DMG create mode 100644 CONTENT/BT/MODELS/MEDDEAD.MOD create mode 100644 CONTENT/BT/MODELS/MGHIT.MOD create mode 100644 CONTENT/BT/MODELS/MGHITI.MOD create mode 100644 CONTENT/BT/MODELS/MINHIT.MOD create mode 100644 CONTENT/BT/MODELS/MLASER.SUB create mode 100644 CONTENT/BT/MODELS/MSL.DMG create mode 100644 CONTENT/BT/MODELS/MSL.MOD create mode 100644 CONTENT/BT/MODELS/MSLBASE.MOD create mode 100644 CONTENT/BT/MODELS/MSLDEAD.MOD create mode 100644 CONTENT/BT/MODELS/MSLG.MOD create mode 100644 CONTENT/BT/MODELS/MSLH.MOD create mode 100644 CONTENT/BT/MODELS/MSLHIT.MOD create mode 100644 CONTENT/BT/MODELS/MSLHITI.MOD create mode 100644 CONTENT/BT/MODELS/MSLR.DMG create mode 100644 CONTENT/BT/MODELS/MSLR.MOD create mode 100644 CONTENT/BT/MODELS/MSLRB.MOD create mode 100644 CONTENT/BT/MODELS/MSLROAD1.MOD create mode 100644 CONTENT/BT/MODELS/MYOMERS.SUB create mode 100644 CONTENT/BT/MODELS/NORETURN.MOD create mode 100644 CONTENT/BT/MODELS/NRK.MOD create mode 100644 CONTENT/BT/MODELS/NRK10.SUB create mode 100644 CONTENT/BT/MODELS/NRK15.SUB create mode 100644 CONTENT/BT/MODELS/NRK20.SUB create mode 100644 CONTENT/BT/MODELS/NRK5.SUB create mode 100644 CONTENT/BT/MODELS/NTR.MOD create mode 100644 CONTENT/BT/MODELS/OLDCON.SUB create mode 100644 CONTENT/BT/MODELS/OLDGEN.SUB create mode 100644 CONTENT/BT/MODELS/OLDLOKI.SUB create mode 100644 CONTENT/BT/MODELS/OWENS.DMG create mode 100644 CONTENT/BT/MODELS/OWENS.MOD create mode 100644 CONTENT/BT/MODELS/OWENS.SUB create mode 100644 CONTENT/BT/MODELS/OWN1.DMG create mode 100644 CONTENT/BT/MODELS/OWN1.MOD create mode 100644 CONTENT/BT/MODELS/OWN1.SUB create mode 100644 CONTENT/BT/MODELS/OWN1DMG.EXP create mode 100644 CONTENT/BT/MODELS/OWN1DMG.TBL create mode 100644 CONTENT/BT/MODELS/OWN1L4.CTL create mode 100644 CONTENT/BT/MODELS/OWN1THR.CTL create mode 100644 CONTENT/BT/MODELS/OWNDEAD.MOD create mode 100644 CONTENT/BT/MODELS/OWNDMG.EXP create mode 100644 CONTENT/BT/MODELS/OWNL4.CTL create mode 100644 CONTENT/BT/MODELS/OWNTHR.CTL create mode 100644 CONTENT/BT/MODELS/PDSH.MOD create mode 100644 CONTENT/BT/MODELS/PGN.DMG create mode 100644 CONTENT/BT/MODELS/PGN.MOD create mode 100644 CONTENT/BT/MODELS/PLAYER.MOD create mode 100644 CONTENT/BT/MODELS/PLIT.MOD create mode 100644 CONTENT/BT/MODELS/PPC.SUB create mode 100644 CONTENT/BT/MODELS/PPCHIT.MOD create mode 100644 CONTENT/BT/MODELS/PPCHITI.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE1.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE2.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE3.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE4.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE5.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE6.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE7.MOD create mode 100644 CONTENT/BT/MODELS/PROFILE8.MOD create mode 100644 CONTENT/BT/MODELS/PROJTILE.MOD create mode 100644 CONTENT/BT/MODELS/PWIN1.MOD create mode 100644 CONTENT/BT/MODELS/PWIN2.MOD create mode 100644 CONTENT/BT/MODELS/PWIN3.MOD create mode 100644 CONTENT/BT/MODELS/PWIN4.MOD create mode 100644 CONTENT/BT/MODELS/PWIN5.MOD create mode 100644 CONTENT/BT/MODELS/PWIN6.MOD create mode 100644 CONTENT/BT/MODELS/PWIN7.MOD create mode 100644 CONTENT/BT/MODELS/PWIN8.MOD create mode 100644 CONTENT/BT/MODELS/RAPDEAD.MOD create mode 100644 CONTENT/BT/MODELS/RAPDMG.EXP create mode 100644 CONTENT/BT/MODELS/RAPDMG.TBL create mode 100644 CONTENT/BT/MODELS/RAPTHR.CTL create mode 100644 CONTENT/BT/MODELS/RAPTOR.MOD create mode 100644 CONTENT/BT/MODELS/RAPTOR.SUB create mode 100644 CONTENT/BT/MODELS/RAVFLOOR.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET1.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET2.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET3.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET4.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET5.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET6.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET7.MOD create mode 100644 CONTENT/BT/MODELS/RAVINET8.MOD create mode 100644 CONTENT/BT/MODELS/RAVWIN.MOD create mode 100644 CONTENT/BT/MODELS/RB1.MOD create mode 100644 CONTENT/BT/MODELS/RB2.MOD create mode 100644 CONTENT/BT/MODELS/RB3.MOD create mode 100644 CONTENT/BT/MODELS/RB4.MOD create mode 100644 CONTENT/BT/MODELS/RB5.MOD create mode 100644 CONTENT/BT/MODELS/RB6.MOD create mode 100644 CONTENT/BT/MODELS/RD1.MOD create mode 100644 CONTENT/BT/MODELS/RD2.MOD create mode 100644 CONTENT/BT/MODELS/RESERVE.SUB create mode 100644 CONTENT/BT/MODELS/RESULT.TXT create mode 100644 CONTENT/BT/MODELS/RESULT2.TXT create mode 100644 CONTENT/BT/MODELS/RK1.MOD create mode 100644 CONTENT/BT/MODELS/RK2.MOD create mode 100644 CONTENT/BT/MODELS/RK3.MOD create mode 100644 CONTENT/BT/MODELS/RK4.MOD create mode 100644 CONTENT/BT/MODELS/RK5.MOD create mode 100644 CONTENT/BT/MODELS/RK6.MOD create mode 100644 CONTENT/BT/MODELS/RK7.MOD create mode 100644 CONTENT/BT/MODELS/ROMMEL.MOD create mode 100644 CONTENT/BT/MODELS/RWD.MOD create mode 100644 CONTENT/BT/MODELS/RWIN1.MOD create mode 100644 CONTENT/BT/MODELS/SAW.MOD create mode 100644 CONTENT/BT/MODELS/SB1.MOD create mode 100644 CONTENT/BT/MODELS/SB1B.MOD create mode 100644 CONTENT/BT/MODELS/SB1C.MOD create mode 100644 CONTENT/BT/MODELS/SB1D.MOD create mode 100644 CONTENT/BT/MODELS/SB1E.MOD create mode 100644 CONTENT/BT/MODELS/SB1N.MOD create mode 100644 CONTENT/BT/MODELS/SB1S.MOD create mode 100644 CONTENT/BT/MODELS/SB1W.MOD create mode 100644 CONTENT/BT/MODELS/SB2.MOD create mode 100644 CONTENT/BT/MODELS/SB2B.MOD create mode 100644 CONTENT/BT/MODELS/SB2C.MOD create mode 100644 CONTENT/BT/MODELS/SB2D.MOD create mode 100644 CONTENT/BT/MODELS/SB2E.MOD create mode 100644 CONTENT/BT/MODELS/SB2N.MOD create mode 100644 CONTENT/BT/MODELS/SB2S.MOD create mode 100644 CONTENT/BT/MODELS/SB2W.MOD create mode 100644 CONTENT/BT/MODELS/SB3E.MOD create mode 100644 CONTENT/BT/MODELS/SB3N.MOD create mode 100644 CONTENT/BT/MODELS/SB3S.MOD create mode 100644 CONTENT/BT/MODELS/SB3W.MOD create mode 100644 CONTENT/BT/MODELS/SB4E.MOD create mode 100644 CONTENT/BT/MODELS/SB4N.MOD create mode 100644 CONTENT/BT/MODELS/SB4S.MOD create mode 100644 CONTENT/BT/MODELS/SB4W.MOD create mode 100644 CONTENT/BT/MODELS/SEMI.MOD create mode 100644 CONTENT/BT/MODELS/SEMIRIG.MOD create mode 100644 CONTENT/BT/MODELS/SENSOR.SUB create mode 100644 CONTENT/BT/MODELS/SKY.MOD create mode 100644 CONTENT/BT/MODELS/SL2.MOD create mode 100644 CONTENT/BT/MODELS/SLASER.SUB create mode 100644 CONTENT/BT/MODELS/SLT.MOD create mode 100644 CONTENT/BT/MODELS/SML.DMG create mode 100644 CONTENT/BT/MODELS/SMLDEAD.MOD create mode 100644 CONTENT/BT/MODELS/SN1.MOD create mode 100644 CONTENT/BT/MODELS/SN2.MOD create mode 100644 CONTENT/BT/MODELS/SN4.MOD create mode 100644 CONTENT/BT/MODELS/SND1.DMG create mode 100644 CONTENT/BT/MODELS/SND1.MOD create mode 100644 CONTENT/BT/MODELS/SND1.SUB create mode 100644 CONTENT/BT/MODELS/SND1DMG.EXP create mode 100644 CONTENT/BT/MODELS/SND1DMG.TBL create mode 100644 CONTENT/BT/MODELS/SND1L4.CTL create mode 100644 CONTENT/BT/MODELS/SND1THR.CTL create mode 100644 CONTENT/BT/MODELS/SND2.MOD create mode 100644 CONTENT/BT/MODELS/SND2.SUB create mode 100644 CONTENT/BT/MODELS/SND2DMG.EXP create mode 100644 CONTENT/BT/MODELS/SND2THR.CTL create mode 100644 CONTENT/BT/MODELS/SNDDEAD.MOD create mode 100644 CONTENT/BT/MODELS/SNDDMG.EXP create mode 100644 CONTENT/BT/MODELS/SNDL4.CTL create mode 100644 CONTENT/BT/MODELS/SNDTHR.CTL create mode 100644 CONTENT/BT/MODELS/SNH.MOD create mode 100644 CONTENT/BT/MODELS/SNTK1.MOD create mode 100644 CONTENT/BT/MODELS/SR1E.MOD create mode 100644 CONTENT/BT/MODELS/SR1N.MOD create mode 100644 CONTENT/BT/MODELS/SR1S.MOD create mode 100644 CONTENT/BT/MODELS/SR1W.MOD create mode 100644 CONTENT/BT/MODELS/SRC1NE.MOD create mode 100644 CONTENT/BT/MODELS/SRC1NW.MOD create mode 100644 CONTENT/BT/MODELS/SRC1SE.MOD create mode 100644 CONTENT/BT/MODELS/SRC1SW.MOD create mode 100644 CONTENT/BT/MODELS/SRCHLITE.SUB create mode 100644 CONTENT/BT/MODELS/SRM.MOD create mode 100644 CONTENT/BT/MODELS/SRM2.SUB create mode 100644 CONTENT/BT/MODELS/SRM4.SUB create mode 100644 CONTENT/BT/MODELS/SRM6.SUB create mode 100644 CONTENT/BT/MODELS/SRMCARRY.MOD create mode 100644 CONTENT/BT/MODELS/ST1.MOD create mode 100644 CONTENT/BT/MODELS/STATE.RST create mode 100644 CONTENT/BT/MODELS/STB.MOD create mode 100644 CONTENT/BT/MODELS/STEPHIT.MOD create mode 100644 CONTENT/BT/MODELS/STF.MOD create mode 100644 CONTENT/BT/MODELS/STH.MOD create mode 100644 CONTENT/BT/MODELS/STIDEAD.MOD create mode 100644 CONTENT/BT/MODELS/STIDMG.EXP create mode 100644 CONTENT/BT/MODELS/STIDMG.TBL create mode 100644 CONTENT/BT/MODELS/STITHR.CTL create mode 100644 CONTENT/BT/MODELS/STRIDER.MOD create mode 100644 CONTENT/BT/MODELS/STRIDER.SUB create mode 100644 CONTENT/BT/MODELS/STRIKER.MOD create mode 100644 CONTENT/BT/MODELS/STRK.MOD create mode 100644 CONTENT/BT/MODELS/STRK2.SUB create mode 100644 CONTENT/BT/MODELS/STRK4.SUB create mode 100644 CONTENT/BT/MODELS/STRK6.SUB create mode 100644 CONTENT/BT/MODELS/STS.MOD create mode 100644 CONTENT/BT/MODELS/STT.MOD create mode 100644 CONTENT/BT/MODELS/SUB.BLD create mode 100644 CONTENT/BT/MODELS/SUN1.SUB create mode 100644 CONTENT/BT/MODELS/SUNDER.DMG create mode 100644 CONTENT/BT/MODELS/SUNDER.MOD create mode 100644 CONTENT/BT/MODELS/SUNDER.SUB create mode 100644 CONTENT/BT/MODELS/SV2.MOD create mode 100644 CONTENT/BT/MODELS/SV2B.MOD create mode 100644 CONTENT/BT/MODELS/SV2C.MOD create mode 100644 CONTENT/BT/MODELS/SV2D.MOD create mode 100644 CONTENT/BT/MODELS/SV3.MOD create mode 100644 CONTENT/BT/MODELS/SV3B.MOD create mode 100644 CONTENT/BT/MODELS/SV3C.MOD create mode 100644 CONTENT/BT/MODELS/SV3D.MOD create mode 100644 CONTENT/BT/MODELS/SW1.MOD create mode 100644 CONTENT/BT/MODELS/SW2.MOD create mode 100644 CONTENT/BT/MODELS/SW3.MOD create mode 100644 CONTENT/BT/MODELS/SW4.MOD create mode 100644 CONTENT/BT/MODELS/SW5.MOD create mode 100644 CONTENT/BT/MODELS/SW6.MOD create mode 100644 CONTENT/BT/MODELS/SWIFTWND.MOD create mode 100644 CONTENT/BT/MODELS/TEST.TXT create mode 100644 CONTENT/BT/MODELS/TEXT.TXT create mode 100644 CONTENT/BT/MODELS/THERMAL.SUB create mode 100644 CONTENT/BT/MODELS/THOR.DMG create mode 100644 CONTENT/BT/MODELS/THOR.MOD create mode 100644 CONTENT/BT/MODELS/THOR.SUB create mode 100644 CONTENT/BT/MODELS/THR.DMG create mode 100644 CONTENT/BT/MODELS/THR1.DMG create mode 100644 CONTENT/BT/MODELS/THR1.MOD create mode 100644 CONTENT/BT/MODELS/THR1.SUB create mode 100644 CONTENT/BT/MODELS/THR1DEAD.MOD create mode 100644 CONTENT/BT/MODELS/THR1DMG.EXP create mode 100644 CONTENT/BT/MODELS/THR1DMG.TBL create mode 100644 CONTENT/BT/MODELS/THR1L4.CTL create mode 100644 CONTENT/BT/MODELS/THR1THR.CTL create mode 100644 CONTENT/BT/MODELS/THR6.MOD create mode 100644 CONTENT/BT/MODELS/THR6DEAD.MOD create mode 100644 CONTENT/BT/MODELS/THR6DMG.EXP create mode 100644 CONTENT/BT/MODELS/THR6THR.CTL create mode 100644 CONTENT/BT/MODELS/THRCTL.BLD create mode 100644 CONTENT/BT/MODELS/THRDEAD.MOD create mode 100644 CONTENT/BT/MODELS/THRDMG.EXP create mode 100644 CONTENT/BT/MODELS/THRDMGRD.EXP create mode 100644 CONTENT/BT/MODELS/THRL4.CTL create mode 100644 CONTENT/BT/MODELS/THRTHR.CTL create mode 100644 CONTENT/BT/MODELS/TK1.MOD create mode 100644 CONTENT/BT/MODELS/TM1.MOD create mode 100644 CONTENT/BT/MODELS/TM2.MOD create mode 100644 CONTENT/BT/MODELS/TMC1.MOD create mode 100644 CONTENT/BT/MODELS/TMC2.MOD create mode 100644 CONTENT/BT/MODELS/TMC3.MOD create mode 100644 CONTENT/BT/MODELS/TMC4.MOD create mode 100644 CONTENT/BT/MODELS/TMC5.MOD create mode 100644 CONTENT/BT/MODELS/TMC6.MOD create mode 100644 CONTENT/BT/MODELS/TMC7.MOD create mode 100644 CONTENT/BT/MODELS/TMC8.MOD create mode 100644 CONTENT/BT/MODELS/TNT.MOD create mode 100644 CONTENT/BT/MODELS/TORSO.SUB create mode 100644 CONTENT/BT/MODELS/TORSOLMT.SUB create mode 100644 CONTENT/BT/MODELS/TREE.MOD create mode 100644 CONTENT/BT/MODELS/TRK.DMG create mode 100644 CONTENT/BT/MODELS/TRK1.MOD create mode 100644 CONTENT/BT/MODELS/TRK3.MOD create mode 100644 CONTENT/BT/MODELS/TRK4.MOD create mode 100644 CONTENT/BT/MODELS/TRKDEAD.MOD create mode 100644 CONTENT/BT/MODELS/TT1.MOD create mode 100644 CONTENT/BT/MODELS/TT2.MOD create mode 100644 CONTENT/BT/MODELS/TWR.DMG create mode 100644 CONTENT/BT/MODELS/TWR.MOD create mode 100644 CONTENT/BT/MODELS/TWRDEAD.MOD create mode 100644 CONTENT/BT/MODELS/VEHICLE.TBL create mode 100644 CONTENT/BT/MODELS/VUL1.DMG create mode 100644 CONTENT/BT/MODELS/VUL1.MOD create mode 100644 CONTENT/BT/MODELS/VUL1.SUB create mode 100644 CONTENT/BT/MODELS/VUL1DMG.EXP create mode 100644 CONTENT/BT/MODELS/VUL1L4.CTL create mode 100644 CONTENT/BT/MODELS/VUL1THR.CTL create mode 100644 CONTENT/BT/MODELS/VUL2.MOD create mode 100644 CONTENT/BT/MODELS/VUL2DMG.EXP create mode 100644 CONTENT/BT/MODELS/VUL2DMG.TBL create mode 100644 CONTENT/BT/MODELS/VUL2THR.CTL create mode 100644 CONTENT/BT/MODELS/VULDEAD.MOD create mode 100644 CONTENT/BT/MODELS/VULDMG.EXP create mode 100644 CONTENT/BT/MODELS/VULL4.CTL create mode 100644 CONTENT/BT/MODELS/VULTHR.CTL create mode 100644 CONTENT/BT/MODELS/VULTURE.DMG create mode 100644 CONTENT/BT/MODELS/VULTURE.MOD create mode 100644 CONTENT/BT/MODELS/VULTURE.SUB create mode 100644 CONTENT/BT/MODELS/WALL1.MOD create mode 100644 CONTENT/BT/MODELS/WALL10K.MOD create mode 100644 CONTENT/BT/MODELS/WALL2.MOD create mode 100644 CONTENT/BT/MODELS/WALL3.MOD create mode 100644 CONTENT/BT/MODELS/WL1.MOD create mode 100644 CONTENT/BT/MODELS/WL2.MOD create mode 100644 CONTENT/BT/MODELS/WL3.MOD create mode 100644 CONTENT/BT/MODELS/WL4.MOD create mode 100644 CONTENT/BT/MODELS/WL5.MOD create mode 100644 CONTENT/BT/MODELS/WL6.MOD create mode 100644 CONTENT/BT/MODELS/WL7.MOD create mode 100644 CONTENT/BT/MODELS/WL8.MOD create mode 100644 CONTENT/BT/MODELS/WL9.MOD create mode 100644 CONTENT/BT/MODELS/WNDSFX01.MOD create mode 100644 CONTENT/BT/MODELS/WNDSFX02.MOD create mode 100644 CONTENT/BT/MODELS/WNDSFX03.MOD create mode 100644 CONTENT/BT/MODELS/WOLF.MOD create mode 100644 CONTENT/BT/MODELS/WPN.BLD create mode 100644 CONTENT/BT/MODELS/WPNDMG.TBL create mode 100644 CONTENT/BT/MODELS/WPNMECH.MOD create mode 100644 CONTENT/BT/MODELS/WPNMECH.SUB create mode 100644 CONTENT/BT/MODELS/WST.MOD create mode 100644 CONTENT/BT/NEWSTUFF.BLD create mode 100644 CONTENT/BT/NULL create mode 100644 CONTENT/BT/OMECH.BLD create mode 100644 CONTENT/BT/RESULT2.TXT create mode 100644 CONTENT/BT/SHOWENV.BAT create mode 100644 CONTENT/BT/SOLIDS/AB01_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB02_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB03_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB04_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB05_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB06_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB07_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB09_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AB10_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/ADWLK1~1.SLD create mode 100644 CONTENT/BT/SOLIDS/ADWLK2~1.SLD create mode 100644 CONTENT/BT/SOLIDS/ADWLK3~1.SLD create mode 100644 CONTENT/BT/SOLIDS/APC.SLD create mode 100644 CONTENT/BT/SOLIDS/AR01_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AR02_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AR03_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AR04_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AR05_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/ARBAN_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/ARENA1.XST create mode 100644 CONTENT/BT/SOLIDS/ARENA2.XST create mode 100644 CONTENT/BT/SOLIDS/ARENA3.XST create mode 100644 CONTENT/BT/SOLIDS/ARLID_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/ARMRMOVR.SLD create mode 100644 CONTENT/BT/SOLIDS/ARTRUCKS.XST create mode 100644 CONTENT/BT/SOLIDS/AVA_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AW03_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AW05_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/AWBOX_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BAC1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BCOR1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BCOR2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BDET4_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLANK.XST create mode 100644 CONTENT/BT/SOLIDS/BLD03_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLD04_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLD06_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLD20_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLD24_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLD26_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLD27_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BLH_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BNK_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BPIP1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/BULLDOG.SLD create mode 100644 CONTENT/BT/SOLIDS/BUTTEA_C.SLD create mode 100644 CONTENT/BT/SOLIDS/BUTTEB_C.SLD create mode 100644 CONTENT/BT/SOLIDS/BUTTEC_C.SLD create mode 100644 CONTENT/BT/SOLIDS/BUTTED_C.SLD create mode 100644 CONTENT/BT/SOLIDS/BUTTEE_C.SLD create mode 100644 CONTENT/BT/SOLIDS/BWLK1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/CALPB_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/CALP_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/CAVERN.XST create mode 100644 CONTENT/BT/SOLIDS/CITY1.XST create mode 100644 CONTENT/BT/SOLIDS/COMTRUCK.SLD create mode 100644 CONTENT/BT/SOLIDS/COOLANT.SLD create mode 100644 CONTENT/BT/SOLIDS/CRT_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/DBASE.XST create mode 100644 CONTENT/BT/SOLIDS/DES.XST create mode 100644 CONTENT/BT/SOLIDS/DISH_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/DOZER.SLD create mode 100644 CONTENT/BT/SOLIDS/FIR_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/FL1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/FP1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/FP2D_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/FP2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/FP3_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/FRSTRM.XST create mode 100644 CONTENT/BT/SOLIDS/FT1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/FT2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GD1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GD2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GD3_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GD4_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GD5_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GNR_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GR100ACV.SLD create mode 100644 CONTENT/BT/SOLIDS/GR100COL.SLD create mode 100644 CONTENT/BT/SOLIDS/GR100_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/GRASS.XST create mode 100644 CONTENT/BT/SOLIDS/HARASSER.SLD create mode 100644 CONTENT/BT/SOLIDS/HC1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HC2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLA_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLB_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLC_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLG1CO.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLG1_C.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLG2CO.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLG2_C.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLG3CO.SLD create mode 100644 CONTENT/BT/SOLIDS/HILLG3_C.SLD create mode 100644 CONTENT/BT/SOLIDS/HL1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HL2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HN1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HUMMER.SLD create mode 100644 CONTENT/BT/SOLIDS/HUT_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/HWZ_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/JAK_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/JAX1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/JAX2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/LOK_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/LRMCARRY.SLD create mode 100644 CONTENT/BT/SOLIDS/MAD_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/MECHMOVR.SLD create mode 100644 CONTENT/BT/SOLIDS/MSLBS_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/MSLG_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/MSLH_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/MSLRB_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/MSLR_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/MSL_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/OWN_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/PDSH_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/PGN_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/PLIT_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/POLAR1.XST create mode 100644 CONTENT/BT/SOLIDS/POLAR2.XST create mode 100644 CONTENT/BT/SOLIDS/POLAR3.XST create mode 100644 CONTENT/BT/SOLIDS/POLAR4.XST create mode 100644 CONTENT/BT/SOLIDS/RAP_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/RAV.XST create mode 100644 CONTENT/BT/SOLIDS/RAV1.XST create mode 100644 CONTENT/BT/SOLIDS/RFLOOR.SLD create mode 100644 CONTENT/BT/SOLIDS/RFLOOR_C.SLD create mode 100644 CONTENT/BT/SOLIDS/RK2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/RK4_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/RK5_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/RK6_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/RK7_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/ROMMEL.SLD create mode 100644 CONTENT/BT/SOLIDS/SAW_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1B_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1C_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1D_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1E_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1N_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1S_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1W_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2B_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2C_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2D_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2E_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2N_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2S_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2W_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB3E_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB3N_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB3S_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB3W_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB4E_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB4N_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB4S_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SB4W_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SEMI.SLD create mode 100644 CONTENT/BT/SOLIDS/SEMIRIG.SLD create mode 100644 CONTENT/BT/SOLIDS/SL2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SN1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SND_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SNH_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SR1E_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SR1N_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SR1S_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SR1W_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SRC1NE_C.SLD create mode 100644 CONTENT/BT/SOLIDS/SRC1NW_C.SLD create mode 100644 CONTENT/BT/SOLIDS/SRC1SE_C.SLD create mode 100644 CONTENT/BT/SOLIDS/SRC1SW_C.SLD create mode 100644 CONTENT/BT/SOLIDS/SRMCARRY.SLD create mode 100644 CONTENT/BT/SOLIDS/ST1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/STATE.RST create mode 100644 CONTENT/BT/SOLIDS/STB_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/STF_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/STH_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/STI_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/STRIKER.SLD create mode 100644 CONTENT/BT/SOLIDS/STS_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV2B_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV2C_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV2D_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV3B_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV3C_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV3D_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SV3_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SW1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SW2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SW3_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SW4_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SW5_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SW6_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/SWIFTWND.SLD create mode 100644 CONTENT/BT/SOLIDS/TEST.XST create mode 100644 CONTENT/BT/SOLIDS/THR_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TK1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TNT_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TREE_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TRK1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TRK3_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TRK4_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TT1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TT2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/TWR_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/VUL_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WALL10K.SLD create mode 100644 CONTENT/BT/SOLIDS/WALL1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WALL2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL1_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL2_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL3_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL4_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL5_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL6_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL7_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL8_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WL9_CV.SLD create mode 100644 CONTENT/BT/SOLIDS/WST_CV.SLD create mode 100644 CONTENT/BT/TEST.BAT create mode 100644 CONTENT/BT/VIDEO/AUTOARM.SKL create mode 100644 CONTENT/BT/VIDEO/AUTODARM.SKL create mode 100644 CONTENT/BT/VIDEO/AVA2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/AVASKIN.DZM create mode 100644 CONTENT/BT/VIDEO/AVX2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/AVXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/BATSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/BAXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/BLHSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/BLXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/BUILD/APCS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/APCS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/ARMRS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/ARMRS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BACKUP/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/BASEV.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/BASEV.BSL create mode 100644 CONTENT/BT/VIDEO/BUILD/BLD03.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BLD03_L0.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BLD04.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BLD08_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BLD24.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BLD26.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BLD26D.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BUILDBAS.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/BUILDGEN.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/BUILDLGO.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/BUILDTEX.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/BULLS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/BULLS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/CALIOPE.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/CALP.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/CALPD.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/CALP_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/COMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/COMS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/COOLS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/COOLS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/CTAR_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DBASE.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DBASE.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DCLOUDS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DISH.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DISH.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DISH_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/APCS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/ARMRS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/BASEV.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/BTRAVWIN.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/BULLS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/CALIOPE.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/COMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/COOLS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/DCLOUDS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/DISH.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/DOZERS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/HARASS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/HUMMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/LRMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/MECHMOVS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/RAVFLOOR.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/ROMMELS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/SEMIRIGS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/SEMIS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/SRMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/STRIKERS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DIVISION.SAV/SWIFTS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DOZERS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DOZERS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/DTAR_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/BLD08_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/BTRAVWIN.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDBAS.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDGEN.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDLGO.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/BUILDTEX.BAT create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/CALP_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/CTAR_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/DBASE.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/DISH_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/DTAR_LP.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/EDITBACK/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/GEN5.TGA create mode 100644 CONTENT/BT/VIDEO/BUILD/GEN6.TGA create mode 100644 CONTENT/BT/VIDEO/BUILD/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/HARASS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/HARASS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/HUMMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/HUMMS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/LRMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/LRMS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/MECHMOVS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/MECHMOVS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/BUILD/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/BUILD/ROMMELS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/ROMMELS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SEMIRIGS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SEMIRIGS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SEMIS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SEMIS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SRMS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SRMS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/STATE.RST create mode 100644 CONTENT/BT/VIDEO/BUILD/STRIKERS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/STRIKERS.VGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SWIFTS.BGF create mode 100644 CONTENT/BT/VIDEO/BUILD/SWIFTS.VGF create mode 100644 CONTENT/BT/VIDEO/DAFC.PFX create mode 100644 CONTENT/BT/VIDEO/DBIGBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/DDAM1.PFX create mode 100644 CONTENT/BT/VIDEO/DDAM2.PFX create mode 100644 CONTENT/BT/VIDEO/DDAM3.PFX create mode 100644 CONTENT/BT/VIDEO/DDAM4.PFX create mode 100644 CONTENT/BT/VIDEO/DDAM5.PFX create mode 100644 CONTENT/BT/VIDEO/DDTHSMK.PFX create mode 100644 CONTENT/BT/VIDEO/DLRMTAIL.PFX create mode 100644 CONTENT/BT/VIDEO/DMEDBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/DMISSING.PFX create mode 100644 CONTENT/BT/VIDEO/DNBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/DSMLBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/DSRM.PFX create mode 100644 CONTENT/BT/VIDEO/DTRKBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/DTRKBURN.PFX create mode 100644 CONTENT/BT/VIDEO/FIRSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/FIRXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/FLUSH.PFX create mode 100644 CONTENT/BT/VIDEO/GEO/AB01.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB02.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB04.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB05.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB06D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB07.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB07D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB08.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB09D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AB10D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ABG.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ACT01.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ACT02.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ACT03.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ACT04.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ACT05.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ADSUP1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ADSUP2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ADWLK1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ADWLK2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ADWLK3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AFLOOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/APCS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AR01_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AR02_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AR03_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AR04_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AR05_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARBAN1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARBAN2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARBAN3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARBAN4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARBAN5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARBAN6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARCLD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/AVA_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/BLH_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/FIR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/LOK_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/MAD_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/OWN_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/RAP_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/SND_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/STI_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/THR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA/VUL_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/AVA_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/BLH_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/FIR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/LOK_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/MAD_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/OWN_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/RAP_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/SND_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/STI_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/THR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARENA3/VUL_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARHORIZ.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARLID.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARMRS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ARTCGRND.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVADLARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVADLGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVADRARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVADRGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_HIP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_LARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_LBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_LDOO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_LGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_LITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_LOTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_RARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_RBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_RDOO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_RITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVA_ROTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVX_COP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AVX_TOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AW01.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AW02.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AW03.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AW05.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AWBOX1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/AWWLK1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BAC1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BALL1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BALL2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BALL3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BALL4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BBG.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BCOR1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BCOR2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BDET1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BDET2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BDET3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BDET4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BDET6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLD03.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLD04.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLD08_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLD24.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLD26.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLD26D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLHDLARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLHDLGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLHDRARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLHDRGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLH_LARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLH_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLH_LULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLH_RARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLH_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLH_RULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BLUEBEAM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BNKD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BNK_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BNK_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BPIP1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BPIP1D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BULLET.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BULLS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BUTTEF.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/BWLK1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CALPD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CALP_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAMPOS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/AVA_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/BLH_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/FIR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/LOK_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/MAD_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/OWN_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/RAP_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/SND_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/STI_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/THR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CAVERN/VUL_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CB1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CB2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CH1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CH2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/COMS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/COOLS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CRTD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/CTAR_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/D1DIRT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DAY/DIVISION.SAV/DSKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DAY/DSKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DAY/DSKY.BMF create mode 100644 CONTENT/BT/VIDEO/GEO/DAY/DSKY.VGF create mode 100644 CONTENT/BT/VIDEO/GEO/DAY/SKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DAY/SKY.VGF create mode 100644 CONTENT/BT/VIDEO/GEO/DAY/SPOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DECLOUDS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DISHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DISH_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/ARMRS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD03.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD03_L0.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD04.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD08_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD24.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD26.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/BLD26D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/CALPD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/CALP_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/COMS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/CTAR_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/D1DIRT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/DISH_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/DTAR_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/RAVFLOOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/RAVINE0.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/SEMIRIGS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TREE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TREESH.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TRUNK.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DOZERS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/DTAR_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ERMLASER.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/EVENING/DSKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/EVENING/SKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/EVENING/SPOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/EVENING/SPOT.BU create mode 100644 CONTENT/BT/VIDEO/GEO/EXDISK_A.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/EXDISK_B.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/EXDISK_C.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/EXP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FD1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FD2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FD3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FD4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FIRHIP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FL1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FLAMEBIG.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FLAMEBIG.VGF create mode 100644 CONTENT/BT/VIDEO/GEO/FLAMESML.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FLAMESML.VGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP0_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP1D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP1D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP1_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP2_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FP3D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FT1D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FT1_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FT1_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FT2D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FT2D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FT2_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/FT2_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/GD1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/GD2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/GD4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/GD5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/GNR_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/GREEBEAM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HARASS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HC1D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HC1_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HC2D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HC2_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HILLA.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HILLB.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HILLC.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HL1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HN1D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HN1_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HN1_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HND1_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HOTBOX.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HUMMS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HUTD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HUT_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HUT_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HWZD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/HWZ_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/JAX1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/JAX1D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/JAX1_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/JAX2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/JAX2D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/JAX2_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LDBR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LLASER.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOKDLARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOKDLGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOKDLIGH.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOKDMSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOKDRARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOKDRGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_HIP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_LDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_LGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_LIGH.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_LULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_MSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_RDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOK_RULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOX_COP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LOX_TOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/LRMS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MADDLARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MADDLGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MADDRARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MADDRGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_HIP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_LBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_LDOO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_LGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_LITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_LOTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_RBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_RDOO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_RGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_RITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAD_ROTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_LBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_LDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_LITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_LOTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_RBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_RDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_RITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MAX_ROTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MECHMOVS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MISSILE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MLASER.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MORNING/DSKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MORNING/RAVFLOOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MORNING/SEMIS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MORNING/SKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MORNING/SPOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLB_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLG_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLG_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLH_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLH_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLRD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLROAD1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLR_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSLR_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MSL_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/MUZFLASH.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/NBEAM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/NIGHT/DSKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/NIGHT/SKY.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/NIGHT/SPOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/NTR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWNDCAM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWNDLMSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWNDRMSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_CAM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_LANT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_LBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_LFTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_LMSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_RANT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_RBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_RFTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWN_RMSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_LBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_LDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_LFTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_LULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_RBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_RDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_RFTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/OWX_RULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PDSD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PDSH_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PDSH_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PGNDBASE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PGNDGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PGND_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PGN_BASE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PGN_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE7.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLACE8.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLIT_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PLTD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME7.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PNAME8.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/AVA_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/BLH_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/FIR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/LOK_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/MAD_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/OWN_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/RAP_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/SND_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/STI_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/THR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/POLAR/VUL_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PPC.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE7.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PROFILE8.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN7.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/PWIN8.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/AVA_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/BLH_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/FIR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/LOK_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/MAD_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/OWN_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/RAP_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/SND_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/STI_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/THR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV/VUL_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/AVA_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/BLH_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/FIR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/LOK_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/MAD_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/OWN_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/RAP_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/SND_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/STI_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/THR_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAV1/VUL_TSHD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAVFLOOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAVINE0.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/GEO/RAVWIN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RB1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RB2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RB3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RB4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RB5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RB6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RD1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RD2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RED_BEAM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RK4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RK5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RK6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RK7.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ROMMELS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RWD.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/RWIN1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SAW.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1B.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1C.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1E.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1N.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1S.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB1W.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2B.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2C.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2E.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2N.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2S.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB2W.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB3E.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB3N.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB3S.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB3W.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB4E.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB4N.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB4S.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SB4W.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SEMIRIGS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SEMIS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SHOCK.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SL2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SL2D.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SL2D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SLASER.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SLD2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SLD2_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SLT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SMK_A.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SMK_B.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SMK_C.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SN1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SN2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SN4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SNDDLARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SNDDLGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SNDDRARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_DOOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_HIP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_LDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_LULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_RARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_RDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SND_RULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SNHD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SNH_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SNX_COP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SNX_TOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SPK1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SPK2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SPOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SR1E.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SR1N.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SR1S.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SR1W.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SRC1NE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SRC1NW.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SRC1SE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SRC1SW.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SRMS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/ST1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/STF.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/STILITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/STILOTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/STIRITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/STIROTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/STRIKERS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/STX_COP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV2BR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV2BS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV2CR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV2DR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV2DS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV2R.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV2S.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3BR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3BS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3CR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3CS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3DR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3DS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3R.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SV3S.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SW1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SW2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SW3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SW4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SW5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SW6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/SWIFTS.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THRDBR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THRDLGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THRDMSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THRDRARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THRDRGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_DOOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_HIP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_LDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_LGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_LULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_MSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_RDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THR_RULE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THXDMSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THX_DOOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THX_MSL.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/THX_TOR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TM1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC1.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC2.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC3.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC3_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC4.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC4_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC5.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC5_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC6.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC6_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC7.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC7_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC8.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMC8_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMSM_A.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMSM_B.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMSM_C.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMST_A.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMST_C.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMS_A.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMS_B.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TMS_C.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TREE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TREESH.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TRK1D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TRK1_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TRK3D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TRK3_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TRK4D_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TRK4_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TRUNK.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TSPHERE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TWRD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TWR_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/TWR_LP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VULDLARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VULDLGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VULDRARM.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VULDRGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_HIP.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_LBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_LDDO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_LGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_LITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_LOTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_LUDO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_RBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_RDDO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_RGUN.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_RITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_ROTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUL_RUDO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_LBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_LDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_LFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_LITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_LOTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_RBTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_RDLE.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_RFOT.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_RITO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/VUX_ROTO.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/WL7.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/WL9.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/WSTD_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/WST_FR.BGF create mode 100644 CONTENT/BT/VIDEO/GEO/WST_LP.BGF create mode 100644 CONTENT/BT/VIDEO/IDAM1.PFX create mode 100644 CONTENT/BT/VIDEO/IDAM2.PFX create mode 100644 CONTENT/BT/VIDEO/IDAM3.PFX create mode 100644 CONTENT/BT/VIDEO/IDAM4.PFX create mode 100644 CONTENT/BT/VIDEO/IDAM5.PFX create mode 100644 CONTENT/BT/VIDEO/JAKSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/JAXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/LASARM.SKL create mode 100644 CONTENT/BT/VIDEO/LOK1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/LOKSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/LOX1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/LOXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/MAD1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/MAD2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/MADSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/MADSKIN.ORG create mode 100644 CONTENT/BT/VIDEO/MAT/ARENA/BTVEH.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVAFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVASKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/AVX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BASEV.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLHFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLHSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BLX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BMAP.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BTCULT.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BTPOLWIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/BTRAVWIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/CALIOPE.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/CAVERN/BTVEH.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/BTARENA.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/BTFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/BTPOLAR.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/DIVISION.SAV/GRASSBU.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/EBTFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/GRASSBU.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/GRASSBU.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DAY/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/DBASE.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DISH.BGF create mode 100644 CONTENT/BT/VIDEO/MAT/DISH.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/BASEV.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/CALIOPE.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/DBASE.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/DISH.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/DIVISION.SAV/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/DUMMY.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/BTPOLAR.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/DIVISION.SAV/BTFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/EVENING/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIRSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIR_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/FIX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAKSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAK_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/JAX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOKFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOKSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/LOX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MADFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MADSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MAX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MECHFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/BTFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/BTPOLAR.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/DIVISION.SAV/BTFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/DIVISION.SAV/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/MORNING/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/BTFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/BTPOLAR.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/DIVISION.SAV/BTFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/GRASS.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/GRASS.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/NIGHT/RAVINES.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWNFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWNSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/OWX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAPSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAP_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAVBU.VMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAVINES.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/RAX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNDFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNDSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/SNX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STIFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STISKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STI_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/STX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THRFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THRSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/THX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VULFX.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VULSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUXSKIN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BLK7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_BRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_GRY7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_RED7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_TAN7.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT0.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT1.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT2.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT3.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT4.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT5.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT6.BMF create mode 100644 CONTENT/BT/VIDEO/MAT/VUX_WHT7.BMF create mode 100644 CONTENT/BT/VIDEO/MAX.ORG create mode 100644 CONTENT/BT/VIDEO/MAX1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/MAX2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/MAXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/MAXSKIN.ORG create mode 100644 CONTENT/BT/VIDEO/NAFC.PFX create mode 100644 CONTENT/BT/VIDEO/NBIGBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/NDAM1.PFX create mode 100644 CONTENT/BT/VIDEO/NDAM2.PFX create mode 100644 CONTENT/BT/VIDEO/NDAM3.PFX create mode 100644 CONTENT/BT/VIDEO/NDAM4.PFX create mode 100644 CONTENT/BT/VIDEO/NDAM5.PFX create mode 100644 CONTENT/BT/VIDEO/NDTHSMK.PFX create mode 100644 CONTENT/BT/VIDEO/NLRMTAIL.PFX create mode 100644 CONTENT/BT/VIDEO/NMEDBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/NMISSING.PFX create mode 100644 CONTENT/BT/VIDEO/NNBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/NSMLBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/NSRM.PFX create mode 100644 CONTENT/BT/VIDEO/NTRKBOOM.PFX create mode 100644 CONTENT/BT/VIDEO/NTRKBURN.PFX create mode 100644 CONTENT/BT/VIDEO/OWNSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/OWXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/PGN.SKL create mode 100644 CONTENT/BT/VIDEO/PGND.SKL create mode 100644 CONTENT/BT/VIDEO/RAPSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/RAXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/RESULT2.TXT create mode 100644 CONTENT/BT/VIDEO/SHKWAVE.PFX create mode 100644 CONTENT/BT/VIDEO/SMLFLASH.PFX create mode 100644 CONTENT/BT/VIDEO/SMLSMOKE.PFX create mode 100644 CONTENT/BT/VIDEO/SND2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/SNX2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/SNXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/STISKIN.DZM create mode 100644 CONTENT/BT/VIDEO/STXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/TEX/BDINTA.VTX create mode 100644 CONTENT/BT/VIDEO/TEX/BDINTB.VTX create mode 100644 CONTENT/BT/VIDEO/TEX/BDINTC.VTX create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/BDLGO128.BAT create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/BUILDLGO.BAT create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/LGO1.TGA create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/LGO2.TGA create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/LGO3.TGA create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/LGO4.TGA create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/LGO5.TGA create mode 100644 CONTENT/BT/VIDEO/TEX/BUILD/LGO6.TGA create mode 100644 CONTENT/BT/VIDEO/TEX/GRASSC.VTX create mode 100644 CONTENT/BT/VIDEO/TEX/LGO.BSL create mode 100644 CONTENT/BT/VIDEO/TEX/SAINTB.VTX create mode 100644 CONTENT/BT/VIDEO/TEX/SBASE.BSL create mode 100644 CONTENT/BT/VIDEO/THR1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/THRSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/THX1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/THXSKIN.DZM create mode 100644 CONTENT/BT/VIDEO/VUL1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/VUL2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/VUX1SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/VUX2SKIN.DZM create mode 100644 CONTENT/BT/VIDEO/VUXSKIN.DZM create mode 100644 CONTENT/BT/WATTCP.CFG create mode 100644 CONTENT/BT3025/32STUB.EXE create mode 100644 CONTENT/BT3025/ANIM.BAT create mode 100644 CONTENT/BT3025/ANIM1.BAT create mode 100644 CONTENT/BT3025/ANIMCAM.BAT create mode 100644 CONTENT/BT3025/ANIMS/BLHBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/BLHBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/BLHSQI.ANI create mode 100644 CONTENT/BT3025/ANIMS/BLHSQT.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRRRL.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRRRLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRRRR.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRRRRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRRWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRRWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRSWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRSWLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRSWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRSWRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRTRN.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRTRNI.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRWSL.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRWSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRWSR.ANI create mode 100644 CONTENT/BT3025/ANIMS/FIRWSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKBSL.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKBSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKBSR.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKBSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKRWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKRWLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKRWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKRWRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKSWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKSWLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKSWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKSWRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKTRN.ANI create mode 100644 CONTENT/BT3025/ANIMS/JAKTRNI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKBBLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKBBRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKBSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKBSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKTRN.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKTRNI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKWSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKWSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKWWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKWWLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKWWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/LOKWWRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/OWNBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/OWNBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/OWNSQI.ANI create mode 100644 CONTENT/BT3025/ANIMS/OWNSQT.ANI create mode 100644 CONTENT/BT3025/ANIMS/RAPBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/RAPBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/RAPRWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/RAPRWLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/RAPRWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/RAPRWRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDBBLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDBBRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDBSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDBSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDTRN.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDTRNI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDWSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDWSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDWWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDWWLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDWWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/SNDWWRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THR4JERR.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRBBLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRBBRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRBMP.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRBMPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRBSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRBSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRCLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THROPI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRSQT.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRTRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRTRN.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRTRNI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRTSI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRTST.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRWSLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRWSRI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRWWL.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRWWLI.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRWWR.ANI create mode 100644 CONTENT/BT3025/ANIMS/THRWWRI.ANI create mode 100644 CONTENT/BT3025/ARCBT.BAT create mode 100644 CONTENT/BT3025/ARCFILES.LST create mode 100644 CONTENT/BT3025/AUDIO/ABFWRN01.MID create mode 100644 CONTENT/BT3025/AUDIO/ABNTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/ACNCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/ACNCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ACNTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/ACNTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ALMINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/AUDIO.INI create mode 100644 CONTENT/BT3025/AUDIO/AUDIOMR.INI create mode 100644 CONTENT/BT3025/AUDIO/AVA1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/AVA1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/AVA2.SCP create mode 100644 CONTENT/BT3025/AUDIO/AVAEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/AVAINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/BATEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/BATINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/BHK1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/BHK1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/BIGEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/BIGEXP01.MID create mode 100644 CONTENT/BT3025/AUDIO/BLKEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/BLKINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/CALEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/CALINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/CLKWRN01.MID create mode 100644 CONTENT/BT3025/AUDIO/CLTCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/CLTTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/CNDCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/CNDTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/COLEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/CRNEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/CTMIX.CFG create mode 100644 CONTENT/BT3025/AUDIO/DGAEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/DGBEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/DGCEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/DSTCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/DSTRD01.MID create mode 100644 CONTENT/BT3025/AUDIO/DSTRD02.MID create mode 100644 CONTENT/BT3025/AUDIO/DSTTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/EPCCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/EPPCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/EPPCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/EPPTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/EPPTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERLCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERLCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERLTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERLTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERMCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERMCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERMTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERMTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERSCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERSCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERSTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/ERSTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/FIND.TXT create mode 100644 CONTENT/BT3025/AUDIO/FIREXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/FIRINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/GENCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/GENTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/GENWRN01.MID create mode 100644 CONTENT/BT3025/AUDIO/GENWRN02.MID create mode 100644 CONTENT/BT3025/AUDIO/GLRCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/GLRTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/HETEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/HETINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/ICOM.CFG create mode 100644 CONTENT/BT3025/AUDIO/INCARM01.MID create mode 100644 CONTENT/BT3025/AUDIO/JAKEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/JAKINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LACCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/LACTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/LEGWRN01.MID create mode 100644 CONTENT/BT3025/AUDIO/LLRCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/LLRCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/LLRTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/LLRTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/LO1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LO1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LOK1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LOK1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LOK2EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LOK2INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LOKEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LOKINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/LRMCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/LRMTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/LSRCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/LSREXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/LSRLDD01.MID create mode 100644 CONTENT/BT3025/AUDIO/LSRTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/MACCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/MACTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/MAD1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MAD1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MAD2EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MAD2INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MADEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MADINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MCHEXP03.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXP04.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXP05.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXP06.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXP07.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXPI1.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXPI2.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXPI3.MID create mode 100644 CONTENT/BT3025/AUDIO/MCHEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MCHFRE01.MID create mode 100644 CONTENT/BT3025/AUDIO/MCTINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/MEDEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/MEDEXP01.MID create mode 100644 CONTENT/BT3025/AUDIO/MGNTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/MLRCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/MLRCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/MLRTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/MLRTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/MSLEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/MSLJAM01.MID create mode 100644 CONTENT/BT3025/AUDIO/MSLLDD01.MID create mode 100644 CONTENT/BT3025/AUDIO/MSLMFR01.MID create mode 100644 CONTENT/BT3025/AUDIO/MSLTVL.SCP create mode 100644 CONTENT/BT3025/AUDIO/MYRCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/MYRTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/OWN1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/OWN1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/OWNEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/OWNINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/PLYINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/PPCCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/PPCCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/PPCEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/PPCEXPI.SCP create mode 100644 CONTENT/BT3025/AUDIO/PPCTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/PPCTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/PRGBUT01.MID create mode 100644 CONTENT/BT3025/AUDIO/PRJCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/PRJJAM01.MID create mode 100644 CONTENT/BT3025/AUDIO/PRJLDD01.MID create mode 100644 CONTENT/BT3025/AUDIO/PRJMFR01.MID create mode 100644 CONTENT/BT3025/AUDIO/PRJTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/PRJTVL.SCP create mode 100644 CONTENT/BT3025/AUDIO/RAPEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/RAPINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/SACCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/SACTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/SLRCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/SLRCMPE.SCP create mode 100644 CONTENT/BT3025/AUDIO/SLRTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/SLRTRGE.SCP create mode 100644 CONTENT/BT3025/AUDIO/SMLEXP.SCP create mode 100644 CONTENT/BT3025/AUDIO/SND1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/SND1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/SND2EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/SND2INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/SNDEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/SNDINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/SNRTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/SRMCMP.SCP create mode 100644 CONTENT/BT3025/AUDIO/SRMTRG.SCP create mode 100644 CONTENT/BT3025/AUDIO/STATIC.SCP create mode 100644 CONTENT/BT3025/AUDIO/STIEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/STIINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/THR1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/THR1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/THR6EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/THR6INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/THREXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/THRINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/TRSEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/TRSINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/VUL1EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/VUL1INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/VUL2EXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/VUL2INT.SCP create mode 100644 CONTENT/BT3025/AUDIO/VULEXT.SCP create mode 100644 CONTENT/BT3025/AUDIO/VULINT.SCP create mode 100644 CONTENT/BT3025/AUDIO/WNDEXT01.SCP create mode 100644 CONTENT/BT3025/AUDIO/WPNINT.SCP create mode 100644 CONTENT/BT3025/AUTOEXEC.BAT create mode 100644 CONTENT/BT3025/BT.BAT create mode 100644 CONTENT/BT3025/BTCAM.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM01.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM02.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM03.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM04.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM05.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM06.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM07.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM08.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM09.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM10.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM11.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM12.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM13.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM14.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM15.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM16.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM17.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM18.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM19.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM20.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM21.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM22.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM23.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM24.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM25.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM26.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM27.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM28.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM29.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM30.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM31.BAT create mode 100644 CONTENT/BT3025/BTCAM/BTCAM32.BAT create mode 100644 CONTENT/BT3025/BTGO.BAT create mode 100644 CONTENT/BT3025/BTLOOK.BAT create mode 100644 CONTENT/BT3025/BTNET.BAT create mode 100644 CONTENT/BT3025/BTPREP.BAT create mode 100644 CONTENT/BT3025/BUILD.BAT create mode 100644 CONTENT/BT3025/BUILD1.BAT create mode 100644 CONTENT/BT3025/DEARCBT.BAT create mode 100644 CONTENT/BT3025/EXCLUDE.LST create mode 100644 CONTENT/BT3025/FAILURE.LOG create mode 100644 CONTENT/BT3025/GAUGE/AB01_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB02_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB03_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB04_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB05_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB06_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB07_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB08_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB09_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AB10_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AD01_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/ADPAL.PCC create mode 100644 CONTENT/BT3025/GAUGE/ADPAL2.PCC create mode 100644 CONTENT/BT3025/GAUGE/APC.GIM create mode 100644 CONTENT/BT3025/GAUGE/AR01_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AR02_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AR03_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AR04_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AR05_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/ARENA_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/ARMRMOVR.GIM create mode 100644 CONTENT/BT3025/GAUGE/AW01_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AW02_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AW03_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AW04_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/AW05_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BDUCK.PCC create mode 100644 CONTENT/BT3025/GAUGE/BLD03_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BLD04_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BLD06_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BLD20_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BLD24_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BLD26_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BLD27_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BLH_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BNK_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/BTEBUS.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTECMODE.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTEFIRE.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTEHFAIL.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTEJAM.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTELOOP.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTEPFAIL.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTESFAIL.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTESLEV.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTESRNGE.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTEUNJM.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTOPAL.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTPBUS.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTPLOOP.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTSPAL.PCC create mode 100644 CONTENT/BT3025/GAUGE/BTWARN.PCC create mode 100644 CONTENT/BT3025/GAUGE/BULLDOG.GIM create mode 100644 CONTENT/BT3025/GAUGE/BUTTEA_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/BUTTEB_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/BUTTEC_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/BUTTED_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/BUTTEE_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/CALPB_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/CALP_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/CM_BOTH.PCC create mode 100644 CONTENT/BT3025/GAUGE/CM_OFF.PCC create mode 100644 CONTENT/BT3025/GAUGE/CM_ONLY.PCC create mode 100644 CONTENT/BT3025/GAUGE/CM_OTHER.PCC create mode 100644 CONTENT/BT3025/GAUGE/COMTRUCK.GIM create mode 100644 CONTENT/BT3025/GAUGE/COOLANT.GIM create mode 100644 CONTENT/BT3025/GAUGE/DISH_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/DOZER.GIM create mode 100644 CONTENT/BT3025/GAUGE/EAFC10.PCC create mode 100644 CONTENT/BT3025/GAUGE/EAFC100.PCC create mode 100644 CONTENT/BT3025/GAUGE/EAFC25.PCC create mode 100644 CONTENT/BT3025/GAUGE/EAFC5.PCC create mode 100644 CONTENT/BT3025/GAUGE/EAFC50.PCC create mode 100644 CONTENT/BT3025/GAUGE/EDESTRYD.PCC create mode 100644 CONTENT/BT3025/GAUGE/EERLLAS.PCC create mode 100644 CONTENT/BT3025/GAUGE/EERPPC.PCC create mode 100644 CONTENT/BT3025/GAUGE/EERSLAS.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELBX10.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELBX100.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELBX25.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELBX5.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELEAK.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELLAS.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELRM10.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELRM15.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELRM20.PCC create mode 100644 CONTENT/BT3025/GAUGE/ELRM5.PCC create mode 100644 CONTENT/BT3025/GAUGE/EMG.PCC create mode 100644 CONTENT/BT3025/GAUGE/ENRK15.PCC create mode 100644 CONTENT/BT3025/GAUGE/ENRK5.PCC create mode 100644 CONTENT/BT3025/GAUGE/EPPC.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESCND.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESENSORS.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESRM2.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESRM4.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESRM6.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESTRK2.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESTRK4.PCC create mode 100644 CONTENT/BT3025/GAUGE/ESTRK6.PCC create mode 100644 CONTENT/BT3025/GAUGE/EVOLT.PCC create mode 100644 CONTENT/BT3025/GAUGE/FP1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/FP2_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/FT1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/FT2_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/GAUGE.GAT create mode 100644 CONTENT/BT3025/GAUGE/GNR_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/HARASSER.GIM create mode 100644 CONTENT/BT3025/GAUGE/HEATPAL.PCC create mode 100644 CONTENT/BT3025/GAUGE/HEATPAL2.PCC create mode 100644 CONTENT/BT3025/GAUGE/HELV15.PCC create mode 100644 CONTENT/BT3025/GAUGE/HELV18.PCC create mode 100644 CONTENT/BT3025/GAUGE/HILLG1_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/HILLG2_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/HILLG3_G.GIM create mode 100644 CONTENT/BT3025/GAUGE/HL1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/HL2_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/HN1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/HUMMER.GIM create mode 100644 CONTENT/BT3025/GAUGE/HUT_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/HWZ_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/JAK_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/L4GAUGE.INI create mode 100644 CONTENT/BT3025/GAUGE/LRMCARRY.GIM create mode 100644 CONTENT/BT3025/GAUGE/MECHMOVR.GIM create mode 100644 CONTENT/BT3025/GAUGE/MRPAL.PCC create mode 100644 CONTENT/BT3025/GAUGE/MSLG_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/MSLR_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/PDSH_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/PGN_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/QAFC10.PCC create mode 100644 CONTENT/BT3025/GAUGE/QAFC100.PCC create mode 100644 CONTENT/BT3025/GAUGE/QAFC25.PCC create mode 100644 CONTENT/BT3025/GAUGE/QAFC5.PCC create mode 100644 CONTENT/BT3025/GAUGE/QAFC50.PCC create mode 100644 CONTENT/BT3025/GAUGE/QCIRCLE.PCC create mode 100644 CONTENT/BT3025/GAUGE/QCIRCR.PCC create mode 100644 CONTENT/BT3025/GAUGE/QERLLAS.PCC create mode 100644 CONTENT/BT3025/GAUGE/QERPPC.PCC create mode 100644 CONTENT/BT3025/GAUGE/QERSLAS.PCC create mode 100644 CONTENT/BT3025/GAUGE/QFIR0.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLBX10.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLBX100.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLBX25.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLBX5.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLBX50.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLLAS.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLRM10.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLRM15.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLRM20.PCC create mode 100644 CONTENT/BT3025/GAUGE/QLRM5.PCC create mode 100644 CONTENT/BT3025/GAUGE/QMG.PCC create mode 100644 CONTENT/BT3025/GAUGE/QNRK15.PCC create mode 100644 CONTENT/BT3025/GAUGE/QNRK5.PCC create mode 100644 CONTENT/BT3025/GAUGE/QPPC.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSENSORS.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSLASER.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSRM2.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSRM4.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSRM6.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSTRK2.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSTRK4.PCC create mode 100644 CONTENT/BT3025/GAUGE/QSTRK6.PCC create mode 100644 CONTENT/BT3025/GAUGE/RAP_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RESULT2.TXT create mode 100644 CONTENT/BT3025/GAUGE/RIVET_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RK1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RK2_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RK3_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RK4_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RK5_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RK6_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/RK7_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/ROMMEL.GIM create mode 100644 CONTENT/BT3025/GAUGE/SB1E_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SB1N_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SB1S_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SB1W_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SB3S_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SEMI.GIM create mode 100644 CONTENT/BT3025/GAUGE/SEMIRIG.GIM create mode 100644 CONTENT/BT3025/GAUGE/SGEN1.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGEN2.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGEN3.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGEN4.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGEN5.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGEN6.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGENA.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGENB.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGENBG.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGENC.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGEND.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGENLEAK.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGENTEMP.PCC create mode 100644 CONTENT/BT3025/GAUGE/SGENVOLT.PCC create mode 100644 CONTENT/BT3025/GAUGE/SIZUMIN.PCC create mode 100644 CONTENT/BT3025/GAUGE/SIZUMOUT.PCC create mode 100644 CONTENT/BT3025/GAUGE/SMLFONT.PCC create mode 100644 CONTENT/BT3025/GAUGE/SR1E_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SR1N_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SR1S_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SR1W_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SRMCARRY.GIM create mode 100644 CONTENT/BT3025/GAUGE/ST1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/STB_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/STF_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/STH_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/STI_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/STRIKER.GIM create mode 100644 CONTENT/BT3025/GAUGE/STS_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/STT_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SVISION.PCC create mode 100644 CONTENT/BT3025/GAUGE/SW1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SW2_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SW3_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SW4_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SW5_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SW6_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/SWIFTWND.GIM create mode 100644 CONTENT/BT3025/GAUGE/THOR_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/TINYFONT.PCC create mode 100644 CONTENT/BT3025/GAUGE/TMC1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/TMC2_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/TNT_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/TREE_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/TWR_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/WALL1_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/WALL2_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/WALL3_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/WST_GA.GIM create mode 100644 CONTENT/BT3025/GAUGE/X_GA.GIM create mode 100644 CONTENT/BT3025/GO.BAT create mode 100644 CONTENT/BT3025/JOYSTICK.INI create mode 100644 CONTENT/BT3025/LAST.EGG create mode 100644 CONTENT/BT3025/MAKEEGG.BAT create mode 100644 CONTENT/BT3025/MAPS/ADROP.MAP create mode 100644 CONTENT/BT3025/MAPS/ALL.ZNE create mode 100644 CONTENT/BT3025/MAPS/ARENA1.MAP create mode 100644 CONTENT/BT3025/MAPS/ARENA2.MAP create mode 100644 CONTENT/BT3025/MAPS/BLANK.MAP create mode 100644 CONTENT/BT3025/MAPS/PDROP.MAP create mode 100644 CONTENT/BT3025/MAPS/POL3SFX.MAP create mode 100644 CONTENT/BT3025/MAPS/POL4DROP.MAP create mode 100644 CONTENT/BT3025/MAPS/POL4SFX.MAP create mode 100644 CONTENT/BT3025/MAPS/TEST.MAP create mode 100644 CONTENT/BT3025/MAPS/TEST1.MAP create mode 100644 CONTENT/BT3025/MAPS/TEST5.MAP create mode 100644 CONTENT/BT3025/MENU.BAT create mode 100644 CONTENT/BT3025/MODELS/AB01.MOD create mode 100644 CONTENT/BT3025/MODELS/AB02.MOD create mode 100644 CONTENT/BT3025/MODELS/AB03.MOD create mode 100644 CONTENT/BT3025/MODELS/AB04.MOD create mode 100644 CONTENT/BT3025/MODELS/AB05.MOD create mode 100644 CONTENT/BT3025/MODELS/AB06.MOD create mode 100644 CONTENT/BT3025/MODELS/AB06D.MOD create mode 100644 CONTENT/BT3025/MODELS/AB07.MOD create mode 100644 CONTENT/BT3025/MODELS/AB08.MOD create mode 100644 CONTENT/BT3025/MODELS/AB09.MOD create mode 100644 CONTENT/BT3025/MODELS/AB09D.MOD create mode 100644 CONTENT/BT3025/MODELS/AB10.MOD create mode 100644 CONTENT/BT3025/MODELS/AB10D.MOD create mode 100644 CONTENT/BT3025/MODELS/ACT01.MOD create mode 100644 CONTENT/BT3025/MODELS/ACT02.MOD create mode 100644 CONTENT/BT3025/MODELS/ACT03.MOD create mode 100644 CONTENT/BT3025/MODELS/ACT04.MOD create mode 100644 CONTENT/BT3025/MODELS/ACT05.MOD create mode 100644 CONTENT/BT3025/MODELS/AD01.MOD create mode 100644 CONTENT/BT3025/MODELS/ADSUP1.MOD create mode 100644 CONTENT/BT3025/MODELS/ADSUP2.MOD create mode 100644 CONTENT/BT3025/MODELS/ADWLK1.MOD create mode 100644 CONTENT/BT3025/MODELS/ADWLK2.MOD create mode 100644 CONTENT/BT3025/MODELS/ADWLK3.MOD create mode 100644 CONTENT/BT3025/MODELS/AFC100.SUB create mode 100644 CONTENT/BT3025/MODELS/AFC25.SUB create mode 100644 CONTENT/BT3025/MODELS/AFC5.SUB create mode 100644 CONTENT/BT3025/MODELS/AFC50.SUB create mode 100644 CONTENT/BT3025/MODELS/AFLOOR.MOD create mode 100644 CONTENT/BT3025/MODELS/AMAFC100.SUB create mode 100644 CONTENT/BT3025/MODELS/AMBSSDOR.MOD create mode 100644 CONTENT/BT3025/MODELS/AMLBX100.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMAFC25.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMAFC5.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMAFC50.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMLBX25.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMLBX5.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMLBX50.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMLRM10.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMLRM15.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMLRM20.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMLRM5.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMNRK10.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMNRK15.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMNRK20.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMNRK5.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMOAC.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMOAC10.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMOGAUS.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMOMG.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSRM2.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSRM25.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSRM30.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSRM4.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSRM6.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSTRK2.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSTRK4.SUB create mode 100644 CONTENT/BT3025/MODELS/AMMSTRK6.SUB create mode 100644 CONTENT/BT3025/MODELS/APC.MOD create mode 100644 CONTENT/BT3025/MODELS/AR01.MOD create mode 100644 CONTENT/BT3025/MODELS/AR02.MOD create mode 100644 CONTENT/BT3025/MODELS/AR03.MOD create mode 100644 CONTENT/BT3025/MODELS/AR04.MOD create mode 100644 CONTENT/BT3025/MODELS/AR05.MOD create mode 100644 CONTENT/BT3025/MODELS/ARBAN1.MOD create mode 100644 CONTENT/BT3025/MODELS/ARBAN2.MOD create mode 100644 CONTENT/BT3025/MODELS/ARBAN3.MOD create mode 100644 CONTENT/BT3025/MODELS/ARBAN4.MOD create mode 100644 CONTENT/BT3025/MODELS/ARBAN5.MOD create mode 100644 CONTENT/BT3025/MODELS/ARBAN6.MOD create mode 100644 CONTENT/BT3025/MODELS/ARCLD.MOD create mode 100644 CONTENT/BT3025/MODELS/ARENA.MOD create mode 100644 CONTENT/BT3025/MODELS/ARHORIZ.MOD create mode 100644 CONTENT/BT3025/MODELS/ARLID.MOD create mode 100644 CONTENT/BT3025/MODELS/ARMOR1.DMG create mode 100644 CONTENT/BT3025/MODELS/ARMRMOVR.MOD create mode 100644 CONTENT/BT3025/MODELS/ARWC.MOD create mode 100644 CONTENT/BT3025/MODELS/ATTACKER.MOD create mode 100644 CONTENT/BT3025/MODELS/AVA1DEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/AVA1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/AVA1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/AVA2DEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/AVA2DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/AVA2THR.CTL create mode 100644 CONTENT/BT3025/MODELS/AVADEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/AVADMG.EXP create mode 100644 CONTENT/BT3025/MODELS/AVATHR.CTL create mode 100644 CONTENT/BT3025/MODELS/AW01.MOD create mode 100644 CONTENT/BT3025/MODELS/AW02.MOD create mode 100644 CONTENT/BT3025/MODELS/AW03.MOD create mode 100644 CONTENT/BT3025/MODELS/AW04.MOD create mode 100644 CONTENT/BT3025/MODELS/AW05.MOD create mode 100644 CONTENT/BT3025/MODELS/AWBOX1.MOD create mode 100644 CONTENT/BT3025/MODELS/AWWLK1.MOD create mode 100644 CONTENT/BT3025/MODELS/BAC1.MOD create mode 100644 CONTENT/BT3025/MODELS/BATDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/BATTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/BCOR1.MOD create mode 100644 CONTENT/BT3025/MODELS/BCOR2.MOD create mode 100644 CONTENT/BT3025/MODELS/BDET1.MOD create mode 100644 CONTENT/BT3025/MODELS/BDET2.MOD create mode 100644 CONTENT/BT3025/MODELS/BDET3.MOD create mode 100644 CONTENT/BT3025/MODELS/BDET4.MOD create mode 100644 CONTENT/BT3025/MODELS/BDET6.MOD create mode 100644 CONTENT/BT3025/MODELS/BHK1DEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/BHK1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/BHK1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/BIGDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD01.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD02.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD03.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD04.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD05.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD06.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD08.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD20.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD24.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD26.MOD create mode 100644 CONTENT/BT3025/MODELS/BLD27.MOD create mode 100644 CONTENT/BT3025/MODELS/BLHDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/BLHDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/BLHTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/BNK.MOD create mode 100644 CONTENT/BT3025/MODELS/BPIP1.MOD create mode 100644 CONTENT/BT3025/MODELS/BULLDOG.MOD create mode 100644 CONTENT/BT3025/MODELS/BUTTEA.MOD create mode 100644 CONTENT/BT3025/MODELS/BUTTEB.MOD create mode 100644 CONTENT/BT3025/MODELS/BUTTEC.MOD create mode 100644 CONTENT/BT3025/MODELS/BUTTED.MOD create mode 100644 CONTENT/BT3025/MODELS/BUTTEE.MOD create mode 100644 CONTENT/BT3025/MODELS/BUTTEEU.MOD create mode 100644 CONTENT/BT3025/MODELS/BUTTEF.MOD create mode 100644 CONTENT/BT3025/MODELS/BWLK1.MOD create mode 100644 CONTENT/BT3025/MODELS/CALP.DMG create mode 100644 CONTENT/BT3025/MODELS/CALP.MOD create mode 100644 CONTENT/BT3025/MODELS/CALPB.MOD create mode 100644 CONTENT/BT3025/MODELS/CAMERA.MOD create mode 100644 CONTENT/BT3025/MODELS/CAMPOS.MOD create mode 100644 CONTENT/BT3025/MODELS/CANHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/CANHITI.MOD create mode 100644 CONTENT/BT3025/MODELS/CB1.MOD create mode 100644 CONTENT/BT3025/MODELS/CLD.MOD create mode 100644 CONTENT/BT3025/MODELS/COMTRUCK.MOD create mode 100644 CONTENT/BT3025/MODELS/CONDENSR.SUB create mode 100644 CONTENT/BT3025/MODELS/CONVOY.MOD create mode 100644 CONTENT/BT3025/MODELS/COOLANT.MOD create mode 100644 CONTENT/BT3025/MODELS/CRT.MOD create mode 100644 CONTENT/BT3025/MODELS/CTARMAC.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM1HIT.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM1HITI.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM2HIT.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM2HITI.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM3EXP.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM3HIT.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM3HITI.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM4EXP.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM4EXPI.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM4HIT.MOD create mode 100644 CONTENT/BT3025/MODELS/DAM4HITI.MOD create mode 100644 CONTENT/BT3025/MODELS/DAVION.MOD create mode 100644 CONTENT/BT3025/MODELS/DECOY.MOD create mode 100644 CONTENT/BT3025/MODELS/DEFENDER.MOD create mode 100644 CONTENT/BT3025/MODELS/DESTHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/DESTHITI.MOD create mode 100644 CONTENT/BT3025/MODELS/DFLTROLE.MOD create mode 100644 CONTENT/BT3025/MODELS/DG100.MOD create mode 100644 CONTENT/BT3025/MODELS/DG100A.MOD create mode 100644 CONTENT/BT3025/MODELS/DHILLG1.MOD create mode 100644 CONTENT/BT3025/MODELS/DHILLG2.MOD create mode 100644 CONTENT/BT3025/MODELS/DHILLG3.MOD create mode 100644 CONTENT/BT3025/MODELS/DISH.MOD create mode 100644 CONTENT/BT3025/MODELS/DMG.BLD create mode 100644 CONTENT/BT3025/MODELS/DOZER.MOD create mode 100644 CONTENT/BT3025/MODELS/DRESF.MOD create mode 100644 CONTENT/BT3025/MODELS/DSKY.MOD create mode 100644 CONTENT/BT3025/MODELS/DTARMAC.MOD create mode 100644 CONTENT/BT3025/MODELS/DUMB.MOD create mode 100644 CONTENT/BT3025/MODELS/DUMB2.SUB create mode 100644 CONTENT/BT3025/MODELS/DUMB4.SUB create mode 100644 CONTENT/BT3025/MODELS/DUMB6.SUB create mode 100644 CONTENT/BT3025/MODELS/ERLLASER.SUB create mode 100644 CONTENT/BT3025/MODELS/ERMLASER.SUB create mode 100644 CONTENT/BT3025/MODELS/ERPPC.SUB create mode 100644 CONTENT/BT3025/MODELS/ERSLASER.SUB create mode 100644 CONTENT/BT3025/MODELS/EXPLODE.MOD create mode 100644 CONTENT/BT3025/MODELS/EXPLODE.ONL create mode 100644 CONTENT/BT3025/MODELS/FD1.MOD create mode 100644 CONTENT/BT3025/MODELS/FD2.MOD create mode 100644 CONTENT/BT3025/MODELS/FD3.MOD create mode 100644 CONTENT/BT3025/MODELS/FD4.MOD create mode 100644 CONTENT/BT3025/MODELS/FIND.TXT create mode 100644 CONTENT/BT3025/MODELS/FIRDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/FIRTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/FL1.MOD create mode 100644 CONTENT/BT3025/MODELS/FP0.MOD create mode 100644 CONTENT/BT3025/MODELS/FP0D.MOD create mode 100644 CONTENT/BT3025/MODELS/FP1.MOD create mode 100644 CONTENT/BT3025/MODELS/FP2.MOD create mode 100644 CONTENT/BT3025/MODELS/FP2D.MOD create mode 100644 CONTENT/BT3025/MODELS/FP3.MOD create mode 100644 CONTENT/BT3025/MODELS/FT1.MOD create mode 100644 CONTENT/BT3025/MODELS/FT2.MOD create mode 100644 CONTENT/BT3025/MODELS/GAUSSRFL.SUB create mode 100644 CONTENT/BT3025/MODELS/GD1.MOD create mode 100644 CONTENT/BT3025/MODELS/GD2.MOD create mode 100644 CONTENT/BT3025/MODELS/GD3.MOD create mode 100644 CONTENT/BT3025/MODELS/GD4.MOD create mode 100644 CONTENT/BT3025/MODELS/GD5.MOD create mode 100644 CONTENT/BT3025/MODELS/GENRATOR.SUB create mode 100644 CONTENT/BT3025/MODELS/GNDHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/GNR.MOD create mode 100644 CONTENT/BT3025/MODELS/GRND100.MOD create mode 100644 CONTENT/BT3025/MODELS/GTARMAC.MOD create mode 100644 CONTENT/BT3025/MODELS/GYRO.SUB create mode 100644 CONTENT/BT3025/MODELS/HARASSER.MOD create mode 100644 CONTENT/BT3025/MODELS/HC1.MOD create mode 100644 CONTENT/BT3025/MODELS/HC2.MOD create mode 100644 CONTENT/BT3025/MODELS/HEATSNK.SUB create mode 100644 CONTENT/BT3025/MODELS/HILLA.MOD create mode 100644 CONTENT/BT3025/MODELS/HILLC.MOD create mode 100644 CONTENT/BT3025/MODELS/HILLG1.MOD create mode 100644 CONTENT/BT3025/MODELS/HILLG2.MOD create mode 100644 CONTENT/BT3025/MODELS/HILLG3.MOD create mode 100644 CONTENT/BT3025/MODELS/HL1.MOD create mode 100644 CONTENT/BT3025/MODELS/HL2.MOD create mode 100644 CONTENT/BT3025/MODELS/HN1.MOD create mode 100644 CONTENT/BT3025/MODELS/HOSTAGE.MOD create mode 100644 CONTENT/BT3025/MODELS/HUD.SUB create mode 100644 CONTENT/BT3025/MODELS/HUMMER.MOD create mode 100644 CONTENT/BT3025/MODELS/HUT.MOD create mode 100644 CONTENT/BT3025/MODELS/HWZ.MOD create mode 100644 CONTENT/BT3025/MODELS/ICONBLH.MOD create mode 100644 CONTENT/BT3025/MODELS/ICONJAK.MOD create mode 100644 CONTENT/BT3025/MODELS/ICONLOK.MOD create mode 100644 CONTENT/BT3025/MODELS/ICONOWN.MOD create mode 100644 CONTENT/BT3025/MODELS/ICONTHR.DMG create mode 100644 CONTENT/BT3025/MODELS/ICONTHR.MOD create mode 100644 CONTENT/BT3025/MODELS/ICONTHRD.MOD create mode 100644 CONTENT/BT3025/MODELS/ICONVUL.DMG create mode 100644 CONTENT/BT3025/MODELS/ICONVUL.MOD create mode 100644 CONTENT/BT3025/MODELS/JAKDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/JAKTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/KURITA.MOD create mode 100644 CONTENT/BT3025/MODELS/LASER.MOD create mode 100644 CONTENT/BT3025/MODELS/LLASER.SUB create mode 100644 CONTENT/BT3025/MODELS/LNTRK1.MOD create mode 100644 CONTENT/BT3025/MODELS/LOK1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/LOK1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/LOK2DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/LOK2THR.CTL create mode 100644 CONTENT/BT3025/MODELS/LOKDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/LOKDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/LOKI.SUB create mode 100644 CONTENT/BT3025/MODELS/LOKTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/LRM.MOD create mode 100644 CONTENT/BT3025/MODELS/LRM10.SUB create mode 100644 CONTENT/BT3025/MODELS/LRM15.SUB create mode 100644 CONTENT/BT3025/MODELS/LRM20.SUB create mode 100644 CONTENT/BT3025/MODELS/LRM5.SUB create mode 100644 CONTENT/BT3025/MODELS/LRMCARRY.MOD create mode 100644 CONTENT/BT3025/MODELS/LRMLANCH.SUB create mode 100644 CONTENT/BT3025/MODELS/LZRHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/LZRHITI.MOD create mode 100644 CONTENT/BT3025/MODELS/MACHGUN.SUB create mode 100644 CONTENT/BT3025/MODELS/MAD.DMG create mode 100644 CONTENT/BT3025/MODELS/MAD1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/MAD1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/MAD2DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/MAD2THR.CTL create mode 100644 CONTENT/BT3025/MODELS/MADDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/MADDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/MADTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/MAJHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/MECHALRM.MOD create mode 100644 CONTENT/BT3025/MODELS/MECHDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/MECHMOVR.MOD create mode 100644 CONTENT/BT3025/MODELS/MED.DMG create mode 100644 CONTENT/BT3025/MODELS/MEDDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/MGHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/MGHITI.MOD create mode 100644 CONTENT/BT3025/MODELS/MINHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/MLASER.SUB create mode 100644 CONTENT/BT3025/MODELS/MSL.DMG create mode 100644 CONTENT/BT3025/MODELS/MSL.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLBASE.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLG.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLH.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLHITI.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLR.DMG create mode 100644 CONTENT/BT3025/MODELS/MSLR.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLRB.MOD create mode 100644 CONTENT/BT3025/MODELS/MSLROAD1.MOD create mode 100644 CONTENT/BT3025/MODELS/MYOMERS.SUB create mode 100644 CONTENT/BT3025/MODELS/NORETURN.MOD create mode 100644 CONTENT/BT3025/MODELS/NRK.MOD create mode 100644 CONTENT/BT3025/MODELS/NRK10.SUB create mode 100644 CONTENT/BT3025/MODELS/NRK15.SUB create mode 100644 CONTENT/BT3025/MODELS/NRK20.SUB create mode 100644 CONTENT/BT3025/MODELS/NRK5.SUB create mode 100644 CONTENT/BT3025/MODELS/NTR.MOD create mode 100644 CONTENT/BT3025/MODELS/OLDCON.SUB create mode 100644 CONTENT/BT3025/MODELS/OLDGEN.SUB create mode 100644 CONTENT/BT3025/MODELS/OLDLOKI.SUB create mode 100644 CONTENT/BT3025/MODELS/OWN1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/OWN1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/OWNDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/OWNDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/OWNTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/PDSH.MOD create mode 100644 CONTENT/BT3025/MODELS/PGN.DMG create mode 100644 CONTENT/BT3025/MODELS/PGN.MOD create mode 100644 CONTENT/BT3025/MODELS/PLAYER.MOD create mode 100644 CONTENT/BT3025/MODELS/PLIT.MOD create mode 100644 CONTENT/BT3025/MODELS/PPC.SUB create mode 100644 CONTENT/BT3025/MODELS/PPCHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/PPCHITI.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE1.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE2.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE3.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE4.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE5.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE6.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE7.MOD create mode 100644 CONTENT/BT3025/MODELS/PROFILE8.MOD create mode 100644 CONTENT/BT3025/MODELS/PROJTILE.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN1.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN2.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN3.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN4.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN5.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN6.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN7.MOD create mode 100644 CONTENT/BT3025/MODELS/PWIN8.MOD create mode 100644 CONTENT/BT3025/MODELS/RAPDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/RAPDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/RAPTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/RAVFLOOR.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET1.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET2.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET3.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET4.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET5.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET6.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET7.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVINET8.MOD create mode 100644 CONTENT/BT3025/MODELS/RAVWIN.MOD create mode 100644 CONTENT/BT3025/MODELS/RB1.MOD create mode 100644 CONTENT/BT3025/MODELS/RB2.MOD create mode 100644 CONTENT/BT3025/MODELS/RB3.MOD create mode 100644 CONTENT/BT3025/MODELS/RB4.MOD create mode 100644 CONTENT/BT3025/MODELS/RB5.MOD create mode 100644 CONTENT/BT3025/MODELS/RB6.MOD create mode 100644 CONTENT/BT3025/MODELS/RD1.MOD create mode 100644 CONTENT/BT3025/MODELS/RD2.MOD create mode 100644 CONTENT/BT3025/MODELS/RESERVE.SUB create mode 100644 CONTENT/BT3025/MODELS/RESULT.TXT create mode 100644 CONTENT/BT3025/MODELS/RESULT2.TXT create mode 100644 CONTENT/BT3025/MODELS/RK1.MOD create mode 100644 CONTENT/BT3025/MODELS/RK2.MOD create mode 100644 CONTENT/BT3025/MODELS/RK3.MOD create mode 100644 CONTENT/BT3025/MODELS/RK4.MOD create mode 100644 CONTENT/BT3025/MODELS/RK5.MOD create mode 100644 CONTENT/BT3025/MODELS/RK6.MOD create mode 100644 CONTENT/BT3025/MODELS/RK7.MOD create mode 100644 CONTENT/BT3025/MODELS/ROMMEL.MOD create mode 100644 CONTENT/BT3025/MODELS/RWD.MOD create mode 100644 CONTENT/BT3025/MODELS/RWIN1.MOD create mode 100644 CONTENT/BT3025/MODELS/SAW.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1B.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1C.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1D.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1E.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1N.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1S.MOD create mode 100644 CONTENT/BT3025/MODELS/SB1W.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2B.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2C.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2D.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2E.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2N.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2S.MOD create mode 100644 CONTENT/BT3025/MODELS/SB2W.MOD create mode 100644 CONTENT/BT3025/MODELS/SB3E.MOD create mode 100644 CONTENT/BT3025/MODELS/SB3N.MOD create mode 100644 CONTENT/BT3025/MODELS/SB3S.MOD create mode 100644 CONTENT/BT3025/MODELS/SB3W.MOD create mode 100644 CONTENT/BT3025/MODELS/SB4E.MOD create mode 100644 CONTENT/BT3025/MODELS/SB4N.MOD create mode 100644 CONTENT/BT3025/MODELS/SB4S.MOD create mode 100644 CONTENT/BT3025/MODELS/SB4W.MOD create mode 100644 CONTENT/BT3025/MODELS/SEMI.MOD create mode 100644 CONTENT/BT3025/MODELS/SEMIRIG.MOD create mode 100644 CONTENT/BT3025/MODELS/SENSOR.SUB create mode 100644 CONTENT/BT3025/MODELS/SKY.MOD create mode 100644 CONTENT/BT3025/MODELS/SL2.MOD create mode 100644 CONTENT/BT3025/MODELS/SLASER.SUB create mode 100644 CONTENT/BT3025/MODELS/SLT.MOD create mode 100644 CONTENT/BT3025/MODELS/SML.DMG create mode 100644 CONTENT/BT3025/MODELS/SMLDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/SN1.MOD create mode 100644 CONTENT/BT3025/MODELS/SN2.MOD create mode 100644 CONTENT/BT3025/MODELS/SN4.MOD create mode 100644 CONTENT/BT3025/MODELS/SND1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/SND1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/SND2DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/SND2THR.CTL create mode 100644 CONTENT/BT3025/MODELS/SNDDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/SNDDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/SNDTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/SNH.MOD create mode 100644 CONTENT/BT3025/MODELS/SNTK1.MOD create mode 100644 CONTENT/BT3025/MODELS/SR1E.MOD create mode 100644 CONTENT/BT3025/MODELS/SR1N.MOD create mode 100644 CONTENT/BT3025/MODELS/SR1S.MOD create mode 100644 CONTENT/BT3025/MODELS/SR1W.MOD create mode 100644 CONTENT/BT3025/MODELS/SRC1NE.MOD create mode 100644 CONTENT/BT3025/MODELS/SRC1NW.MOD create mode 100644 CONTENT/BT3025/MODELS/SRC1SE.MOD create mode 100644 CONTENT/BT3025/MODELS/SRC1SW.MOD create mode 100644 CONTENT/BT3025/MODELS/SRCHLITE.SUB create mode 100644 CONTENT/BT3025/MODELS/SRM.MOD create mode 100644 CONTENT/BT3025/MODELS/SRM2.SUB create mode 100644 CONTENT/BT3025/MODELS/SRM4.SUB create mode 100644 CONTENT/BT3025/MODELS/SRM6.SUB create mode 100644 CONTENT/BT3025/MODELS/SRMCARRY.MOD create mode 100644 CONTENT/BT3025/MODELS/ST1.MOD create mode 100644 CONTENT/BT3025/MODELS/STATE.RST create mode 100644 CONTENT/BT3025/MODELS/STB.MOD create mode 100644 CONTENT/BT3025/MODELS/STEPHIT.MOD create mode 100644 CONTENT/BT3025/MODELS/STF.MOD create mode 100644 CONTENT/BT3025/MODELS/STH.MOD create mode 100644 CONTENT/BT3025/MODELS/STIDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/STIDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/STITHR.CTL create mode 100644 CONTENT/BT3025/MODELS/STRIKER.MOD create mode 100644 CONTENT/BT3025/MODELS/STRK.MOD create mode 100644 CONTENT/BT3025/MODELS/STRK2.SUB create mode 100644 CONTENT/BT3025/MODELS/STRK4.SUB create mode 100644 CONTENT/BT3025/MODELS/STRK6.SUB create mode 100644 CONTENT/BT3025/MODELS/STS.MOD create mode 100644 CONTENT/BT3025/MODELS/STT.MOD create mode 100644 CONTENT/BT3025/MODELS/SUB.BLD create mode 100644 CONTENT/BT3025/MODELS/SV2.MOD create mode 100644 CONTENT/BT3025/MODELS/SV2B.MOD create mode 100644 CONTENT/BT3025/MODELS/SV2C.MOD create mode 100644 CONTENT/BT3025/MODELS/SV2D.MOD create mode 100644 CONTENT/BT3025/MODELS/SV3.MOD create mode 100644 CONTENT/BT3025/MODELS/SV3B.MOD create mode 100644 CONTENT/BT3025/MODELS/SV3C.MOD create mode 100644 CONTENT/BT3025/MODELS/SV3D.MOD create mode 100644 CONTENT/BT3025/MODELS/SW1.MOD create mode 100644 CONTENT/BT3025/MODELS/SW2.MOD create mode 100644 CONTENT/BT3025/MODELS/SW3.MOD create mode 100644 CONTENT/BT3025/MODELS/SW4.MOD create mode 100644 CONTENT/BT3025/MODELS/SW5.MOD create mode 100644 CONTENT/BT3025/MODELS/SW6.MOD create mode 100644 CONTENT/BT3025/MODELS/SWIFTWND.MOD create mode 100644 CONTENT/BT3025/MODELS/TEST.TXT create mode 100644 CONTENT/BT3025/MODELS/TEXT.TXT create mode 100644 CONTENT/BT3025/MODELS/THERMAL.SUB create mode 100644 CONTENT/BT3025/MODELS/THR.DMG create mode 100644 CONTENT/BT3025/MODELS/THR1DEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/THR1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/THR1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/THR6DEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/THR6DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/THR6THR.CTL create mode 100644 CONTENT/BT3025/MODELS/THRCTL.BLD create mode 100644 CONTENT/BT3025/MODELS/THRDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/THRDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/THRDMGRD.EXP create mode 100644 CONTENT/BT3025/MODELS/THRTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/TK1.MOD create mode 100644 CONTENT/BT3025/MODELS/TM1.MOD create mode 100644 CONTENT/BT3025/MODELS/TM2.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC1.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC2.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC3.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC4.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC5.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC6.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC7.MOD create mode 100644 CONTENT/BT3025/MODELS/TMC8.MOD create mode 100644 CONTENT/BT3025/MODELS/TNT.MOD create mode 100644 CONTENT/BT3025/MODELS/TORSO.SUB create mode 100644 CONTENT/BT3025/MODELS/TORSOLMT.SUB create mode 100644 CONTENT/BT3025/MODELS/TREE.MOD create mode 100644 CONTENT/BT3025/MODELS/TRK.DMG create mode 100644 CONTENT/BT3025/MODELS/TRK1.MOD create mode 100644 CONTENT/BT3025/MODELS/TRK3.MOD create mode 100644 CONTENT/BT3025/MODELS/TRK4.MOD create mode 100644 CONTENT/BT3025/MODELS/TRKDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/TT1.MOD create mode 100644 CONTENT/BT3025/MODELS/TT2.MOD create mode 100644 CONTENT/BT3025/MODELS/TWR.DMG create mode 100644 CONTENT/BT3025/MODELS/TWR.MOD create mode 100644 CONTENT/BT3025/MODELS/TWRDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/VEHICLE.TBL create mode 100644 CONTENT/BT3025/MODELS/VUL1DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/VUL1THR.CTL create mode 100644 CONTENT/BT3025/MODELS/VUL2DMG.EXP create mode 100644 CONTENT/BT3025/MODELS/VUL2THR.CTL create mode 100644 CONTENT/BT3025/MODELS/VULDEAD.MOD create mode 100644 CONTENT/BT3025/MODELS/VULDMG.EXP create mode 100644 CONTENT/BT3025/MODELS/VULTHR.CTL create mode 100644 CONTENT/BT3025/MODELS/WALL1.MOD create mode 100644 CONTENT/BT3025/MODELS/WALL10K.MOD create mode 100644 CONTENT/BT3025/MODELS/WALL2.MOD create mode 100644 CONTENT/BT3025/MODELS/WALL3.MOD create mode 100644 CONTENT/BT3025/MODELS/WL1.MOD create mode 100644 CONTENT/BT3025/MODELS/WL2.MOD create mode 100644 CONTENT/BT3025/MODELS/WL3.MOD create mode 100644 CONTENT/BT3025/MODELS/WL4.MOD create mode 100644 CONTENT/BT3025/MODELS/WL5.MOD create mode 100644 CONTENT/BT3025/MODELS/WL6.MOD create mode 100644 CONTENT/BT3025/MODELS/WL7.MOD create mode 100644 CONTENT/BT3025/MODELS/WL8.MOD create mode 100644 CONTENT/BT3025/MODELS/WL9.MOD create mode 100644 CONTENT/BT3025/MODELS/WNDSFX01.MOD create mode 100644 CONTENT/BT3025/MODELS/WNDSFX02.MOD create mode 100644 CONTENT/BT3025/MODELS/WNDSFX03.MOD create mode 100644 CONTENT/BT3025/MODELS/WOLF.MOD create mode 100644 CONTENT/BT3025/MODELS/WPN.BLD create mode 100644 CONTENT/BT3025/MODELS/WPNDMG.TBL create mode 100644 CONTENT/BT3025/MODELS/WST.MOD create mode 100644 CONTENT/BT3025/NEWSTUFF.BLD create mode 100644 CONTENT/BT3025/NULL create mode 100644 CONTENT/BT3025/RESULT2.TXT create mode 100644 CONTENT/BT3025/SHOWENV.BAT create mode 100644 CONTENT/BT3025/SOLIDS/AB01_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AB02_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AB03_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AB04_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AB05_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AB09_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ADWLK1~1.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ADWLK2~1.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ADWLK3~1.SLD create mode 100644 CONTENT/BT3025/SOLIDS/APC.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AR02_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AR04_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ARBAN_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ARENA1.XST create mode 100644 CONTENT/BT3025/SOLIDS/ARENA2.XST create mode 100644 CONTENT/BT3025/SOLIDS/ARENA3.XST create mode 100644 CONTENT/BT3025/SOLIDS/ARLID_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ARMRMOVR.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ARTRUCKS.XST create mode 100644 CONTENT/BT3025/SOLIDS/AVA_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AW03_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AW05_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/AWBOX_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BAC1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BCOR1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BCOR2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BDET4_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLANK.XST create mode 100644 CONTENT/BT3025/SOLIDS/BLD03_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLD04_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLD06_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLD20_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLD24_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLD26_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLD27_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BLH_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BNK_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BPIP1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BULLDOG.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BUTTEA_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BUTTEB_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BUTTEC_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BUTTED_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BUTTEE_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/BWLK1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/CALPB_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/CALP_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/CAVERN.XST create mode 100644 CONTENT/BT3025/SOLIDS/CITY1.XST create mode 100644 CONTENT/BT3025/SOLIDS/COMTRUCK.SLD create mode 100644 CONTENT/BT3025/SOLIDS/COOLANT.SLD create mode 100644 CONTENT/BT3025/SOLIDS/CRT_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/DBASE.XST create mode 100644 CONTENT/BT3025/SOLIDS/DES.XST create mode 100644 CONTENT/BT3025/SOLIDS/DISH_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/DOZER.SLD create mode 100644 CONTENT/BT3025/SOLIDS/FIR_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/FL1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/FP2D_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/FP2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/FP3_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/FRSTRM.XST create mode 100644 CONTENT/BT3025/SOLIDS/FT1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/FT2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GD1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GD2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GD3_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GD4_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GD5_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GNR_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GR100ACV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GR100COL.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GR100_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/GRASS.XST create mode 100644 CONTENT/BT3025/SOLIDS/HARASSER.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HC1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HC2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLA_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLB_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLC_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLG1CO.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLG1_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLG2CO.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLG2_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLG3CO.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HILLG3_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HL1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HN1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HUMMER.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HUT_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/HWZ_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/JAK_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/JAX1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/JAX2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/LOK_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/LRMCARRY.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MAD_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MECHMOVR.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MSLBS_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MSLG_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MSLH_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MSLRB_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MSLR_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/MSL_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/OWN_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/PDSH_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/PGN_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/PLIT_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/POLAR1.XST create mode 100644 CONTENT/BT3025/SOLIDS/POLAR2.XST create mode 100644 CONTENT/BT3025/SOLIDS/POLAR3.XST create mode 100644 CONTENT/BT3025/SOLIDS/POLAR4.XST create mode 100644 CONTENT/BT3025/SOLIDS/RAP_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/RAV.XST create mode 100644 CONTENT/BT3025/SOLIDS/RAV1.XST create mode 100644 CONTENT/BT3025/SOLIDS/RFLOOR.SLD create mode 100644 CONTENT/BT3025/SOLIDS/RFLOOR_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/RK5_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/RK6_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/RK7_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ROMMEL.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SAW_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1B_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1C_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1D_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1E_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1N_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1S_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1W_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2B_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2C_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2D_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2E_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2N_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2S_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2W_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB3E_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB3N_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB3S_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB3W_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB4E_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB4N_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB4S_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SB4W_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SEMI.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SEMIRIG.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SL2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SN1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SND_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SNH_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SR1E_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SR1N_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SR1S_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SR1W_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SRC1NE_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SRC1NW_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SRC1SE_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SRC1SW_C.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SRMCARRY.SLD create mode 100644 CONTENT/BT3025/SOLIDS/ST1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/STATE.RST create mode 100644 CONTENT/BT3025/SOLIDS/STB_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/STF_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/STI_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/STRIKER.SLD create mode 100644 CONTENT/BT3025/SOLIDS/STS_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV2B_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV2C_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV2D_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV3B_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV3C_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV3D_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SV3_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SW1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SW2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SW3_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SW4_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SW5_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SW6_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/SWIFTWND.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TEST.XST create mode 100644 CONTENT/BT3025/SOLIDS/THR_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TK1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TNT_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TREE_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TRK1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TRK3_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TRK4_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TT1_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TT2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/TWR_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/VUL_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WALL10K.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WL2_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WL4_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WL5_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WL6_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WL7_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WL9_CV.SLD create mode 100644 CONTENT/BT3025/SOLIDS/WST_CV.SLD create mode 100644 CONTENT/BT3025/TEST.BAT create mode 100644 CONTENT/BT3025/VIDEO/AUTOARM.SKL create mode 100644 CONTENT/BT3025/VIDEO/AUTODARM.SKL create mode 100644 CONTENT/BT3025/VIDEO/AVX2SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/AVXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/BAXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/BLXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/BUILD/APCS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/APCS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/ARMRS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/ARMRS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BACKUP/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BLD08_LP.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BUILDBAS.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BUILDGEN.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BUILDLGO.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BUILDTEX.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BULLS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/BULLS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/CALIOPE.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/CALP_LP.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/COMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/COMS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/COOLS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/COOLS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DBASE.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DCLOUDS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DISH_LP.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/APCS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/ARMRS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/BTRAVWIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/BULLS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/CALIOPE.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/COMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/COOLS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/DCLOUDS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/DOZERS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/HARASS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/HUMMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/LRMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/MECHMOVS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/ROMMELS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/SEMIRIGS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/SEMIS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/SRMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/STRIKERS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DIVISION.SAV/SWIFTS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DOZERS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/DOZERS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/BLD08_LP.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/BTRAVWIN.VMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/BUILDBAS.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/BUILDGEN.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/BUILDLGO.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/BUILDTEX.BAT create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/CALP_LP.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/DISH_LP.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/EDITBACK/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/HARASS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/HARASS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/HUMMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/HUMMS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/LRMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/LRMS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/MECHMOVS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/MECHMOVS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/ROMMELS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/ROMMELS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SEMIRIGS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SEMIRIGS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SEMIS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SEMIS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SRMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SRMS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/STATE.RST create mode 100644 CONTENT/BT3025/VIDEO/BUILD/STRIKERS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/STRIKERS.VGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SWIFTS.BGF create mode 100644 CONTENT/BT3025/VIDEO/BUILD/SWIFTS.VGF create mode 100644 CONTENT/BT3025/VIDEO/DAFC.PFX create mode 100644 CONTENT/BT3025/VIDEO/DBIGBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/DDAM1.PFX create mode 100644 CONTENT/BT3025/VIDEO/DDAM2.PFX create mode 100644 CONTENT/BT3025/VIDEO/DDAM3.PFX create mode 100644 CONTENT/BT3025/VIDEO/DDAM4.PFX create mode 100644 CONTENT/BT3025/VIDEO/DDAM5.PFX create mode 100644 CONTENT/BT3025/VIDEO/DDTHSMK.PFX create mode 100644 CONTENT/BT3025/VIDEO/DLRMTAIL.PFX create mode 100644 CONTENT/BT3025/VIDEO/DMEDBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/DMISSING.PFX create mode 100644 CONTENT/BT3025/VIDEO/DNBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/DSMLBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/DSRM.PFX create mode 100644 CONTENT/BT3025/VIDEO/DTRKBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/DTRKBURN.PFX create mode 100644 CONTENT/BT3025/VIDEO/FIRXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/FLUSH.PFX create mode 100644 CONTENT/BT3025/VIDEO/GEO/AB07D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AB08.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AB09D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AB10D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ABG.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ACT01.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ACT02.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ACT03.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ACT04.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ACT05.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ADSUP1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ADSUP2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ADWLK1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ADWLK2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ADWLK3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/APCS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AR01_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AR03_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AR04_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARBAN1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARBAN2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARBAN3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARBAN4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARBAN5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARBAN6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARCLD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/AVA_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/BLH_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/FIR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/LOK_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/MAD_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/OWN_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/RAP_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/SND_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/STI_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/THR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA/VUL_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/AVA_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/BLH_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/FIR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/LOK_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/MAD_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/OWN_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/RAP_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/SND_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/STI_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/THR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARENA3/VUL_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARHORIZ.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARLID.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ARMRS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_LBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_LDOO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_LFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_LITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_LOTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_RBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_RDOO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_RFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_RITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVA_ROTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AVX_TOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AW01.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AW02.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AW03.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AW05.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AWBOX1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/AWWLK1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BAC1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BALL1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BALL2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BALL3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BALL4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BBG.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BCOR1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BCOR2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BDET1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BDET2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BDET3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BDET4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BDET6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BLD08_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BLHDLARM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BLHDRARM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BLUEBEAM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BNKD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BNK_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BNK_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BPIP1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BPIP1D.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BULLET.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BULLS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/BWLK1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CALP_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAMPOS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/AVA_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/BLH_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/FIR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/LOK_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/MAD_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/OWN_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/RAP_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/SND_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/STI_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/THR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CAVERN/VUL_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CH1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CH2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/COMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/COOLS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CRTD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/CTAR_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/D1DIRT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DAY/DIVISION.SAV/DSKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DAY/DSKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DAY/DSKY.BMF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DAY/SPOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DECLOUDS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DISH_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/ARMRS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/BLD08_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/CALP_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/COMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/CTAR_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/D1DIRT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/DISH_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/DTAR_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/RAVFLOOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/SEMIRIGS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/TREESH.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DIVISION.SAV/TRUNK.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DOZERS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/DTAR_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/EVENING/DSKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/EVENING/SKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/EVENING/SPOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/EVENING/SPOT.BU create mode 100644 CONTENT/BT3025/VIDEO/GEO/EXDISK_A.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/EXDISK_B.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/EXDISK_C.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/EXP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FD1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FD2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FD3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FD4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FL1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FLAMEBIG.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FLAMEBIG.VGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FLAMESML.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FLAMESML.VGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FP0_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FP1D.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FP2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FP2_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FT1D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FT1_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FT1_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FT2D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FT2_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/FT2_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/GD5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/GNR_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/GREEBEAM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HARASS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HC1D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HC1_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HC2D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HC2_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HN1_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HN1_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HOTBOX.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HUMMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HUT_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/HUT_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/JAX1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/JAX1D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/JAX1_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/JAX2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/JAX2D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/JAX2_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LDBR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LOKDLIGH.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LOKDRARM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LOKDRGUN.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LOK_LIGH.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LOK_MSL.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LOX_TOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/LRMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_LBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_LDOO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_LFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_LITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_LOTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_RBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_RDOO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_RFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_RITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAD_ROTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_LBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_LFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_LITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_LOTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_RBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_RFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_RITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MAX_ROTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MECHMOVS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MISSILE.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MORNING/DSKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MORNING/RAVFLOOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MORNING/SEMIS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MORNING/SKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MORNING/SPOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLB_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLG_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLG_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLH_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLH_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLRD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLR_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSLR_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MSL_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/MUZFLASH.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/NIGHT/DSKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/NIGHT/SKY.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/NIGHT/SPOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/NTR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWNDCAM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWN_LANT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWN_RANT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWX_LBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWX_LDLE.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWX_LFTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWX_RBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWX_RDLE.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/OWX_RFTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PDSD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PDSH_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PDSH_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PGNDBASE.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PGND_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PGN_BASE.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PGN_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE7.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLACE8.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLIT_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PLTD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME7.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PNAME8.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/AVA_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/BLH_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/FIR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/LOK_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/MAD_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/OWN_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/RAP_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/SND_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/STI_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/THR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/POLAR/VUL_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE7.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PROFILE8.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN7.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/PWIN8.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/AVA_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/BLH_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/FIR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/LOK_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/MAD_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/OWN_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/RAP_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/SND_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/STI_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/THR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV/VUL_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/AVA_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/BLH_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/FIR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/LOK_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/MAD_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/OWN_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/RAP_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/SND_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/STI_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/THR_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAV1/VUL_TSHD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAVFLOOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RB6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RD1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RD2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RED_BEAM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ROMMELS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RWD.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/RWIN1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SAW.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1B.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1C.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1D.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1E.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1N.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1S.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB1W.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2B.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2C.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2D.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2E.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2N.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2S.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB2W.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB3E.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB3N.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB3S.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB3W.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB4E.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB4N.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB4S.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SB4W.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SEMIRIGS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SEMIS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SHOCK.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SL2D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SLD2_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SLT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SMK_A.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SMK_B.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SMK_C.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SN1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SN2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SN4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SND_DOOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SND_RARM.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SNHD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SNH_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SNX_TOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SPK1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SPK2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SPOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SR1E.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SR1N.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SR1S.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SR1W.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SRMS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/ST1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/STF.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/STRIKERS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV2BR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV2BS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV2DR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV2DS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV2R.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV2S.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3BR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3BS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3CR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3CS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3DR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3DS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3R.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SV3S.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SW1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SW2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SW3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SW4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SW5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SW6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/SWIFTS.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/THRDBR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/THXDMSL.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/THX_DOOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/THX_TOR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC1.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC2.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC3.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC3_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC4.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC4_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC5.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC5_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC6.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC6_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC7.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC7_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC8.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMC8_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMSM_A.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMSM_B.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMSM_C.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMS_A.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMS_B.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TMS_C.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TREESH.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TRK1D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TRK1_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TRK3D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TRK3_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TRK4D_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TRK4_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TRUNK.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TSPHERE.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TWRD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TWR_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/TWR_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_LBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_LDDO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_LFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_LITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_LOTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_LUDO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_RBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_RDDO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_RFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_RITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_ROTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUL_RUDO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_LBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_LFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_LITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_LOTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_RBTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_RFOT.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_RITO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/VUX_ROTO.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/WSTD_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/WST_FR.BGF create mode 100644 CONTENT/BT3025/VIDEO/GEO/WST_LP.BGF create mode 100644 CONTENT/BT3025/VIDEO/IDAM1.PFX create mode 100644 CONTENT/BT3025/VIDEO/IDAM2.PFX create mode 100644 CONTENT/BT3025/VIDEO/IDAM3.PFX create mode 100644 CONTENT/BT3025/VIDEO/IDAM4.PFX create mode 100644 CONTENT/BT3025/VIDEO/IDAM5.PFX create mode 100644 CONTENT/BT3025/VIDEO/JAKSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/JAXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/LASARM.SKL create mode 100644 CONTENT/BT3025/VIDEO/LOX1SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/LOXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVAFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/AVX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLHFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BLX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BMAP.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BTCULT.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BTPOLWIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/BTRAVWIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/CALIOPE.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/DIVISION.SAV/GRASSBU.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/GRASSBU.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/GRASSBU.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DAY/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DBASE.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DIVISION.SAV/CALIOPE.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DIVISION.SAV/DBASE.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DIVISION.SAV/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DIVISION.SAV/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/DUMMY.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/EVENING/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/EVENING/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/EVENING/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/EVENING/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/EVENING/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/EVENING/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIRSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIR_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/FIX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAKSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAK_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/JAX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOKFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/LOX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MADFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MAX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MECHFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MORNING/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MORNING/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MORNING/DIVISION.SAV/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MORNING/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MORNING/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MORNING/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/MORNING/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/NIGHT/DIVISION.SAV/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/NIGHT/DIVISION.SAV/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/NIGHT/GRASS.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/NIGHT/GRASS.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/NIGHT/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/NIGHT/RAVINES.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWNFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/OWX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAPSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAP_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAVBU.VMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAVINES.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/RAX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNDFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/SNX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STIFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STISKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STI_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/STX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THRFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/THX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VULFX.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUXSKIN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BLK7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_BRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_GRY7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_RED7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_TAN7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT0.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT1.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT2.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT3.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT4.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT5.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT6.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAT/VUX_WHT7.BMF create mode 100644 CONTENT/BT3025/VIDEO/MAX1SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/MAX2SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/MAXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/MAXSKIN.ORG create mode 100644 CONTENT/BT3025/VIDEO/NAFC.PFX create mode 100644 CONTENT/BT3025/VIDEO/NBIGBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/NDAM1.PFX create mode 100644 CONTENT/BT3025/VIDEO/NDAM2.PFX create mode 100644 CONTENT/BT3025/VIDEO/NDAM3.PFX create mode 100644 CONTENT/BT3025/VIDEO/NDAM4.PFX create mode 100644 CONTENT/BT3025/VIDEO/NDAM5.PFX create mode 100644 CONTENT/BT3025/VIDEO/NDTHSMK.PFX create mode 100644 CONTENT/BT3025/VIDEO/NLRMTAIL.PFX create mode 100644 CONTENT/BT3025/VIDEO/NMEDBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/NMISSING.PFX create mode 100644 CONTENT/BT3025/VIDEO/NNBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/NSMLBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/NSRM.PFX create mode 100644 CONTENT/BT3025/VIDEO/NTRKBOOM.PFX create mode 100644 CONTENT/BT3025/VIDEO/NTRKBURN.PFX create mode 100644 CONTENT/BT3025/VIDEO/OWXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/PGN.SKL create mode 100644 CONTENT/BT3025/VIDEO/PGND.SKL create mode 100644 CONTENT/BT3025/VIDEO/RESULT2.TXT create mode 100644 CONTENT/BT3025/VIDEO/SHKWAVE.PFX create mode 100644 CONTENT/BT3025/VIDEO/SMLFLASH.PFX create mode 100644 CONTENT/BT3025/VIDEO/SMLSMOKE.PFX create mode 100644 CONTENT/BT3025/VIDEO/SNX2SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/SNXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/STXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/TEX/BUILD/BDLGO128.BAT create mode 100644 CONTENT/BT3025/VIDEO/TEX/BUILD/BUILDLGO.BAT create mode 100644 CONTENT/BT3025/VIDEO/THX1SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/THXSKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/VUL2SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/VUX1SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/VUX2SKIN.DZM create mode 100644 CONTENT/BT3025/VIDEO/VUXSKIN.DZM create mode 100644 CONTENT/BT3025/WATTCP.CFG create mode 100644 CONTENT/MTMCDAI.SYS create mode 100644 CONTENT/RP/$$ARCALL.TMP create mode 100644 CONTENT/RP/32STUB.EXE create mode 100644 CONTENT/RP/ANIM.BAT create mode 100644 CONTENT/RP/ANIMCAM.BAT create mode 100644 CONTENT/RP/ARCALL.BAT create mode 100644 CONTENT/RP/ARCFILES.LST create mode 100644 CONTENT/RP/ARCRP.BAT create mode 100644 CONTENT/RP/AUDIO/AUDIO.INI create mode 100644 CONTENT/RP/AUDIO/AUDIO.RES create mode 100644 CONTENT/RP/AUDIO/AUDIOMR.INI create mode 100644 CONTENT/RP/AUDIO/BARGE.SCP create mode 100644 CONTENT/RP/AUDIO/BLKSPK.SCP create mode 100644 CONTENT/RP/AUDIO/BROCCOLI.SCP create mode 100644 CONTENT/RP/AUDIO/BTLEXT.SCP create mode 100644 CONTENT/RP/AUDIO/BTTLBRG.SCP create mode 100644 CONTENT/RP/AUDIO/BUG.SCP create mode 100644 CONTENT/RP/AUDIO/BURRO.SCP create mode 100644 CONTENT/RP/AUDIO/CHIGGER.SCP create mode 100644 CONTENT/RP/AUDIO/CHUTE.SCP create mode 100644 CONTENT/RP/AUDIO/COLTWR1.SCP create mode 100644 CONTENT/RP/AUDIO/CTMIX.CFG create mode 100644 CONTENT/RP/AUDIO/DARK.SCP create mode 100644 CONTENT/RP/AUDIO/DARKEXT.SCP create mode 100644 CONTENT/RP/AUDIO/DEMOPACK.SCP create mode 100644 CONTENT/RP/AUDIO/DPEXP.SCP create mode 100644 CONTENT/RP/AUDIO/DRAGON.SCP create mode 100644 CONTENT/RP/AUDIO/FULTNK1.SCP create mode 100644 CONTENT/RP/AUDIO/GATOR.SCP create mode 100644 CONTENT/RP/AUDIO/GRUNT.SCP create mode 100644 CONTENT/RP/AUDIO/HVAC1.SCP create mode 100644 CONTENT/RP/AUDIO/HVAC2.SCP create mode 100644 CONTENT/RP/AUDIO/HVAC3.SCP create mode 100644 CONTENT/RP/AUDIO/ICOM.CFG create mode 100644 CONTENT/RP/AUDIO/LASEREXP.SCP create mode 100644 CONTENT/RP/AUDIO/LEPTON.SCP create mode 100644 CONTENT/RP/AUDIO/LSREXPC.SCP create mode 100644 CONTENT/RP/AUDIO/LSREXPI.SCP create mode 100644 CONTENT/RP/AUDIO/LSREXT.SCP create mode 100644 CONTENT/RP/AUDIO/MANTIS.SCP create mode 100644 CONTENT/RP/AUDIO/MTNCDR1.SCP create mode 100644 CONTENT/RP/AUDIO/MTNCDR2.SCP create mode 100644 CONTENT/RP/AUDIO/MTNCDR3.SCP create mode 100644 CONTENT/RP/AUDIO/MTNCDR4.SCP create mode 100644 CONTENT/RP/AUDIO/MTSEXT.SCP create mode 100644 CONTENT/RP/AUDIO/OREDRP1.SCP create mode 100644 CONTENT/RP/AUDIO/OREDRP2.SCP create mode 100644 CONTENT/RP/AUDIO/PCKEXT.SCP create mode 100644 CONTENT/RP/AUDIO/PLYEXT.SCP create mode 100644 CONTENT/RP/AUDIO/PLYINT.SCP create mode 100644 CONTENT/RP/AUDIO/QUARK.SCP create mode 100644 CONTENT/RP/AUDIO/RDBEXT.SCP create mode 100644 CONTENT/RP/AUDIO/REFINERY.SCP create mode 100644 CONTENT/RP/AUDIO/RIPPER.SCP create mode 100644 CONTENT/RP/AUDIO/RIVET.SCP create mode 100644 CONTENT/RP/AUDIO/RIVETEXP.SCP create mode 100644 CONTENT/RP/AUDIO/ROADBLK.SCP create mode 100644 CONTENT/RP/AUDIO/RVTEXPC.SCP create mode 100644 CONTENT/RP/AUDIO/RVTEXPI.SCP create mode 100644 CONTENT/RP/AUDIO/SCORING.SCP create mode 100644 CONTENT/RP/AUDIO/SKEETER.SCP create mode 100644 CONTENT/RP/AUDIO/SKTEXT.SCP create mode 100644 CONTENT/RP/AUDIO/SPITTER.SCP create mode 100644 CONTENT/RP/AUDIO/SYMBOLS.SCP create mode 100644 CONTENT/RP/AUDIO/TEMPLATE.SCP create mode 100644 CONTENT/RP/AUDIO/VCS.CFG create mode 100644 CONTENT/RP/AUDIO/VLEEXT.SCP create mode 100644 CONTENT/RP/AUDIO/VOLE.SCP create mode 100644 CONTENT/RP/AUDIO/VTVLSR.SCP create mode 100644 CONTENT/RP/AUDIO/VTVMNE.SCP create mode 100644 CONTENT/RP/AUDIO/VTVRVT.SCP create mode 100644 CONTENT/RP/AUDIO/WASP.SCP create mode 100644 CONTENT/RP/AUDIO/WELLHD1.SCP create mode 100644 CONTENT/RP/AUDIO/WELLHD2.SCP create mode 100644 CONTENT/RP/AUDIO/WELLHD3.SCP create mode 100644 CONTENT/RP/AUDIO/WELLHD4.SCP create mode 100644 CONTENT/RP/AUTOEXEC.BAT create mode 100644 CONTENT/RP/BLDFILES.LST create mode 100644 CONTENT/RP/BUILD.BAT create mode 100644 CONTENT/RP/BUILD1.BAT create mode 100644 CONTENT/RP/BUILDRES.BAK create mode 100644 CONTENT/RP/BUILDRES.BAT create mode 100644 CONTENT/RP/DEARCRP.BAT create mode 100644 CONTENT/RP/EXCLUDE.LST create mode 100644 CONTENT/RP/FAILURE.LOG create mode 100644 CONTENT/RP/FIND.TXT create mode 100644 CONTENT/RP/FRSTRM.BAT create mode 100644 CONTENT/RP/GAUGE/BP1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/BR1B_GA.GIM create mode 100644 CONTENT/RP/GAUGE/BR1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/BR2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/BR3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/BRE1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/BUTCROSS.PCC create mode 100644 CONTENT/RP/GAUGE/BUTHORN.PCC create mode 100644 CONTENT/RP/GAUGE/BUTPRES1.PCC create mode 100644 CONTENT/RP/GAUGE/BUTPRES2.PCC create mode 100644 CONTENT/RP/GAUGE/BUTPRES3.PCC create mode 100644 CONTENT/RP/GAUGE/BUTPRES4.PCC create mode 100644 CONTENT/RP/GAUGE/BUTPRES5.PCC create mode 100644 CONTENT/RP/GAUGE/BUTPRES6.PCC create mode 100644 CONTENT/RP/GAUGE/BUTZMIN.PCC create mode 100644 CONTENT/RP/GAUGE/BUTZMOUT.PCC create mode 100644 CONTENT/RP/GAUGE/BU_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CAMPAL.PCC create mode 100644 CONTENT/RP/GAUGE/CC1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CFGBOTH.PCC create mode 100644 CONTENT/RP/GAUGE/CFGME.PCC create mode 100644 CONTENT/RP/GAUGE/CFGNONE.PCC create mode 100644 CONTENT/RP/GAUGE/CFGOTHER.PCC create mode 100644 CONTENT/RP/GAUGE/CL1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CLKFONT.PCC create mode 100644 CONTENT/RP/GAUGE/CN1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN3U_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN4_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN5U_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN5_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN6_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CN7U_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CQ1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CQ2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR1A_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR4_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR5_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR6_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CR8_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CRE_GA.GIM create mode 100644 CONTENT/RP/GAUGE/CT1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/D45_GA.GIM create mode 100644 CONTENT/RP/GAUGE/DPACK_GA.BAK create mode 100644 CONTENT/RP/GAUGE/DPACK_GA.GIM create mode 100644 CONTENT/RP/GAUGE/DR1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/DR2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/DRW_GA.GIM create mode 100644 CONTENT/RP/GAUGE/FT1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/GAR1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/GAR2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/GAR_GA.GIM create mode 100644 CONTENT/RP/GAUGE/GAUGE.BAK create mode 100644 CONTENT/RP/GAUGE/GAUGE.GAT create mode 100644 CONTENT/RP/GAUGE/GR1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/GR2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/HV5_GA.GIM create mode 100644 CONTENT/RP/GAUGE/HVE_GA.GIM create mode 100644 CONTENT/RP/GAUGE/L4GAUGE.1 create mode 100644 CONTENT/RP/GAUGE/L4GAUGE.2 create mode 100644 CONTENT/RP/GAUGE/L4GAUGE.GF create mode 100644 CONTENT/RP/GAUGE/L4GAUGE.INI create mode 100644 CONTENT/RP/GAUGE/MD3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/MD4_GA.GIM create mode 100644 CONTENT/RP/GAUGE/ME1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/ME3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/MULE_GA.GIM create mode 100644 CONTENT/RP/GAUGE/MU_GA.GIM create mode 100644 CONTENT/RP/GAUGE/OA1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/OA3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/OAO_GA.GIM create mode 100644 CONTENT/RP/GAUGE/OD3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/PIT1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/PIT2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/PL1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/PM1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/PO_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RF1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RIVET_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RL1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RL2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RL3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RP1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RP2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RP3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/RPSALTB.PCC create mode 100644 CONTENT/RP/GAUGE/RPSCMPB.PCC create mode 100644 CONTENT/RP/GAUGE/RPSCMPE.PCC create mode 100644 CONTENT/RP/GAUGE/RPSCMPN.PCC create mode 100644 CONTENT/RP/GAUGE/RPSCMPS.PCC create mode 100644 CONTENT/RP/GAUGE/RPSCMPW.PCC create mode 100644 CONTENT/RP/GAUGE/RPSREV.PCC create mode 100644 CONTENT/RP/GAUGE/RPSSPDB.PCC create mode 100644 CONTENT/RP/GAUGE/SC500_GA.GIM create mode 100644 CONTENT/RP/GAUGE/SC50_GA.GIM create mode 100644 CONTENT/RP/GAUGE/SDBU.PCC create mode 100644 CONTENT/RP/GAUGE/SDLU.PCC create mode 100644 CONTENT/RP/GAUGE/SDMA.PCC create mode 100644 CONTENT/RP/GAUGE/SDPA.PCC create mode 100644 CONTENT/RP/GAUGE/SDPO.PCC create mode 100644 CONTENT/RP/GAUGE/SDPU.PCC create mode 100644 CONTENT/RP/GAUGE/SDSA.PCC create mode 100644 CONTENT/RP/GAUGE/SDSU.PCC create mode 100644 CONTENT/RP/GAUGE/SECPAL.PCC create mode 100644 CONTENT/RP/GAUGE/SLU.PCC create mode 100644 CONTENT/RP/GAUGE/SMLFONT.PCC create mode 100644 CONTENT/RP/GAUGE/SPO.PCC create mode 100644 CONTENT/RP/GAUGE/SP_GA.GIM create mode 100644 CONTENT/RP/GAUGE/SSA.PCC create mode 100644 CONTENT/RP/GAUGE/SSU.PCC create mode 100644 CONTENT/RP/GAUGE/STING.BAK create mode 100644 CONTENT/RP/GAUGE/STING.GIM create mode 100644 CONTENT/RP/GAUGE/TINYFONT.PCC create mode 100644 CONTENT/RP/GAUGE/TRS_GA.GIM create mode 100644 CONTENT/RP/GAUGE/VCS.CFG create mode 100644 CONTENT/RP/GAUGE/VM1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WH1_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WH2_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WH3_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WH4_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WH5_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WH6_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WH9_GA.GIM create mode 100644 CONTENT/RP/GAUGE/WT1_GA.GIM create mode 100644 CONTENT/RP/GETAUD.BAT create mode 100644 CONTENT/RP/GETVID.BAT create mode 100644 CONTENT/RP/GO.BAT create mode 100644 CONTENT/RP/GRABOPT.BAT create mode 100644 CONTENT/RP/GRABRES.BAT create mode 100644 CONTENT/RP/JOYSTICK.INI create mode 100644 CONTENT/RP/LAST.EGG create mode 100644 CONTENT/RP/MAKEEGG.BAT create mode 100644 CONTENT/RP/MAPS/ALL.ZNE create mode 100644 CONTENT/RP/MAPS/ARENA.CAM create mode 100644 CONTENT/RP/MAPS/BLADE.CAM create mode 100644 CONTENT/RP/MAPS/BLANK.CAM create mode 100644 CONTENT/RP/MAPS/BLANK.SCN create mode 100644 CONTENT/RP/MAPS/BREWERS.CAM create mode 100644 CONTENT/RP/MAPS/BURNT.BAK create mode 100644 CONTENT/RP/MAPS/BURNT.CAM create mode 100644 CONTENT/RP/MAPS/CANAL.MAP create mode 100644 CONTENT/RP/MAPS/CN create mode 100644 CONTENT/RP/MAPS/DR.MAP create mode 100644 CONTENT/RP/MAPS/FIRST.MAP create mode 100644 CONTENT/RP/MAPS/GENE.MAP create mode 100644 CONTENT/RP/MAPS/GREG.MAP create mode 100644 CONTENT/RP/MAPS/HEADMF.CAM create mode 100644 CONTENT/RP/MAPS/HEADOFF.BAK create mode 100644 CONTENT/RP/MAPS/LYZLANE.CAM create mode 100644 CONTENT/RP/MAPS/PAIN.CAM create mode 100644 CONTENT/RP/MAPS/PUCKLAND.CAM create mode 100644 CONTENT/RP/MAPS/PUCKLAND.MAP create mode 100644 CONTENT/RP/MAPS/THIRD.MAP create mode 100644 CONTENT/RP/MAPS/THRDRACE.SCE create mode 100644 CONTENT/RP/MAPS/VCS.CFG create mode 100644 CONTENT/RP/MAPS/YIP.CAM create mode 100644 CONTENT/RP/MENU.BAT create mode 100644 CONTENT/RP/MODELS/2LSRTHR.CTL create mode 100644 CONTENT/RP/MODELS/2RIVTHR.CTL create mode 100644 CONTENT/RP/MODELS/2X6L4.CTL create mode 100644 CONTENT/RP/MODELS/2X6THR.CTL create mode 100644 CONTENT/RP/MODELS/3RIVTHR.CTL create mode 100644 CONTENT/RP/MODELS/3X4L4.CTL create mode 100644 CONTENT/RP/MODELS/3X4THR.CTL create mode 100644 CONTENT/RP/MODELS/4X4L4.CTL create mode 100644 CONTENT/RP/MODELS/4X4THR.CTL create mode 100644 CONTENT/RP/MODELS/BAN.DMG create mode 100644 CONTENT/RP/MODELS/BAN.MOD create mode 100644 CONTENT/RP/MODELS/BARGE.BAK create mode 100644 CONTENT/RP/MODELS/BARGE.DMG create mode 100644 CONTENT/RP/MODELS/BARGE.MOD create mode 100644 CONTENT/RP/MODELS/BARGE.SUB create mode 100644 CONTENT/RP/MODELS/BARGEL4.CTL create mode 100644 CONTENT/RP/MODELS/BARGETHR.CTL create mode 100644 CONTENT/RP/MODELS/BAS.DMG create mode 100644 CONTENT/RP/MODELS/BAS.MOD create mode 100644 CONTENT/RP/MODELS/BAS.SUB create mode 100644 CONTENT/RP/MODELS/BASL4.CTL create mode 100644 CONTENT/RP/MODELS/BASTHR.CTL create mode 100644 CONTENT/RP/MODELS/BAT.DMG create mode 100644 CONTENT/RP/MODELS/BAT.MOD create mode 100644 CONTENT/RP/MODELS/BLKSPK.DMG create mode 100644 CONTENT/RP/MODELS/BLKSPK.MOD create mode 100644 CONTENT/RP/MODELS/BLKSPK.SUB create mode 100644 CONTENT/RP/MODELS/BLKTRN.DMG create mode 100644 CONTENT/RP/MODELS/BLKTRN.MOD create mode 100644 CONTENT/RP/MODELS/BLKTRN.SUB create mode 100644 CONTENT/RP/MODELS/BN1.MOD create mode 100644 CONTENT/RP/MODELS/BP1.MOD create mode 100644 CONTENT/RP/MODELS/BR1.MOD create mode 100644 CONTENT/RP/MODELS/BR1A.MOD create mode 100644 CONTENT/RP/MODELS/BR1B.MOD create mode 100644 CONTENT/RP/MODELS/BR2.MOD create mode 100644 CONTENT/RP/MODELS/BR3.MOD create mode 100644 CONTENT/RP/MODELS/BR4.MOD create mode 100644 CONTENT/RP/MODELS/BRE1.MOD create mode 100644 CONTENT/RP/MODELS/BREW.MOD create mode 100644 CONTENT/RP/MODELS/BROCCOLI.BAK create mode 100644 CONTENT/RP/MODELS/BROCCOLI.DMG create mode 100644 CONTENT/RP/MODELS/BROCCOLI.MOD create mode 100644 CONTENT/RP/MODELS/BROCCOLI.SUB create mode 100644 CONTENT/RP/MODELS/BTTLBRG.BAK create mode 100644 CONTENT/RP/MODELS/BTTLBRG.DMG create mode 100644 CONTENT/RP/MODELS/BTTLBRG.MOD create mode 100644 CONTENT/RP/MODELS/BTTLBRG.SUB create mode 100644 CONTENT/RP/MODELS/BTTLTHR.CTL create mode 100644 CONTENT/RP/MODELS/BUG.BAK create mode 100644 CONTENT/RP/MODELS/BUG.DMG create mode 100644 CONTENT/RP/MODELS/BUG.MOD create mode 100644 CONTENT/RP/MODELS/BUG.SUB create mode 100644 CONTENT/RP/MODELS/BULL.BAK create mode 100644 CONTENT/RP/MODELS/BULL.DMG create mode 100644 CONTENT/RP/MODELS/BULL.MOD create mode 100644 CONTENT/RP/MODELS/BULL.SUB create mode 100644 CONTENT/RP/MODELS/BULLET.MOD create mode 100644 CONTENT/RP/MODELS/BUN.DMG create mode 100644 CONTENT/RP/MODELS/BUN.MOD create mode 100644 CONTENT/RP/MODELS/BURRO.BAK create mode 100644 CONTENT/RP/MODELS/BURRO.DMG create mode 100644 CONTENT/RP/MODELS/BURRO.MOD create mode 100644 CONTENT/RP/MODELS/BURRO.SUB create mode 100644 CONTENT/RP/MODELS/BURROL4.CTL create mode 100644 CONTENT/RP/MODELS/BURROTHR.CTL create mode 100644 CONTENT/RP/MODELS/BUS.DMG create mode 100644 CONTENT/RP/MODELS/BUS.MOD create mode 100644 CONTENT/RP/MODELS/BUS.SUB create mode 100644 CONTENT/RP/MODELS/BUSL4.CTL create mode 100644 CONTENT/RP/MODELS/BUSTHR.CTL create mode 100644 CONTENT/RP/MODELS/BUT.DMG create mode 100644 CONTENT/RP/MODELS/BUT.MOD create mode 100644 CONTENT/RP/MODELS/C8E.MOD create mode 100644 CONTENT/RP/MODELS/CAMERA.MOD create mode 100644 CONTENT/RP/MODELS/CAMPOS.MOD create mode 100644 CONTENT/RP/MODELS/CAP.MOD create mode 100644 CONTENT/RP/MODELS/CC1.MOD create mode 100644 CONTENT/RP/MODELS/CHIGGER.BAK create mode 100644 CONTENT/RP/MODELS/CHIGGER.DMG create mode 100644 CONTENT/RP/MODELS/CHIGGER.MOD create mode 100644 CONTENT/RP/MODELS/CHIGGER.SUB create mode 100644 CONTENT/RP/MODELS/CL1.MOD create mode 100644 CONTENT/RP/MODELS/CL2.MOD create mode 100644 CONTENT/RP/MODELS/CL3.MOD create mode 100644 CONTENT/RP/MODELS/CLD.MOD create mode 100644 CONTENT/RP/MODELS/CN1.MOD create mode 100644 CONTENT/RP/MODELS/CN2.MOD create mode 100644 CONTENT/RP/MODELS/CN3.MOD create mode 100644 CONTENT/RP/MODELS/CN3U.MOD create mode 100644 CONTENT/RP/MODELS/CN4.MOD create mode 100644 CONTENT/RP/MODELS/CN5.MOD create mode 100644 CONTENT/RP/MODELS/CN5N.MOD create mode 100644 CONTENT/RP/MODELS/CN5U.MOD create mode 100644 CONTENT/RP/MODELS/CN6.MOD create mode 100644 CONTENT/RP/MODELS/CN7.MOD create mode 100644 CONTENT/RP/MODELS/CN7U.MOD create mode 100644 CONTENT/RP/MODELS/CQ1.MOD create mode 100644 CONTENT/RP/MODELS/CQ1A.MOD create mode 100644 CONTENT/RP/MODELS/CQ2.MOD create mode 100644 CONTENT/RP/MODELS/CR1.MOD create mode 100644 CONTENT/RP/MODELS/CR1A.MOD create mode 100644 CONTENT/RP/MODELS/CR2.MOD create mode 100644 CONTENT/RP/MODELS/CR3.MOD create mode 100644 CONTENT/RP/MODELS/CR4.MOD create mode 100644 CONTENT/RP/MODELS/CR5.MOD create mode 100644 CONTENT/RP/MODELS/CR5U.MOD create mode 100644 CONTENT/RP/MODELS/CR6.MOD create mode 100644 CONTENT/RP/MODELS/CR7.MOD create mode 100644 CONTENT/RP/MODELS/CR8.MOD create mode 100644 CONTENT/RP/MODELS/CRE.MOD create mode 100644 CONTENT/RP/MODELS/CRP.MOD create mode 100644 CONTENT/RP/MODELS/CT1.MOD create mode 100644 CONTENT/RP/MODELS/D45.MOD create mode 100644 CONTENT/RP/MODELS/DARK.DMG create mode 100644 CONTENT/RP/MODELS/DARK.MOD create mode 100644 CONTENT/RP/MODELS/DARK.SUB create mode 100644 CONTENT/RP/MODELS/DARKL4.CTL create mode 100644 CONTENT/RP/MODELS/DARKTHR.CTL create mode 100644 CONTENT/RP/MODELS/DEMO2.BAK create mode 100644 CONTENT/RP/MODELS/DEMO2.MOD create mode 100644 CONTENT/RP/MODELS/DEMO3.MOD create mode 100644 CONTENT/RP/MODELS/DEMOPACK.MOD create mode 100644 CONTENT/RP/MODELS/DP2THR.CTL create mode 100644 CONTENT/RP/MODELS/DPEXP.MOD create mode 100644 CONTENT/RP/MODELS/DPL4.CTL create mode 100644 CONTENT/RP/MODELS/DPTHR.CTL create mode 100644 CONTENT/RP/MODELS/DR1.MOD create mode 100644 CONTENT/RP/MODELS/DR2.MOD create mode 100644 CONTENT/RP/MODELS/DRAGON.BAK create mode 100644 CONTENT/RP/MODELS/DRAGON.DMG create mode 100644 CONTENT/RP/MODELS/DRAGON.MOD create mode 100644 CONTENT/RP/MODELS/DRAGON.SUB create mode 100644 CONTENT/RP/MODELS/DRGNL4.CTL create mode 100644 CONTENT/RP/MODELS/DRGNTHR.CTL create mode 100644 CONTENT/RP/MODELS/DRW.MOD create mode 100644 CONTENT/RP/MODELS/DRW.SUB create mode 100644 CONTENT/RP/MODELS/DRW2.MOD create mode 100644 CONTENT/RP/MODELS/DRW2.SUB create mode 100644 CONTENT/RP/MODELS/DRW_1.BAK create mode 100644 CONTENT/RP/MODELS/DRW_1.MOD create mode 100644 CONTENT/RP/MODELS/EFFECT.MOD create mode 100644 CONTENT/RP/MODELS/EXPLODE.MOD create mode 100644 CONTENT/RP/MODELS/FLEA.BAK create mode 100644 CONTENT/RP/MODELS/FLEA.DMG create mode 100644 CONTENT/RP/MODELS/FLEA.MOD create mode 100644 CONTENT/RP/MODELS/FLEA.SUB create mode 100644 CONTENT/RP/MODELS/FT1.MOD create mode 100644 CONTENT/RP/MODELS/FT2.MOD create mode 100644 CONTENT/RP/MODELS/FT2U.MOD create mode 100644 CONTENT/RP/MODELS/GAR.MOD create mode 100644 CONTENT/RP/MODELS/GAR1.MOD create mode 100644 CONTENT/RP/MODELS/GAR2.MOD create mode 100644 CONTENT/RP/MODELS/GATOR.BAK create mode 100644 CONTENT/RP/MODELS/GATOR.MOD create mode 100644 CONTENT/RP/MODELS/GATOR.SUB create mode 100644 CONTENT/RP/MODELS/GATORTHR.CTL create mode 100644 CONTENT/RP/MODELS/GR1.MOD create mode 100644 CONTENT/RP/MODELS/GR2.MOD create mode 100644 CONTENT/RP/MODELS/GRUNT.BAK create mode 100644 CONTENT/RP/MODELS/GRUNT.DMG create mode 100644 CONTENT/RP/MODELS/GRUNT.MOD create mode 100644 CONTENT/RP/MODELS/GRUNT.SUB create mode 100644 CONTENT/RP/MODELS/HDOFF.MOD create mode 100644 CONTENT/RP/MODELS/HOME.MOD create mode 100644 CONTENT/RP/MODELS/HRIVET.MOD create mode 100644 CONTENT/RP/MODELS/HV1.MOD create mode 100644 CONTENT/RP/MODELS/HV2.MOD create mode 100644 CONTENT/RP/MODELS/HV4.MOD create mode 100644 CONTENT/RP/MODELS/HV5.MOD create mode 100644 CONTENT/RP/MODELS/HV6.MOD create mode 100644 CONTENT/RP/MODELS/HV7.MOD create mode 100644 CONTENT/RP/MODELS/HVA.MOD create mode 100644 CONTENT/RP/MODELS/HVB.MOD create mode 100644 CONTENT/RP/MODELS/HVC.MOD create mode 100644 CONTENT/RP/MODELS/HVE.MOD create mode 100644 CONTENT/RP/MODELS/LASEREXP.MOD create mode 100644 CONTENT/RP/MODELS/LASERL4.CTL create mode 100644 CONTENT/RP/MODELS/LASERTHR.CTL create mode 100644 CONTENT/RP/MODELS/LAZDRIL.MOD create mode 100644 CONTENT/RP/MODELS/LEPTON.BAK create mode 100644 CONTENT/RP/MODELS/LEPTON.DMG create mode 100644 CONTENT/RP/MODELS/LEPTON.MOD create mode 100644 CONTENT/RP/MODELS/LEPTON.SUB create mode 100644 CONTENT/RP/MODELS/LRIVET.MOD create mode 100644 CONTENT/RP/MODELS/LSREXPC.MOD create mode 100644 CONTENT/RP/MODELS/LSREXPI.MOD create mode 100644 CONTENT/RP/MODELS/MAN.DMG create mode 100644 CONTENT/RP/MODELS/MAN.MOD create mode 100644 CONTENT/RP/MODELS/MANTIS.BAK create mode 100644 CONTENT/RP/MODELS/MANTIS.DMG create mode 100644 CONTENT/RP/MODELS/MANTIS.MOD create mode 100644 CONTENT/RP/MODELS/MANTIS.SUB create mode 100644 CONTENT/RP/MODELS/MAS.CTL create mode 100644 CONTENT/RP/MODELS/MAS.DMG create mode 100644 CONTENT/RP/MODELS/MAS.MOD create mode 100644 CONTENT/RP/MODELS/MAS.SUB create mode 100644 CONTENT/RP/MODELS/MASL4.CTL create mode 100644 CONTENT/RP/MODELS/MASTHR.CTL create mode 100644 CONTENT/RP/MODELS/MAT.DMG create mode 100644 CONTENT/RP/MODELS/MAT.MOD create mode 100644 CONTENT/RP/MODELS/MB1.MOD create mode 100644 CONTENT/RP/MODELS/MB1A.MOD create mode 100644 CONTENT/RP/MODELS/MCS.MOD create mode 100644 CONTENT/RP/MODELS/MD1.MOD create mode 100644 CONTENT/RP/MODELS/MD2.MOD create mode 100644 CONTENT/RP/MODELS/MD3.MOD create mode 100644 CONTENT/RP/MODELS/MD4.MOD create mode 100644 CONTENT/RP/MODELS/MD5.MOD create mode 100644 CONTENT/RP/MODELS/MDD.MOD create mode 100644 CONTENT/RP/MODELS/ME1.MOD create mode 100644 CONTENT/RP/MODELS/ME2.MOD create mode 100644 CONTENT/RP/MODELS/ME3.MOD create mode 100644 CONTENT/RP/MODELS/ME4.MOD create mode 100644 CONTENT/RP/MODELS/MED.MOD create mode 100644 CONTENT/RP/MODELS/MI1.MOD create mode 100644 CONTENT/RP/MODELS/MISSILE.MOD create mode 100644 CONTENT/RP/MODELS/MRIVET.MOD create mode 100644 CONTENT/RP/MODELS/MS1.MOD create mode 100644 CONTENT/RP/MODELS/MS2.MOD create mode 100644 CONTENT/RP/MODELS/MULE.BAK create mode 100644 CONTENT/RP/MODELS/MULE.DMG create mode 100644 CONTENT/RP/MODELS/MULE.MOD create mode 100644 CONTENT/RP/MODELS/MULE.SUB create mode 100644 CONTENT/RP/MODELS/MUN.DMG create mode 100644 CONTENT/RP/MODELS/MUN.MOD create mode 100644 CONTENT/RP/MODELS/MUS.DMG create mode 100644 CONTENT/RP/MODELS/MUS.MOD create mode 100644 CONTENT/RP/MODELS/MUS.SUB create mode 100644 CONTENT/RP/MODELS/MUSL4.CTL create mode 100644 CONTENT/RP/MODELS/MUSTHR.CTL create mode 100644 CONTENT/RP/MODELS/MUT.DMG create mode 100644 CONTENT/RP/MODELS/MUT.MOD create mode 100644 CONTENT/RP/MODELS/OA1.MOD create mode 100644 CONTENT/RP/MODELS/OA1N.MOD create mode 100644 CONTENT/RP/MODELS/OA3.MOD create mode 100644 CONTENT/RP/MODELS/OAO.MOD create mode 100644 CONTENT/RP/MODELS/OAO1.MOD create mode 100644 CONTENT/RP/MODELS/OD1.MOD create mode 100644 CONTENT/RP/MODELS/OD2.MOD create mode 100644 CONTENT/RP/MODELS/OD3.MOD create mode 100644 CONTENT/RP/MODELS/ODC.MOD create mode 100644 CONTENT/RP/MODELS/PIT1.MOD create mode 100644 CONTENT/RP/MODELS/PIT2.MOD create mode 100644 CONTENT/RP/MODELS/PL1.MOD create mode 100644 CONTENT/RP/MODELS/PLAYER.MOD create mode 100644 CONTENT/RP/MODELS/PM1.MOD create mode 100644 CONTENT/RP/MODELS/PP1.MOD create mode 100644 CONTENT/RP/MODELS/PP2.MOD create mode 100644 CONTENT/RP/MODELS/PRESHOW.MOD create mode 100644 CONTENT/RP/MODELS/PROTON.BAK create mode 100644 CONTENT/RP/MODELS/PROTON.DMG create mode 100644 CONTENT/RP/MODELS/PROTON.MOD create mode 100644 CONTENT/RP/MODELS/PROTON.SUB create mode 100644 CONTENT/RP/MODELS/PUCK.DMG create mode 100644 CONTENT/RP/MODELS/PUCK.MOD create mode 100644 CONTENT/RP/MODELS/PUCK.SUB create mode 100644 CONTENT/RP/MODELS/PUCKL4.CTL create mode 100644 CONTENT/RP/MODELS/PUCKTHR.CTL create mode 100644 CONTENT/RP/MODELS/PZ1.MOD create mode 100644 CONTENT/RP/MODELS/PZ2.MOD create mode 100644 CONTENT/RP/MODELS/PZ3.MOD create mode 100644 CONTENT/RP/MODELS/PZ4.MOD create mode 100644 CONTENT/RP/MODELS/QUARK.BAK create mode 100644 CONTENT/RP/MODELS/QUARK.DMG create mode 100644 CONTENT/RP/MODELS/QUARK.MOD create mode 100644 CONTENT/RP/MODELS/QUARK.SUB create mode 100644 CONTENT/RP/MODELS/QUARKL4.CTL create mode 100644 CONTENT/RP/MODELS/QUARKTHR.CTL create mode 100644 CONTENT/RP/MODELS/RDBLKL4X.CTL create mode 100644 CONTENT/RP/MODELS/RDBLKTHR.CTL create mode 100644 CONTENT/RP/MODELS/RF1.MOD create mode 100644 CONTENT/RP/MODELS/RIPPER.BAK create mode 100644 CONTENT/RP/MODELS/RIPPER.DMG create mode 100644 CONTENT/RP/MODELS/RIPPER.MOD create mode 100644 CONTENT/RP/MODELS/RIPPER.SUB create mode 100644 CONTENT/RP/MODELS/RIVET.MOD create mode 100644 CONTENT/RP/MODELS/RIVETEXP.MOD create mode 100644 CONTENT/RP/MODELS/RIVETL4.CTL create mode 100644 CONTENT/RP/MODELS/RIVETTHR.CTL create mode 100644 CONTENT/RP/MODELS/RL1.MOD create mode 100644 CONTENT/RP/MODELS/RL2.MOD create mode 100644 CONTENT/RP/MODELS/RL3.MOD create mode 100644 CONTENT/RP/MODELS/ROACH.BAK create mode 100644 CONTENT/RP/MODELS/ROACH.DMG create mode 100644 CONTENT/RP/MODELS/ROACH.MOD create mode 100644 CONTENT/RP/MODELS/ROACH.SUB create mode 100644 CONTENT/RP/MODELS/ROADBLK.BAK create mode 100644 CONTENT/RP/MODELS/ROADBLK.DMG create mode 100644 CONTENT/RP/MODELS/ROADBLK.MOD create mode 100644 CONTENT/RP/MODELS/ROADBLK.SUB create mode 100644 CONTENT/RP/MODELS/RP0.MOD create mode 100644 CONTENT/RP/MODELS/RP1.MOD create mode 100644 CONTENT/RP/MODELS/RP2.MOD create mode 100644 CONTENT/RP/MODELS/RP3.MOD create mode 100644 CONTENT/RP/MODELS/RVTEXPC.MOD create mode 100644 CONTENT/RP/MODELS/RVTEXPI.MOD create mode 100644 CONTENT/RP/MODELS/SAN.DMG create mode 100644 CONTENT/RP/MODELS/SAN.MOD create mode 100644 CONTENT/RP/MODELS/SAS.DMG create mode 100644 CONTENT/RP/MODELS/SAS.MOD create mode 100644 CONTENT/RP/MODELS/SAS.SUB create mode 100644 CONTENT/RP/MODELS/SASL4.CTL create mode 100644 CONTENT/RP/MODELS/SASTHR.CTL create mode 100644 CONTENT/RP/MODELS/SAT.DMG create mode 100644 CONTENT/RP/MODELS/SAT.MOD create mode 100644 CONTENT/RP/MODELS/SC50.MOD create mode 100644 CONTENT/RP/MODELS/SC500.MOD create mode 100644 CONTENT/RP/MODELS/SC500A.MOD create mode 100644 CONTENT/RP/MODELS/SC50A.MOD create mode 100644 CONTENT/RP/MODELS/SKEETER.BAK create mode 100644 CONTENT/RP/MODELS/SKEETER.MOD create mode 100644 CONTENT/RP/MODELS/SKEETER.SUB create mode 100644 CONTENT/RP/MODELS/SKTRL4.CTL create mode 100644 CONTENT/RP/MODELS/SKTRTHR.CTL create mode 100644 CONTENT/RP/MODELS/SNAALE.MOD create mode 100644 CONTENT/RP/MODELS/SNACRANE.MOD create mode 100644 CONTENT/RP/MODELS/SNADOS.MOD create mode 100644 CONTENT/RP/MODELS/SNAENTER.MOD create mode 100644 CONTENT/RP/MODELS/SNAEVAC.MOD create mode 100644 CONTENT/RP/MODELS/SNAHAZ.MOD create mode 100644 CONTENT/RP/MODELS/SNAHEADM.MOD create mode 100644 CONTENT/RP/MODELS/SNALIMIT.MOD create mode 100644 CONTENT/RP/MODELS/SNALOXM.MOD create mode 100644 CONTENT/RP/MODELS/SNAMFAC.MOD create mode 100644 CONTENT/RP/MODELS/SNANORC.MOD create mode 100644 CONTENT/RP/MODELS/SNARADS.MOD create mode 100644 CONTENT/RP/MODELS/SNASPDS.MOD create mode 100644 CONTENT/RP/MODELS/SNATSPD.MOD create mode 100644 CONTENT/RP/MODELS/SNAWELC.MOD create mode 100644 CONTENT/RP/MODELS/SNAWORK.MOD create mode 100644 CONTENT/RP/MODELS/SPECK.BAK create mode 100644 CONTENT/RP/MODELS/SPECK.DMG create mode 100644 CONTENT/RP/MODELS/SPECK.MOD create mode 100644 CONTENT/RP/MODELS/SPECK.SUB create mode 100644 CONTENT/RP/MODELS/SPITTER.BAK create mode 100644 CONTENT/RP/MODELS/SPITTER.DMG create mode 100644 CONTENT/RP/MODELS/SPITTER.MOD create mode 100644 CONTENT/RP/MODELS/SPITTER.SUB create mode 100644 CONTENT/RP/MODELS/STAD.MOD create mode 100644 CONTENT/RP/MODELS/STATIC.ONL create mode 100644 CONTENT/RP/MODELS/STATIC.SCP create mode 100644 CONTENT/RP/MODELS/STL4.CTL create mode 100644 CONTENT/RP/MODELS/STTHR.CTL create mode 100644 CONTENT/RP/MODELS/SUN.DMG create mode 100644 CONTENT/RP/MODELS/SUN.MOD create mode 100644 CONTENT/RP/MODELS/SUS.DMG create mode 100644 CONTENT/RP/MODELS/SUS.MOD create mode 100644 CONTENT/RP/MODELS/SUS.SUB create mode 100644 CONTENT/RP/MODELS/SUSL4.CTL create mode 100644 CONTENT/RP/MODELS/SUSTHR.CTL create mode 100644 CONTENT/RP/MODELS/SUT.DMG create mode 100644 CONTENT/RP/MODELS/SUT.MOD create mode 100644 CONTENT/RP/MODELS/TARNTULA.BAK create mode 100644 CONTENT/RP/MODELS/TARNTULA.DMG create mode 100644 CONTENT/RP/MODELS/TARNTULA.MOD create mode 100644 CONTENT/RP/MODELS/TARNTULA.SUB create mode 100644 CONTENT/RP/MODELS/TRS.MOD create mode 100644 CONTENT/RP/MODELS/TS1.MOD create mode 100644 CONTENT/RP/MODELS/TUN1.MOD create mode 100644 CONTENT/RP/MODELS/VCS.CFG create mode 100644 CONTENT/RP/MODELS/VEHICLE.TBL create mode 100644 CONTENT/RP/MODELS/VM1.MOD create mode 100644 CONTENT/RP/MODELS/VOLE.BAK create mode 100644 CONTENT/RP/MODELS/VOLE.MOD create mode 100644 CONTENT/RP/MODELS/VOLE.SUB create mode 100644 CONTENT/RP/MODELS/WASP.BAK create mode 100644 CONTENT/RP/MODELS/WASP.DMG create mode 100644 CONTENT/RP/MODELS/WASP.MOD create mode 100644 CONTENT/RP/MODELS/WASP.SUB create mode 100644 CONTENT/RP/MODELS/WCIRCLE.MOD create mode 100644 CONTENT/RP/MODELS/WH1.MOD create mode 100644 CONTENT/RP/MODELS/WH2.MOD create mode 100644 CONTENT/RP/MODELS/WH4.MOD create mode 100644 CONTENT/RP/MODELS/WH5.MOD create mode 100644 CONTENT/RP/MODELS/WH6.MOD create mode 100644 CONTENT/RP/MODELS/WH6U.MOD create mode 100644 CONTENT/RP/MODELS/WH8.MOD create mode 100644 CONTENT/RP/MODELS/WH9.MOD create mode 100644 CONTENT/RP/MODELS/WHC.MOD create mode 100644 CONTENT/RP/MODELS/WINBOX.MOD create mode 100644 CONTENT/RP/MODELS/WT1.MOD create mode 100644 CONTENT/RP/MODELS/WT2.MOD create mode 100644 CONTENT/RP/NULL create mode 100644 CONTENT/RP/RESULT2.TXT create mode 100644 CONTENT/RP/RP.BAT create mode 100644 CONTENT/RP/RPCAM.BAT create mode 100644 CONTENT/RP/RPGO.BAT create mode 100644 CONTENT/RP/RPL4.BAK create mode 100644 CONTENT/RP/RPL4.BLD create mode 100644 CONTENT/RP/RPL4.BL_ create mode 100644 CONTENT/RP/RPL4.OPS create mode 100644 CONTENT/RP/RPL4.OP_ create mode 100644 CONTENT/RP/RPL4JM.BLD create mode 100644 CONTENT/RP/RPLOOK.BAT create mode 100644 CONTENT/RP/RPNET.BAT create mode 100644 CONTENT/RP/RPPREP.BAT create mode 100644 CONTENT/RP/RPSPL.BAT create mode 100644 CONTENT/RP/SCENES/CAM.BAT create mode 100644 CONTENT/RP/SCENES/DONTNEED.SPL create mode 100644 CONTENT/RP/SCENES/FRSTRM.CAM create mode 100644 CONTENT/RP/SCENES/GO.BAT create mode 100644 CONTENT/RP/SCENES/JOYSTICK.CAL create mode 100644 CONTENT/RP/SCENES/NEXT.BAT create mode 100644 CONTENT/RP/SCENES/ONETHING.SCN create mode 100644 CONTENT/RP/SCENES/OTTOCAM.SPL create mode 100644 CONTENT/RP/SCENES/RPFLY.BAT create mode 100644 CONTENT/RP/SCENES/SETNTSC.BAT create mode 100644 CONTENT/RP/SCENES/SETSVGA.BAT create mode 100644 CONTENT/RP/SCENES/SETSVGA6.BAT create mode 100644 CONTENT/RP/SHOWENV.BAT create mode 100644 CONTENT/RP/SOLIDS/BA_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BLADE.XST create mode 100644 CONTENT/RP/SOLIDS/BLANK.XST create mode 100644 CONTENT/RP/SOLIDS/BN1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BP1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BR1A_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BR1B_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BR1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BR3_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BRE1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BREWERS.XST create mode 100644 CONTENT/RP/SOLIDS/BREW_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/BURNT.BAK create mode 100644 CONTENT/RP/SOLIDS/BURNT.XST create mode 100644 CONTENT/RP/SOLIDS/BU_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/C8E_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CAP_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CC1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CHG_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CHOICE2.XST create mode 100644 CONTENT/RP/SOLIDS/CL1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CL2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CL3_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN3U_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN3_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN4_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN5U_CV.ORG create mode 100644 CONTENT/RP/SOLIDS/CN5U_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN5_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN7U_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CN7_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CQ1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CQ2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CR2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CR4_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CR5U_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CR5_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CR6_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CR8_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CRE_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CRP_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/CT1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/D45.XST create mode 100644 CONTENT/RP/SOLIDS/D45_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/DR1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/DR2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/DU_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/EASY.XST create mode 100644 CONTENT/RP/SOLIDS/ED009100.$$$ create mode 100644 CONTENT/RP/SOLIDS/ED009101.$$$ create mode 100644 CONTENT/RP/SOLIDS/FRSTRM.XST create mode 100644 CONTENT/RP/SOLIDS/FT1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/FT2U_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/FT2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/GAR1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/GAR2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/GAR_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/HDOFF_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/HEADMF.XST create mode 100644 CONTENT/RP/SOLIDS/HEADOFF.BAK create mode 100644 CONTENT/RP/SOLIDS/HEADOFF.XST create mode 100644 CONTENT/RP/SOLIDS/HV2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/HV4_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/HV6_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/HV7_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/HVA_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/HVB_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/LU_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/LYZLANE.XST create mode 100644 CONTENT/RP/SOLIDS/MA_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/MB1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/MD1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/MD2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/MD3_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/MD4_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/ME1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/ME2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/ME4_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/MED_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/MU_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/OA1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/OAO_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/ODC_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/OTTO.XST create mode 100644 CONTENT/RP/SOLIDS/PAIN.XST create mode 100644 CONTENT/RP/SOLIDS/PIT1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PIT2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PM1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PO_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PP1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PP2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PUCKLAND.XST create mode 100644 CONTENT/RP/SOLIDS/PZ1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PZ2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PZ3_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/PZ4_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/RL1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/RL2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/RL3_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/RP0_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/RP1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/RP2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/RP3_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/SA_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/SC500_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/SC50_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/SHOOT.XST create mode 100644 CONTENT/RP/SOLIDS/SIG.XST create mode 100644 CONTENT/RP/SOLIDS/SU_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/TEST.XST create mode 100644 CONTENT/RP/SOLIDS/TOUGH.XST create mode 100644 CONTENT/RP/SOLIDS/TRS_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/TUN1_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/VCS.CFG create mode 100644 CONTENT/RP/SOLIDS/WHC_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/WISE.XST create mode 100644 CONTENT/RP/SOLIDS/WT2_CV.SLD create mode 100644 CONTENT/RP/SOLIDS/YIP.XST create mode 100644 CONTENT/RP/TOOLOPT.BAT create mode 100644 CONTENT/RP/VCS.CFG create mode 100644 CONTENT/RP/VIDEO/BMAP.BMF create mode 100644 CONTENT/RP/VIDEO/BN1L.BGF create mode 100644 CONTENT/RP/VIDEO/BOOST.PFX create mode 100644 CONTENT/RP/VIDEO/BP1.BGF create mode 100644 CONTENT/RP/VIDEO/BR1L.BGF create mode 100644 CONTENT/RP/VIDEO/BR2L.BGF create mode 100644 CONTENT/RP/VIDEO/BR3.BGF create mode 100644 CONTENT/RP/VIDEO/BST.BGF create mode 100644 CONTENT/RP/VIDEO/BUA.BGF create mode 100644 CONTENT/RP/VIDEO/BUB.BGF create mode 100644 CONTENT/RP/VIDEO/BUB.SKL create mode 100644 CONTENT/RP/VIDEO/BUC.BGF create mode 100644 CONTENT/RP/VIDEO/C8EL.BGF create mode 100644 CONTENT/RP/VIDEO/CAMPOS.BGF create mode 100644 CONTENT/RP/VIDEO/CENTER.BGF create mode 100644 CONTENT/RP/VIDEO/CH1.BGF create mode 100644 CONTENT/RP/VIDEO/CH2.BGF create mode 100644 CONTENT/RP/VIDEO/CHG.BGF create mode 100644 CONTENT/RP/VIDEO/CHT.BGF create mode 100644 CONTENT/RP/VIDEO/CL2.BGF create mode 100644 CONTENT/RP/VIDEO/CL3.BGF create mode 100644 CONTENT/RP/VIDEO/CLD.BGF create mode 100644 CONTENT/RP/VIDEO/CN2L.BGF create mode 100644 CONTENT/RP/VIDEO/CN3.BGF create mode 100644 CONTENT/RP/VIDEO/CN3U.BGF create mode 100644 CONTENT/RP/VIDEO/CQ2.BGF create mode 100644 CONTENT/RP/VIDEO/CR1L.BGF create mode 100644 CONTENT/RP/VIDEO/CR2L.BGF create mode 100644 CONTENT/RP/VIDEO/CR3L.BGF create mode 100644 CONTENT/RP/VIDEO/CR4.BGF create mode 100644 CONTENT/RP/VIDEO/CR5.BGF create mode 100644 CONTENT/RP/VIDEO/CR6.BGF create mode 100644 CONTENT/RP/VIDEO/CR8.BGF create mode 100644 CONTENT/RP/VIDEO/CRC.BGF create mode 100644 CONTENT/RP/VIDEO/CREL.BGF create mode 100644 CONTENT/RP/VIDEO/CT1L.BGF create mode 100644 CONTENT/RP/VIDEO/CTF.BGF create mode 100644 CONTENT/RP/VIDEO/DEMOBOOM.PFX create mode 100644 CONTENT/RP/VIDEO/DEMOBURN.PFX create mode 100644 CONTENT/RP/VIDEO/DEMOFUSE.PFX create mode 100644 CONTENT/RP/VIDEO/DR1L.BGF create mode 100644 CONTENT/RP/VIDEO/DR2.BG_ create mode 100644 CONTENT/RP/VIDEO/DR2L.BGF create mode 100644 CONTENT/RP/VIDEO/DRWL.BGF create mode 100644 CONTENT/RP/VIDEO/DUA.BGF create mode 100644 CONTENT/RP/VIDEO/DUB.BGF create mode 100644 CONTENT/RP/VIDEO/DUC.BGF create mode 100644 CONTENT/RP/VIDEO/DUMMY.BMF create mode 100644 CONTENT/RP/VIDEO/DUMMYENG.BGF create mode 100644 CONTENT/RP/VIDEO/FT1L.BGF create mode 100644 CONTENT/RP/VIDEO/GR1L.BGF create mode 100644 CONTENT/RP/VIDEO/GR2L.BGF create mode 100644 CONTENT/RP/VIDEO/HV1L.BGF create mode 100644 CONTENT/RP/VIDEO/HVA.BGF create mode 100644 CONTENT/RP/VIDEO/HVB.BGF create mode 100644 CONTENT/RP/VIDEO/HVEL.BGF create mode 100644 CONTENT/RP/VIDEO/LAA.BGF create mode 100644 CONTENT/RP/VIDEO/LAA.SKL create mode 100644 CONTENT/RP/VIDEO/LAB.BGF create mode 100644 CONTENT/RP/VIDEO/LAB.SKL create mode 100644 CONTENT/RP/VIDEO/LAC.BGF create mode 100644 CONTENT/RP/VIDEO/LAC.SKL create mode 100644 CONTENT/RP/VIDEO/LAN.SKL create mode 100644 CONTENT/RP/VIDEO/LAS.SKL create mode 100644 CONTENT/RP/VIDEO/LASER.PFX create mode 100644 CONTENT/RP/VIDEO/LAT.SKL create mode 100644 CONTENT/RP/VIDEO/LAZDRIL.BGF create mode 100644 CONTENT/RP/VIDEO/LSABER.BGF create mode 100644 CONTENT/RP/VIDEO/LUA.BGF create mode 100644 CONTENT/RP/VIDEO/LUA.SKL create mode 100644 CONTENT/RP/VIDEO/LUB.BGF create mode 100644 CONTENT/RP/VIDEO/LUB.SKL create mode 100644 CONTENT/RP/VIDEO/LUC.BGF create mode 100644 CONTENT/RP/VIDEO/LUC.SKL create mode 100644 CONTENT/RP/VIDEO/LUN.SKL create mode 100644 CONTENT/RP/VIDEO/LUS.SKL create mode 100644 CONTENT/RP/VIDEO/LUT.SKL create mode 100644 CONTENT/RP/VIDEO/MB1.BGF create mode 100644 CONTENT/RP/VIDEO/MINE.BGF create mode 100644 CONTENT/RP/VIDEO/MISSILE.BGF create mode 100644 CONTENT/RP/VIDEO/MUA.BGF create mode 100644 CONTENT/RP/VIDEO/MUA.SKL create mode 100644 CONTENT/RP/VIDEO/MUB.BGF create mode 100644 CONTENT/RP/VIDEO/MUB.SKL create mode 100644 CONTENT/RP/VIDEO/MUC.BGF create mode 100644 CONTENT/RP/VIDEO/MUC.SKL create mode 100644 CONTENT/RP/VIDEO/MUN.SKL create mode 100644 CONTENT/RP/VIDEO/MUS.SKL create mode 100644 CONTENT/RP/VIDEO/MUT.SKL create mode 100644 CONTENT/RP/VIDEO/OA3L.BGF create mode 100644 CONTENT/RP/VIDEO/OD1L.BGF create mode 100644 CONTENT/RP/VIDEO/OD3L.BGF create mode 100644 CONTENT/RP/VIDEO/OS1.BGF create mode 100644 CONTENT/RP/VIDEO/PL1L.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE1.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE2.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE3.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE4.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE5.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE6.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE7.BGF create mode 100644 CONTENT/RP/VIDEO/PLACE8.BGF create mode 100644 CONTENT/RP/VIDEO/PM1L.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME1.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME2.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME3.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME4.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME5.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME6.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME7.BGF create mode 100644 CONTENT/RP/VIDEO/PNAME8.BGF create mode 100644 CONTENT/RP/VIDEO/POA.SKL create mode 100644 CONTENT/RP/VIDEO/POB.SKL create mode 100644 CONTENT/RP/VIDEO/POC.SKL create mode 100644 CONTENT/RP/VIDEO/PON.SKL create mode 100644 CONTENT/RP/VIDEO/POS.SKL create mode 100644 CONTENT/RP/VIDEO/POT.SKL create mode 100644 CONTENT/RP/VIDEO/RF1L.BGF create mode 100644 CONTENT/RP/VIDEO/RIVET.BGF create mode 100644 CONTENT/RP/VIDEO/RL1L.BGF create mode 100644 CONTENT/RP/VIDEO/RL2L.BGF create mode 100644 CONTENT/RP/VIDEO/RL3L.BGF create mode 100644 CONTENT/RP/VIDEO/RP0.BGF create mode 100644 CONTENT/RP/VIDEO/RP1L.BGF create mode 100644 CONTENT/RP/VIDEO/RP2L.BGF create mode 100644 CONTENT/RP/VIDEO/RP3L.BGF create mode 100644 CONTENT/RP/VIDEO/RPFX.BMF create mode 100644 CONTENT/RP/VIDEO/SAA.BGF create mode 100644 CONTENT/RP/VIDEO/SAA.SKL create mode 100644 CONTENT/RP/VIDEO/SAB.BGF create mode 100644 CONTENT/RP/VIDEO/SAB.SKL create mode 100644 CONTENT/RP/VIDEO/SAC.BGF create mode 100644 CONTENT/RP/VIDEO/SAC.SKL create mode 100644 CONTENT/RP/VIDEO/SAN.SKL create mode 100644 CONTENT/RP/VIDEO/SAS.SKL create mode 100644 CONTENT/RP/VIDEO/SAT.SKL create mode 100644 CONTENT/RP/VIDEO/SC500L.BGF create mode 100644 CONTENT/RP/VIDEO/SMOKE.PFX create mode 100644 CONTENT/RP/VIDEO/SNAALE.BGF create mode 100644 CONTENT/RP/VIDEO/SNACRANE.BGF create mode 100644 CONTENT/RP/VIDEO/SNADOS.BGF create mode 100644 CONTENT/RP/VIDEO/SNAENTER.BGF create mode 100644 CONTENT/RP/VIDEO/SNAEVAC.BGF create mode 100644 CONTENT/RP/VIDEO/SNAHAZ.BGF create mode 100644 CONTENT/RP/VIDEO/SNAHEADM.BGF create mode 100644 CONTENT/RP/VIDEO/SNALIMIT.BGF create mode 100644 CONTENT/RP/VIDEO/SNALOXM.BGF create mode 100644 CONTENT/RP/VIDEO/SNAMFAC.BGF create mode 100644 CONTENT/RP/VIDEO/SNANORC.BGF create mode 100644 CONTENT/RP/VIDEO/SNARADS.BGF create mode 100644 CONTENT/RP/VIDEO/SNASPDS.BGF create mode 100644 CONTENT/RP/VIDEO/SNATSPD.BGF create mode 100644 CONTENT/RP/VIDEO/SNAWELC.BGF create mode 100644 CONTENT/RP/VIDEO/SNAWORK.BGF create mode 100644 CONTENT/RP/VIDEO/SPARKS.PFX create mode 100644 CONTENT/RP/VIDEO/SUA.BGF create mode 100644 CONTENT/RP/VIDEO/SUA.SKL create mode 100644 CONTENT/RP/VIDEO/SUB.BGF create mode 100644 CONTENT/RP/VIDEO/SUB.SKL create mode 100644 CONTENT/RP/VIDEO/SUC.BGF create mode 100644 CONTENT/RP/VIDEO/SUC.SKL create mode 100644 CONTENT/RP/VIDEO/SUN.SKL create mode 100644 CONTENT/RP/VIDEO/SUS.SKL create mode 100644 CONTENT/RP/VIDEO/SUT.SKL create mode 100644 CONTENT/RP/VIDEO/TEST.PFX create mode 100644 CONTENT/RP/VIDEO/TEST.TXT create mode 100644 CONTENT/RP/VIDEO/TSPHERE.BGF create mode 100644 CONTENT/RP/VIDEO/VLA.BGF create mode 100644 CONTENT/RP/VIDEO/VLC.BGF create mode 100644 CONTENT/RP/VIDEO/VM1L.BGF create mode 100644 CONTENT/RP/VIDEO/VRA.BGF create mode 100644 CONTENT/RP/VIDEO/VRC.BGF create mode 100644 CONTENT/RP/VIDEO/VTVBURN.PFX create mode 100644 CONTENT/RP/VIDEO/WH1L.BGF create mode 100644 CONTENT/RP/VIDEO/WH2L.BGF create mode 100644 CONTENT/RP/VIDEO/WH4L.BGF create mode 100644 CONTENT/RP/VIDEO/WH5L.BGF create mode 100644 CONTENT/RP/VIDEO/WH9L.BGF create mode 100644 CONTENT/RP/VIDEO/WINBOX.BGF create mode 100644 CONTENT/RP/VIDEO/WINSIGNS.BGF create mode 100644 CONTENT/RP/VIDEO/WT1L.BGF create mode 100644 CONTENT/RP/VIDEO/WT2L.BGF create mode 100644 CONTENT/RP/WATTCP.CFG create mode 100644 CONTENT/TAISATAP.SYS create mode 100644 HEADOFF/HEADMF.BAK create mode 100644 HEADOFF/HEADMF.CAM create mode 100644 HEADOFF/HEADMF.XST create mode 100644 HEADOFF/HEADOFF.BAK create mode 100644 HEADOFF/HEADOFF.XST create mode 100644 README.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..221d121 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Archival repository: preserve all files byte-for-byte. +# No line-ending conversion, no diff/merge text munging. +* -text diff --git a/ARTTOOLS/.gitkeep b/ARTTOOLS/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/BORLAND/.gitkeep b/BORLAND/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/CODE/BT/32RTM.EXE b/CODE/BT/32RTM.EXE new file mode 100644 index 0000000000000000000000000000000000000000..29bb61a1e968c2401fcf3742f7f24e02584dc1d4 GIT binary patch literal 152108 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

+aA9>x$0W@ou1 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 -9RdE*irllZET!A!6)q^B4D0Bef$rOZ^3<%Rx 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 +# endif + +# if !defined(NO_PRECOMPILED_HEADERS) + +# if !defined(MECH_HPP) +# include +# endif + +# if !defined(BTPLAYER_HPP) +# include +# endif + +# if !defined(MECHSUB_HPP) +# include +# endif + +# endif + +#endif diff --git a/CODE/BT/BT/BT.MAK b/CODE/BT/BT/BT.MAK new file mode 100644 index 0000000..930a57d --- /dev/null +++ b/CODE/BT/BT/BT.MAK @@ -0,0 +1,112 @@ +.autodepend +.cacheautodepend +.suffixes: .cpp + +!ifndef BTYPE +!error BTYPE macro not supplied +!endif + +!ifndef BPATH +!error BPATH macro not supplied +!endif + +!include make.cfg +!include $(BPATH) + +!ifndef BT_ROOT +!error BT_ROOT macro is not defined +!endif + +TARGET_DIR = $(BT_ROOT)\$(BTYPE) +TARGET_PATH = $(TARGET_DIR)\\ +.path.obj = $(TARGET_DIR) +.path.lib = $(LIBRARY_PATH) + +LIB_PREFIX = -+$(TARGET_DIR)\\ + +CFG_FILE = $(TARGET_DIR)\$(BTYPE).cfg +HEADER_FILE = bt$(BTYPE).csm + +#------------------------------------------------------------------------------ +# Library targets +# +all: $(CFG_FILE) $(TARGET_DIR)\bt.lib + +clean: + del $(TARGET_DIR)\*.obj + del $(TARGET_DIR)\*.lib + del $(TARGET_DIR)\*.bak + del $(TARGET_DIR)\*.cfg + +assemble: + @echo No assembly targets + +#------------------------------------------------------------------------------ +# Implicit rules +# +!include $(BTYPE).mak + +!ifndef STARTUP_OBJ +!error STARTUP_OBJ macro is not defined +!endif + +!ifndef STARTUP_LIBS +!error STARTUP_LIBS macro is not defined +!endif + +{$(INCLUDE_PATH)}.cpp{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(INCLUDE_PATH)}.c{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(BT_ROOT)}.asm{$(TARGET_DIR)}.obj: + tasm32 -ml $(TASM_OPTIONS) -i$(BT_ROOT) $<,$@ >>error.log + +#------------------------------------------------------------------------------ +# Battletech library +# +BT_OBJS = \ + ?btmssn.obj \ + ?messmgr.obj \ + ?mechdmg.obj \ + ?dmgtable.obj \ + ?mech.obj \ + ?mech2.obj \ + ?mech3.obj \ + ?mech4.obj \ + ?mechsub.obj \ + ?mechtech.obj \ + ?heat.obj \ + ?mechmppr.obj \ + ?powersub.obj \ + ?sensor.obj \ + ?gnrator.obj \ + ?gyro.obj \ + ?torso.obj \ + ?hud.obj \ + ?myomers.obj \ + ?mechweap.obj \ + ?emitter.obj \ + ?ppc.obj \ + ?projweap.obj \ + ?mislanch.obj \ + ?ammobin.obj \ + ?gauss.obj \ + ?projtile.obj \ + ?misthrst.obj \ + ?seeker.obj \ + ?missile.obj \ + ?btplayer.obj \ + ?btteam.obj \ + ?btdirect.obj \ + ?btreg.obj \ + ?btcnsl.obj \ + ?bttool.obj + +$(BT_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\bt.lib: $(BT_OBJS:?=) $(BT_ROOT)\bt.mak + tlib $@ $(LIB_OPTIONS) @&&| +$(BT_OBJS:?=$(LIB_PREFIX)) +| >>error.log diff --git a/CODE/BT/BT/BTCNSL.CPP b/CODE/BT/BT/BTCNSL.CPP new file mode 100644 index 0000000..2dc59a8 --- /dev/null +++ b/CODE/BT/BT/BTCNSL.CPP @@ -0,0 +1,107 @@ +//===========================================================================// +// File: cnslmsgs.cpp // +// Project: MUNGA Brick: // +// Contents: Console messages // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/02/95 ECH Initial coding. // +// 06/03/95 GAH Added corresponding Macintosh message defintions. // +// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BTCNSL_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerMechKilledMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerMechKilledMessage:: + ConsolePlayerMechKilledMessage( + HostID player_host_ID, + HostID killer_host_ID + ): + NetworkClient::Message( + ConsolePlayerMechKilledMessageID, + sizeof(ConsolePlayerMechKilledMessage) + ) +{ + playerHostID = player_host_ID; + killerHostID = killer_host_ID; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerMechScoreUpdateMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerMechScoreUpdateMessage:: + ConsolePlayerMechScoreUpdateMessage( + HostID player_host_ID, + int score + ): + NetworkClient::Message( + ConsolePlayerMechScoreUpdateMessageID, + sizeof(ConsolePlayerMechScoreUpdateMessage) + ) +{ + playerHostID = player_host_ID; + playerScore = score; +} + +//~~~~~~~~~~~~~~~~~~ ConsoleBTTeamScoreUpdateMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsoleBTTeamScoreUpdateMessage:: + ConsoleBTTeamScoreUpdateMessage( + int team_ID, + int score + ): + NetworkClient::Message( + ConsoleBTTeamScoreUpdateMessageID, + sizeof(ConsoleBTTeamScoreUpdateMessage) + ) +{ + teamID = team_ID; + teamScore = score; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerMechDamagedMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerMechDamagedMessage:: + ConsolePlayerMechDamagedMessage( + HostID player_host_ID, + HostID damager_host_ID, + int loss, + int damage_zone_index, + Logical damage_zone_destroyed, + int points_transfered, + int weapon_index + ): + NetworkClient::Message( + ConsolePlayerMechDamagedMessageID, + sizeof(ConsolePlayerMechDamagedMessage) + ) +{ + playerHostID = player_host_ID; + damagerHostID = damager_host_ID; + damageLoss = loss; + pointsTransfered = points_transfered; + damageZoneIndex = damage_zone_index; + damageZoneDestroyed = damage_zone_destroyed; + weaponIndex = weapon_index; +} + +//~~~~~~~~~~~~~~~~ ConsolePlayerMechDeathWithoutHonorMessage ~~~~~~~~~~~~~~~~~~~ +ConsolePlayerMechDeathWithoutHonorMessage:: + ConsolePlayerMechDeathWithoutHonorMessage( + HostID player_host_ID + ): + NetworkClient::Message( + ConsolePlayerMechDeathWithoutHonorMessageID, + sizeof(ConsolePlayerMechDeathWithoutHonorMessage) + ) +{ + playerHostID = player_host_ID; +} + +//============================================================================== diff --git a/CODE/BT/BT/BTDIRECT.HPP b/CODE/BT/BT/BTDIRECT.HPP new file mode 100644 index 0000000..abd6ddf --- /dev/null +++ b/CODE/BT/BT/BTDIRECT.HPP @@ -0,0 +1,76 @@ +//===========================================================================// +// File: btdirect.hh // +// Project: Red Planet // +// Contents: Chooses from a Selection of Camerea's and provides information // +// to any number of cameraship's as to which player to follow // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/15/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined (BTDIRECT_HPP) +# define BTDIRECT_HPP + +# if !defined (DIRECTOR_HPP) +# include +# endif + +# if !defined (BTPLAYER_HPP) && 0 +# include +# endif + + +class BTCameraDirector : + public CameraDirector +{ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Simulation Support + // + public: + + typedef void + (BTCameraDirector::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + CreateBTCameraShip(Scalar); + + void + BeABTDirector(Scalar); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + BTCameraDirector( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + + static BTCameraDirector* + BTCameraDirector::Make(CameraDirector::MakeMessage *creation_message); + + ~BTCameraDirector(); + + Logical + TestInstance() const; +}; +#endif diff --git a/CODE/BT/BT/BTMSSN.CPP b/CODE/BT/BT/BTMSSN.CPP new file mode 100644 index 0000000..9cfe70f --- /dev/null +++ b/CODE/BT/BT/BTMSSN.CPP @@ -0,0 +1,70 @@ +//===========================================================================// +// File: btmssn.cpp // +// Project: BattleTech // +// Contents: Implementation Details for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/07/95 ECH Initial coding. // +// 09/12/95 JM added scenario // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#include +#pragma hdrstop + +#if !defined(BTMSSN_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +//########################################################################## +//########################### BTMission ################################ +//########################################################################## + +BTMission::BTMission( + NotationFile *notation_file, + ResourceFile *resource_file +): + Mission(notation_file, resource_file) +{ + Check(notation_file); + Check(resource_file); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Load Up Default Values + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + + experienceLevel = BTMission::NoviceMode; + advancedDamageOn = False; + + int ret; + ret = notation_file->GetEntry("mission", "temperature", &missionTemperature); + if (!ret) + { + DEBUG_STREAM << "ERROR: no temperature in egg!\n"; + Exit(AbortExitCodeID); + } + missionTemperature += 273.15f; // Celsius to Kelvin conversion + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BTMission::~BTMission() +{ + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BTMission::SetPlayerData(NotationFile*) +{ + Fail("Should never reach BTMission::SetPlayerData() \n"); +} diff --git a/CODE/BT/BT/BTMSSN.HPP b/CODE/BT/BT/BTMSSN.HPP new file mode 100644 index 0000000..a0dbf5c --- /dev/null +++ b/CODE/BT/BT/BTMSSN.HPP @@ -0,0 +1,96 @@ +//===========================================================================// +// File: btmssn.hpp // +// Project: BattleTech // +// Contents: Implementation Details for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/07/95 ECH Initial coding. // +// 09/12/95 JM added scenario // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTMSSN_HPP) +# define BTMSSN_HPP + +# if !defined(MISSION_HPP) +# include +# endif + +//########################################################################## +//########################### BTMission ################################ +//########################################################################## + + +class BTMission : + public Mission +{ + + public: + enum { + NoviceMode = 0, + StandardMode, + VeteranMode, + ExpertMode, + ExperienceLevelModeCount + }; + + protected: + + Enumeration experienceLevel; + + CString + roleName; + CString + teamName; + + Logical + advancedDamageOn; + + Scalar + missionTemperature; + + CString + patchName; + + public: + + BTMission( + NotationFile *notation_file, + ResourceFile *resources + ); + + ~BTMission(); + + void + SetPlayerData(NotationFile *notation_file); + + CString + GetRoleName() const + { Check(this); return roleName; } + + CString + GetTeamName() const + { Check(this); return teamName; } + + const CString + GetPatchName() + {Check(this); return patchName;} + + const Scalar + GetMissionTemperature() + {Check(this); return missionTemperature;} + + const Enumeration + ExperienceLevel() + {Check(this); return experienceLevel;} + + const Logical + AdvancedDamageOn() + {Check(this); return advancedDamageOn;} + +}; +#endif diff --git a/CODE/BT/BT/BTREG.CPP b/CODE/BT/BT/BTREG.CPP new file mode 100644 index 0000000..acdabdc --- /dev/null +++ b/CODE/BT/BT/BTREG.CPP @@ -0,0 +1,162 @@ +//===========================================================================// +// File: btreg.cc // +// Project: MUNGA Brick: Registry Manager // +// Contents: Interface specification for Registry Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/22/94 ECH Initial coding. // +// 11/29/94 JMA Changed Identities to IDs // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BTREG_HPP) +# include +#endif + +#if !defined(BTPLAYER_HPP) +# include +#endif + +#if !defined(BTDIRECT_HPP) +# include +#endif + +// +// Registered classes... +// +#if !defined(MECH_HPP) +# include +#endif + +#if !defined(PROJTILE_HPP) +# include +#endif + +#if !defined(MISSILE_HPP) +# include +#endif + +#if !defined(BTTEAM_HPP) +# include +#endif + +// +//~~~~~~~~~~~~~~~~ +// Munga Includes +//~~~~~~~~~~~~~~~~ +// +#if !defined(BTMSSN_HPP) +# include +#endif + +#if !defined(DIRECTOR_HPP) +# include +#endif + +#if !defined(HOSTMGR_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Registry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Registry +//############################################################################# +// +BTRegistry::BTRegistry(ResourceFile *) +{ + +} + +// +//############################################################################# +// ~Registry +//############################################################################# +// +BTRegistry::~BTRegistry() +{ +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Entity::SharedData* + BTRegistry::GetStaticData(ClassID class_ID) +{ + switch (class_ID) + { + case MechClassID: + return &Mech::DefaultData; + case ProjectileClassID: + return &Projectile::DefaultData; + case MissileClassID: + return &Missile::DefaultData; + case BTPlayerClassID: + return &BTPlayer::DefaultData; + case BTTeamClassID: + return &BTTeam::DefaultData; + default: + return Registry::GetStaticData(class_ID); + } +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Player* + BTRegistry::MakePlayer(Mission *mission) +{ + Check(this); + Check(mission); + BTMission *bt_mission = Cast_Object(BTMission *, mission); + + if (strcmp(mission->GetGameModel(), "camera")) + { + BTPlayer::MakeMessage + make_player( + BTPlayer::MakeMessageID, + sizeof(BTPlayer::MakeMessage), + BTPlayerClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + BTPlayer::DefaultFlags, + Origin::Identity, + mission->GetPlayerBitmapIndex(), + bt_mission->GetRoleName(), + bt_mission->GetTeamName() + ); + return new BTPlayer(&make_player); + } + + else + { + BTCameraDirector::MakeMessage create_director( + BTCameraDirector::MakeMessageID, + sizeof(BTCameraDirector::MakeMessage), + CameraDirectorClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + BTCameraDirector::DefaultFlags, + Origin::Identity, + mission->GetPlayerBitmapIndex() + ); + return new BTCameraDirector(&create_director); + } + } + diff --git a/CODE/BT/BT/BTREG.HPP b/CODE/BT/BT/BTREG.HPP new file mode 100644 index 0000000..18aac96 --- /dev/null +++ b/CODE/BT/BT/BTREG.HPP @@ -0,0 +1,74 @@ +//===========================================================================// +// File: registry.hh // +// Project: MUNGA Brick: Registry Manager // +// Contents: Interface specification for Registry Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/22/94 ECH Initial coding. // +// 11/29/94 JMA Changed Identities to IDs // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTREG_HPP) +# define BTREG_HPP + +# if !defined(REGISTRY_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Registry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // + //-------------------------------------------------------------------- + // Registry + // + // Provides construction methods for entities. + // Provides access to a classes static data. + //-------------------------------------------------------------------- + // + + class BTRegistry: + public Registry + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Construction, Destruction, and testing + //-------------------------------------------------------------------- + // + BTRegistry(ResourceFile *); + ~BTRegistry(); + + // + //-------------------------------------------------------------- + // GetStaticData + // + // Provides an interface by which the static data for a class + // may be accessed. + //-------------------------------------------------------------- + // + Entity__SharedData* + GetStaticData(ClassID entity_class); + + // + //------------------------- + // Create the player object + //------------------------- + // + Player* + MakePlayer(Mission *mission); + }; + +#endif diff --git a/CODE/BT/BT/BTSCNRL.CPP b/CODE/BT/BT/BTSCNRL.CPP new file mode 100644 index 0000000..6d69bb0 --- /dev/null +++ b/CODE/BT/BT/BTSCNRL.CPP @@ -0,0 +1,22 @@ +//===========================================================================// +// File: btscnrl.cpp // +// Project: MUNGA // +// Contents: BT Scenario Role Specific Data // +//------------------- -------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/06/96 GDU Initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + + +#include +#pragma hdrstop + + +# if !defined(BTSCNRL_HPP) +# include +# endif diff --git a/CODE/BT/BT/BTTEAM.CPP b/CODE/BT/BT/BTTEAM.CPP new file mode 100644 index 0000000..af6295e --- /dev/null +++ b/CODE/BT/BT/BTTEAM.CPP @@ -0,0 +1,152 @@ +//===========================================================================// +// File: btteam.cpp // +// Project: BattleTech // +// Contents: BattleTech Team Specifications // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/96 JM initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BTTEAM_HPP) +# include +#endif + +#if !defined(HOSTMGR_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#if !defined(BTCNSL_HPP) +# include +#endif + +//############################################################################# +//############################### BTTeam ############################### +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation + BTTeam::ClassDerivations(Team::ClassDerivations,"BTTeam"); + +BTTeam::SharedData + BTTeam::DefaultData( + BTTeam::ClassDerivations, + BTTeam::MessageHandlers, + BTTeam::AttributeIndex, + BTTeam::StateCount, + (BTTeam::MakeHandler)BTTeam::Make + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BTTeam::TeamSimulation( + Scalar // time_slice + ) +{ + Check(this); + // + //------------------------------------------------------------------------ + // Update the console every 15 seconds + //------------------------------------------------------------------------ + // + if (lastPerformance - lastConsoleUpdate >= 15.0f) + { + lastConsoleUpdate = lastPerformance; + + // + //--------------------------------------------- + // Tell the console (if there is one) our score + //--------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsoleBTTeamScoreUpdateMessage + score_message(ownerID, (int)teamScore); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &score_message + ); + } + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BTTeam::BTTeam( + MakeMessage *creation_message, + SharedData &shared_data +) : + Team (creation_message, shared_data) +{ + lastConsoleUpdate = lastPerformance; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BTTeam::~BTTeam() +{ + +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BTTeam* + BTTeam::Make(MakeMessage *creation_message) +{ + Check_Fpu(); + return new BTTeam(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BTTeam::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories +) +{ + Check(creation_message); + Check(model_file); + + if (!Team::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->classToCreate = BTTeamClassID; + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BTTeam::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/BT/BT/BTTEAM.HPP b/CODE/BT/BT/BTTEAM.HPP new file mode 100644 index 0000000..6113143 --- /dev/null +++ b/CODE/BT/BT/BTTEAM.HPP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: btteam.hpp // +// Project: BattleTech // +// Contents: BattleTech Team Specifications // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/96 JM initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined (BTTEAM_HPP) +# define BTTEAM_HPP + +# if !defined (TEAM_HPP) +# include +# endif + + //########################################################################## + //######################## CLASS BTTeam ############################## + //########################################################################## + class BTTeam : + public Team + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation + ClassDerivations; + + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + typedef void + (BTTeam::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + TeamSimulation(Scalar time_slice); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Console Support + // + protected: + + Time + lastConsoleUpdate; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction Support + // + public: + + BTTeam( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + + ~BTTeam(); + + Logical + TestInstance() const; + + static BTTeam* + Make(MakeMessage *creation_message); + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + }; +#endif diff --git a/CODE/BT/BT/BTTOOL.CPP b/CODE/BT/BT/BTTOOL.CPP new file mode 100644 index 0000000..225fcd1 --- /dev/null +++ b/CODE/BT/BT/BTTOOL.CPP @@ -0,0 +1,209 @@ +//===========================================================================// +// File: txttores.cpp // +// Project: Resource Tools // +// Author: Jerry Edsall // +// Purpose: Program to convert Notation files to MUNGA .res files. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include "bt.hpp" + +#if !defined(BTTOOL_HPP) +# include "bttool.hpp" +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(MECH_HPP) +# include "mech.hpp" +#endif + +#if !defined(BTPLAYER_HPP) +# include "btplayer.hpp" +#endif + +#if !defined(PROJTILE_HPP) +# include "projtile.hpp" +#endif + +#if !defined(MISSILE_HPP) +# include "missile.hpp" +#endif + +#if !defined(BTTEAM_HPP) +# include "btteam.hpp" +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BTTool::CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(class_name,"MechClassID")) + { + Mech::CreateMakeMessage( + (Mech::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name, "BTTeamClassID")) + { + BTTeam::CreateMakeMessage( + (BTTeam::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + + return + ApplicationTool::CreateMakeMessage( + class_name, + creation_message, + model_file, + directories + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BTTool::CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(model_class, "MechClassID")) + { +#if 0 + strcpy(ops_file_data, ops_name); + strcat(ops_file_data, "::Standard::Vehicle::"); + strcat(ops_file_data, model_name ); + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::Standard::VehicleList"); + + ops_file->AppendEntry(ops_file_page, "vehicle", ops_file_data); + ops_file->SetEntry(ops_file_data, "tag", model_name ); + ops_file->SetEntry(ops_file_data, "classID", "BTVh"); + ops_file->AppendEntry(ops_file_data, NULL, (char *)NULL); +#endif + + model_resources.gameResourceID = + Mech::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + model_resources.subsystemResourceID = + Mech::CreateSubsystemStream( + resource_file, + model_name, + model_file, + directories + ); + model_resources.damageZoneResourceID = + Mech::CreateDamageZoneStream( + resource_file, + model_name, + model_file, + directories + ); + model_resources.skeletonResourceID = + Mech::CreateSkeletonStream( + resource_file, + model_name, + model_file, + directories + ); + model_resources.explosionTableResourceID = + Mech::CreateExplosionTableStream( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "ProjectileClassID")) + { + model_resources.gameResourceID = + Projectile::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "MissileClassID")) + { + model_resources.gameResourceID = + Missile::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else + { + ApplicationTool::CreateModelResource( + model_resources, + model_class, + resource_file, + model_name, + model_file, + directories + ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + BTTool::CreateControlMappingStream( + const char *model_class, + const char *mapping_name, + NotationFile *mapping_file, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + ) +{ + if (!stricmp(model_class, "MechClassID")) + { + return + Mech::CreateControlMappingStream( + mapping_name, + mapping_file, + platformTool->GetControlMappingFunction(), + resource_file, + model_name, + model_file, + directories, + current_tool + ); + } + else + { + return -1; + } +} + diff --git a/CODE/BT/BT/BTTOOL.HPP b/CODE/BT/BT/BTTOOL.HPP new file mode 100644 index 0000000..03c4d52 --- /dev/null +++ b/CODE/BT/BT/BTTOOL.HPP @@ -0,0 +1,64 @@ +//===========================================================================// +// File: txttores.hpp // +// Project: Art Tools // +// Author: Jerry Edsall // +// Purpose: Program to convert Notation files to MUNGA .res files. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(BTTOOL_HPP) +# define BTTOOL_HPP + +# if !defined(TOOL_HPP) +# include +# endif + + //########################################################################## + //############################ RPTool ################################ + //########################################################################## + + class BTTool: + public ApplicationTool + { + protected: + Logical + CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + void + CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateControlMappingStream( + const char *model_class, + const char *mapping_name, + NotationFile *mapping_file, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + ); + + public: + BTTool(PlatformTool *platform): + ApplicationTool(platform) + {} + }; + +#endif + diff --git a/CODE/BT/BT/EMITTER.TCP b/CODE/BT/BT/EMITTER.TCP new file mode 100644 index 0000000..955244a --- /dev/null +++ b/CODE/BT/BT/EMITTER.TCP @@ -0,0 +1,101 @@ +#include "testbt.hpp" + +//############################################################################# +// Test Class -- Emitter +// + +Logical + Emitter::TestClass(Mech &mech) +{ + Emitter *emitter; + PowerBar *power_Bar; + Condenser *condenser; + Generator *generator; + const Scalar time_Slice = 0.05f; + +#if 0 + Tell("Testing Emitter .................\n"); + emitter = (Emitter*) mech.GetSubsystem(LaserSubsystemID); + power_Bar = (PowerBar*) mech.GetSubsystem(PowerBarSubsystemID); + condenser = (Condenser*) mech.GetSubsystem(CondenserSubsystemID); + generator = (Generator*) mech.GetSubsystem(GeneratorSubsystemID); + + // Test Initial Values as given in the resource file + Test(Close_Enough(emitter->dischargeVoltage, 3.8f)); + Test(Close_Enough(emitter->outputVoltage, 0.0f)); + Test(Close_Enough(emitter->currentTemperature, 300.0f)); + + // Run the simulation a few times + #if defined (TEST_DEBUG) + Dump(emitter->currentLevel); + Dump(emitter->outputVoltage); + Dump(emitter->currentTemperature); + #endif + Test(Close_Enough(emitter->currentLevel,0.0f)); + Test(Close_Enough(emitter->outputVoltage,0.0f)); + + // Run the Simulation Loops + MemoryStream stream(NULL, 0); + condenser->HeatSimulation(time_Slice, stream); + power_Bar->PoweredSimulation(time_Slice, stream); + emitter->EmitterSimulation(time_Slice, stream); + generator->GeneratorSimulation(time_Slice, stream); + + #if defined (TEST_DEBUG) + Dump(emitter->currentLevel); + Dump(emitter->outputVoltage); + Dump(emitter->currentTemperature); + #endif + + Test(Close_Enough(emitter->outputVoltage,0.00f,0.001f)); + Test(Close_Enough(emitter->currentTemperature, 300.00f,0.001f)); + + + emitter->outputVoltage = 5.0f; //Give it enough to fire! + #if defined (TEST_DEBUG) + Dump(emitter->outputVoltage); + #endif + + emitter->AcceptHeat(35.0f); + // Run the Simulation Loops + condenser->HeatSimulation(time_Slice, stream); + power_Bar->PoweredSimulation(time_Slice, stream); + emitter->EmitterSimulation(time_Slice, stream); + + #if defined (TEST_DEBUG) + Dump(emitter->currentLevel); + Dump(emitter->outputVoltage); + Dump(emitter->currentTemperature); + #endif + Test(Close_Enough(emitter->currentTemperature, 301.75f, 0.001f)); + + // Run the Simulation Loops + condenser->HeatSimulation(time_Slice, stream); + power_Bar->PoweredSimulation(time_Slice, stream); + emitter->EmitterSimulation(time_Slice, stream); + + #if defined( TEST_DEBUG) + Dump(emitter->currentLevel); + Dump(emitter->outputVoltage); + Dump(emitter->currentTemperature); + #endif + Test(Close_Enough(emitter->currentTemperature, 301.597f, 0.001f)); + + // Return Power Bar and Laser to Initial States! + condenser->ResetToInitialState(); + power_Bar->ResetToInitialState(); + emitter->ResetToInitialState(); + generator->ResetToInitialState(); +#endif + return True; +} +//######################################################################## +// resetToInitialState Emitter +// +void Emitter::ResetToInitialState() +{ + SetSimulationState(Loaded); + PoweredSubsystem::ResetToInitialState(); + +} + diff --git a/CODE/BT/BT/GAUSS.CPP b/CODE/BT/BT/GAUSS.CPP new file mode 100644 index 0000000..cb9cb0e --- /dev/null +++ b/CODE/BT/BT/GAUSS.CPP @@ -0,0 +1,153 @@ +//===========================================================================// +// File: gauss.cc // +// Project: BT Brick: Entity Manager // +// Contents: Basic weapons system pieces // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/13/95 JM Initial coding. // +// 07/19/95 GDU Complied with new munga and added electrical behavior +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(GAUSS_HPP) +# include +#endif + +//############################################################################# +// Shared Data Support +// +GaussRifle::SharedData + GaussRifle::DefaultData( + GaussRifle::ClassDerivations, + GaussRifle::MessageHandlers, + GaussRifle::AttributeIndex, + GaussRifle::StateCount + ); + +Derivation + GaussRifle::ClassDerivations( + Emitter::ClassDerivations, + "GaussRifle" + ); + + +//############################################################################# +// Messaging Support +// + +#if 0 +//############################################################################# +// Attribute Support +// + +const GaussRifle::IndexEntry + GaussRifle::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(GaussRifle, DischargeVoltage, dischargeVoltage) +}; + +GaussRifle::AttributeIndexSet + GaussRifle::AttributeIndex( + ELEMENTS(GaussRifle::AttributePointers), + GaussRifle::AttributePointers, + Emitter::AttributeIndex + ); +#endif + +//############################################################################# +// Model Support +// + +void + GaussRifle::FireWeapon() +{ + // + // Fire the weapon + // + outputVoltage = 0.0f; + + Check_Fpu(); +} + +//############################################################################# +// Constructer/Destructor Support +// + +GaussRifle::GaussRifle( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + Emitter(owner, subsystem_ID, subsystem_resource, shared_data) +{ + Check(owner); + Check_Pointer(subsystem_resource); + outputVoltage = 0.0f; + Check_Fpu(); +} + +GaussRifle::~GaussRifle() +{ + Check(this); + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateStreamedSubsystem +// +Logical + GaussRifle::CreateStreamedSubsystem( + ResourceFile *resource_file, + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes + ) +{ + + if ( + !Emitter::CreateStreamedSubsystem( + resource_file, + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + directories, + passes + ) + ) + { + Check_Fpu(); + return False; + } + + + + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::GaussRifleClassID; + + + Check_Fpu(); + return True; +} + +Logical + GaussRifle::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/BT/BT/GAUSS.HPP b/CODE/BT/BT/GAUSS.HPP new file mode 100644 index 0000000..74270fe --- /dev/null +++ b/CODE/BT/BT/GAUSS.HPP @@ -0,0 +1,144 @@ +//===========================================================================// +// File: gauss.hh // +// Project: BT Brick: Entity Manager // +// Contents: Gauss Rifle class, derives from Projectile Weapon // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/13/95 JM Initial coding. // +// 07/19/95 GDU Complied to new munga, added new electrical behavior // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined (GAUSS_HPP) +#define GAUSS_HPP + +#if !defined(EMITTER_HPP) +# include +#endif + + +//##################### Forward Class Declarations ####################### +class Mech; +class Projectile; + +//########################################################################### +//######################### GaussRifle Model Resource ######################## +//########################################################################### + struct GaussRifle__SubsystemResource: + public Emitter::SubsystemResource + { + Scalar dischargeVoltage; + }; +//########################################################################### +//######################### CLASS -- GaussRifle ########################## +//########################################################################### + class GaussRifle : public Emitter + { + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messageing Support + // + +#if 0 + //########################################################################## + // Attribute Support + // + public: + + enum { + = Emitter::NextAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + public: + static AttributeIndexSet AttributeIndex; +#endif + + //########################################################################## + // Model Support + // + public: + + + typedef void + (GaussRifle::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + GaussRifleSimulation(Scalar time_slice); + + //########################################################################## + // TestClass Support + // + public: + + static Logical + TestClass(Mech &); + void + ResetToInitialState(); + + //########################################################################## + // Construction and Destruction + // + public: + typedef GaussRifle__SubsystemResource SubsystemResource; + + GaussRifle( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data=DefaultData + ); + ~GaussRifle(); + + Logical + TestInstance() const; + + static int + CreateStreamedSubsystem( + ResourceFile *resource_file, + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes =1 + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local data for the gun class + // + + protected: + + void + FireWeapon(); + + Vector3D + muzzleVelocity; + + }; + + +#endif diff --git a/CODE/BT/BT/GNRATOR.TCP b/CODE/BT/BT/GNRATOR.TCP new file mode 100644 index 0000000..ee9f89c --- /dev/null +++ b/CODE/BT/BT/GNRATOR.TCP @@ -0,0 +1,18 @@ +#include "testbt.hpp" + +//############################################################################# +// TestClass -- Generator +// +Logical Generator::TestClass(Mech &) +{ + return True; +} + +//########################################################################### +// ResetToIntialState -- Generator +// +void Generator::ResetToInitialState() +{ + HeatableSubsystem::ResetToInitialState(); + outputVoltage = 0.0f; +} \ No newline at end of file diff --git a/CODE/BT/BT/HEAT.TCP b/CODE/BT/BT/HEAT.TCP new file mode 100644 index 0000000..1f01e43 --- /dev/null +++ b/CODE/BT/BT/HEAT.TCP @@ -0,0 +1,58 @@ +#include "heat.hpp" +#include "app.hpp" +#include "testbt.hpp" + +#define JM_CLOSE_ENOUGH 0.0005f + + +//########################################################################### +// Test Class for HeatableSubsystem +// +Logical + HeatableSubsystem::TestClass(Mech &) +{ + return True; +} +//########################################################################### +// ResetToIntialState -- HeatableSubsystem +// +void HeatableSubsystem::ResetToInitialState() +{ + currentTemperature = 300.0f; + heatLoad = 0.0f; +} + + + +//########################################################################### +// Test Class for Condenser +// +Logical Condenser::TestClass( Mech& ) +{ + + return True; +} +//########################################################################### +// ResetToIntialState -- Condenser +// +void Condenser::ResetToInitialState() +{ + HeatableSubsystem::ResetToInitialState(); +} +//########################################################################### +// Test Class for HeatSink +// + +Logical HeatSink::TestClass( Mech& ) +{ + return True; +} + +//########################################################################### +// ResetToIntialState -- Condenser +// +void HeatSink::ResetToInitialState() +{ + HeatableSubsystem::ResetToInitialState(); +} + diff --git a/CODE/BT/BT/MECHDMG.HPP b/CODE/BT/BT/MECHDMG.HPP new file mode 100644 index 0000000..e5ea48b --- /dev/null +++ b/CODE/BT/BT/MECHDMG.HPP @@ -0,0 +1,208 @@ +//==========================================================================// +// File: mechdmg.hpp // +// Project: BattleTech // +// Contents: Mech::DamageZone // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 06/05/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MECHDMG_HPP) +# define MECHDMG_HPP + +# if !defined(DAMAGE_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + +# if !defined(ENTITYID_HPP) +# include +# endif + + class Mech; + class Subsystem; + class DamageZone; + + //########################################################################## + //###################### MechCriticalSubsystem ################# + //########################################################################## + + class + MechCriticalSubsystem SIGNATURED + { + public: + + MechCriticalSubsystem(DamageZone *owner); + + virtual ~MechCriticalSubsystem(); + + SlotOf + subsystemPlug; + + Scalar + damagePercentage, damagePercentageUsed; + + Scalar + criticalWeight; + + Logical + TestInstance() const; + + }; + + + //########################################################################## + //#################### Mech::DamageZone ########################### + //########################################################################## + + class Mech__DamageZone : + public DamageZone + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // LOD Support + // + protected: + + void + LODDamageRouter(EntityID inflicting, Damage damage); + + int + RandomRedirect(); + + typedef PlugOf IntegerPlug; + + typedef TableOf DamageZoneIndexTable; + + typedef TableIteratorOf DamageZoneIndexTableIterator; + + + // Zones which are artifacts have a table of their real children. + + DamageZoneIndexTable redirectTable; + + // The result of the last random redirect + + int lastHitZone; + Scalar lastDamageTime; + EntityID lastInflicting; + // + // Zones which are real have a pointer (slot) back to their artifact parent. + // With the current art (1/30/96) no zone has both a parent and children, + // and many zones have neither. + + SlotOf parentArtifactZone; + + void + UpdateLODDamageLevel(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Descending Heirarchy when DamageZone Destroyed Support + // + void + ShortAttachedGenerators(); + + void + SendSubsystemDamage(); + + void + RecurseSegmentTable(Mech *my_mech); + + int + segmentIndex; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Damage Support + // + public: + + void + TakeDamage(Damage& damage); + + Subsystem* + CriticalHit(Damage &damage_data); + + protected: + + Logical + vitalDamageZone; + + Logical + descendOnDestruction; + + Logical + destroySiblingsOnDestruction; + + Logical + leftLeg; + + Logical + rightLeg; + + int + criticalSubsystemCount; + + Scalar + criticalWeightSum; + + MechCriticalSubsystem + **criticalSubsystems; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Graphic State Support + // + + public: + + void + SetGraphicState(Enumeration new_state); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction + // + + public: + + static const int NullDamageZone; + + Mech__DamageZone( + Mech *mech, + int damage_zone_index, + MemoryStream *stream + ); + + void SetLODParentPointers(); + + ~Mech__DamageZone(); + + static Logical + CreateStreamedDamageZone( + ResourceFile *resource_file, + NotationFile *model_file, + const char *model_name, + NotationFile *skl_file, + const char *damage_zone_name, + NotationFile *dmg_file, + const ResourceDirectories *directories, + MemoryStream *damage_zone_stream + ); + + static int + GetSegmentIndex( + CString damage_zone_name, + NotationFile *skl_file + ); + }; + +#endif diff --git a/CODE/BT/BT/MECHTECH.HPP b/CODE/BT/BT/MECHTECH.HPP new file mode 100644 index 0000000..801d6dd --- /dev/null +++ b/CODE/BT/BT/MECHTECH.HPP @@ -0,0 +1,149 @@ +#if !defined(MECHTECH_HPP) +# define MECHTECH_HPP + +# if !defined(MECHSUB_HPP) +# include +# endif + + //########################################################################## + //###################### MechTech::StatusInfo ######################## + //########################################################################## + + struct MechTech__StatusInfo SIGNATURED + { + public: + int + currentStatus, + wooHooed; + Time + startTime, + wooHooEnd; + }; + + //########################################################################## + //###############3### MechTech::SubsystemMonitor ##################### + //########################################################################## + + struct MechTech__SubsystemMonitor: + public Plug + { + friend class MechTech; + + //########################################################################## + // Memory Allocation Support + // + private: + static MemoryBlock AllocatedMemory; + + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + + public: + MechTech__StatusInfo statusArray[MechSubsystem::TechStatusTypeCount]; + MechSubsystem *monitoredSubsystem; + + MechTech__SubsystemMonitor(MechSubsystem *subsystem); + ~MechTech__SubsystemMonitor(); + }; + + //########################################################################## + //##################### MechTech::ModelResource ###################### + //########################################################################## + + struct MechTech__SubsystemResource: + public Subsystem::SubsystemResource + { + ResourceDescription::ResourceID + alarmModel; + Scalar + wooHooMinimumDuration, + wooHooDurationRange, + wooHooChance; + }; + + //########################################################################## + //############################ MechTech ############################## + //########################################################################## + + class MechTech: + public Subsystem + { + //########################################################################## + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //########################################################################## + // Attribute Support + // + public: + typedef MechTech__StatusInfo StatusInfo; + typedef MechTech__SubsystemMonitor SubsystemMonitor; + typedef MechTech__SubsystemResource SubsystemResource; + + //########################################################################## + // Construction and Destruction Support + // + public: + ~MechTech(); + + static Logical + CreateStreamedSubsystem( + NotationFile *model_file, + const char* model_name, + const char* subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + ResourceFile *resource_file + ); + + MechTech( + Mech *entity, + int subsystem_id, + SubsystemResource *model, + SharedData &shared_data = DefaultData + ); + + Logical + TestInstance() const; + + //########################################################################## + // Model support + // + public: + typedef void + (MechTech::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + ChainOf subsystemMonitors; + Scalar + wooHooMinimumDuration, + wooHooDurationRange, + wooHooChance; + + ResourceDescription::ResourceID + alarmModel; + + void + TechnicalAssistance(Scalar time_slice); + + Mech* + GetEntity() + {return (Mech*)Subsystem::GetEntity();} + }; + +#endif + diff --git a/CODE/BT/BT/MESSMGR.HPP b/CODE/BT/BT/MESSMGR.HPP new file mode 100644 index 0000000..5f36f2a --- /dev/null +++ b/CODE/BT/BT/MESSMGR.HPP @@ -0,0 +1,184 @@ +//===========================================================================// +// File: messmgr.hh // +// Project: BattleTech // +// Contents: Consolidates Messages from Subsystems and Graphics Generation // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/30/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined (MESSMGR_HPP) +# define MESSMGR_HPP + +#if !defined (SUBSYSTM_HPP) +# include +#endif + +#if !defined (RESOURCE_HPP) +# include +#endif + +#if !defined (VCHAIN_HPP) +# include +#endif + +#if !defined (PLUG_HPP) +# include +#endif + +#if !defined(ENTITYID_HPP) +# include +#endif + +class Entity; +class Mech; +class Entity__TakeDamageMessage; + +//########################################################################## +//########## SubsystemMessageManager::SubsystemResource ############### +//########################################################################## +struct SubsystemMessageManager__SubsystemResource : + public Subsystem::SubsystemResource +{ + ResourceDescription::ResourceID + terrainHitExplosionID; + + Scalar + rendererCompensateTime; +}; + +//########################################################################## +//##################### SubsystemMessageManager ################### +//########################################################################## +class + SubsystemMessageManager : + public Subsystem + +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Death and Damage Support +// + + public: + + void DeathReset(Logical) {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// + protected: + + struct CommonDamageInformation + { + Entity + *entityHit; + + int + damageZoneIndex; + + Point3D + impactPoint; + + } commonDamageInformation; + + public: + + struct DamageInformation + : public Plug + { + Enumeration + damageType; + + int + subsystemID; + }; + + typedef void + (SubsystemMessageManager::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + void + ConsolidateAndSendDamage(Scalar time_slice); + + Mech* + GetEntity() + {Check(this); return Cast_Object(Mech*, Subsystem::GetEntity());} + + protected: + + Scalar + rendererCompensateTime; + + typedef PlugOf + ResourceIDPlug; + + VChainOf + weaponExplosions; + + VChainOf damageInformation; + + ResourceDescription::ResourceID + terrainHitExplosionID; + + void + CreateWeaponExplosions( + Logical terrain_hit, + EntityID entity_hit, + Point3D explode_position + ); + + public: + + void + AddDamageMessage( + Entity *damaged_entity, + Entity__TakeDamageMessage *message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// + public: + + typedef SubsystemMessageManager__SubsystemResource SubsystemResource; + + SubsystemMessageManager( + Mech *owner, + int subsystem_ID, + SubsystemResource *sub_res, + SharedData &shared_data=DefaultData + ); + + ~SubsystemMessageManager(); + + Logical + TestInstance() const; + + static Logical + CreateStreamedSubsystem( + ResourceFile *resource_file, + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ); +}; +#endif diff --git a/CODE/BT/BT/MISLANCH.HPP b/CODE/BT/BT/MISLANCH.HPP new file mode 100644 index 0000000..4eb54de --- /dev/null +++ b/CODE/BT/BT/MISLANCH.HPP @@ -0,0 +1,120 @@ +//============================================================================// +// File: mislanch.hh // +// Project: BattleTech // +// Contents: Weapon Which Lanches a missile // +// Derived From Projectile Weapon // +//----------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ------------------------------------------------------------// +// 04/13/95 JM Initial coding. // +//----------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//============================================================================// + +#if !defined (MISLANCH_HPP) +# define MISLANCH_HPP + +# if !defined(PROJWEAP_HPP) +# include +# endif + + +class Missile; + +//################# MissileLauncher SubsystemResource ################### + struct MissileLauncher__SubsystemResource: + public ProjectileWeapon::SubsystemResource + { + int missileCount; + + Vector3D + muzzleVelocity; + }; + + +//########################################################################### +//################# CLASS -- MissileLauncher ########################## +//########################################################################### + + class MissileLauncher: + public ProjectileWeapon + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messaging Support + // + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Damage Support + // + public: + void TakeDamage(Damage &damage); + void DeathReset(Logical full_reset); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + typedef void + (MissileLauncher::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + + typedef MissileLauncher__SubsystemResource SubsystemResource; + MissileLauncher( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &default_data = DefaultData + ); + ~MissileLauncher(); + + Logical + TestInstance() const; + + static Logical + CreateStreamedSubsystem( + ResourceFile *resource_file, + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes =1 + ); + + +// local stuff + protected: + + void + FireWeapon(); + + int missileCount; // how many individual missiles get fired at once + + }; +#endif diff --git a/CODE/BT/BT/MISSILE.TCP b/CODE/BT/BT/MISSILE.TCP new file mode 100644 index 0000000..36abb36 --- /dev/null +++ b/CODE/BT/BT/MISSILE.TCP @@ -0,0 +1,44 @@ +#include "testbt.hpp" +#include "projweap.hpp" + + +//############################################################################# +// Missile Test Class +// + +Logical Missile::TestClass(Mech &mech) +{ + ProjectileWeapon *gun; + Missile *missile; + MissileThruster *thruster; + Seeker *seeker; + Scalar time_slice =0.5f; + + gun = (ProjectileWeapon*) mech.GetSubsystem(ProjectileWeaponSubsystemID); + + gun->triggerState = 1; + MemoryStream stream(NULL, 0); + gun->ProjectileWeaponSimulation(time_slice, stream); + gun->triggerState = -1; + + missile = (Missile*) gun->currentProjectile; // BAD!!! + Check(missile); + thruster = (MissileThruster*) missile->GetSubsystem(Missile::MissileThrusterSubsystem); + seeker = (Seeker*) missile->GetSubsystem(Missile::SeekerSubsystem); + Check(thruster); + Check(seeker); + + seeker->FindTarget(time_slice, stream); + thruster->MissileThrusterSimulation(time_slice, stream); + missile->MoveAndCollide(time_slice, stream); + + time_slice = 5.0f; + gun->ProjectileWeaponSimulation(time_slice, stream); + seeker->FindTarget(time_slice, stream); + thruster->MissileThrusterSimulation(time_slice, stream); + missile->MoveAndCollide(time_slice, stream); + + + return True; +} + diff --git a/CODE/BT/BT/MISTHRST.HPP b/CODE/BT/BT/MISTHRST.HPP new file mode 100644 index 0000000..2db0140 --- /dev/null +++ b/CODE/BT/BT/MISTHRST.HPP @@ -0,0 +1,141 @@ +//============================================================================// +// File: misthrst.hh // +// Project: BattleTech // +// Contents: Missile Thruster provides power to move the missile // +//----------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ------------------------------------------------------------// +// 04/13/95 JM Initial coding. // +//----------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//============================================================================// + +#if !defined (MISTHRST_HPP) + #define MISTHRST_HPP + + #if !defined(SUBSYSTM_HPP) + #include + #endif + + #if !defined(ANGLE_HPP) + #include + #endif + + #if !defined(MOTION_HPP) + #include + #endif + +//################### Froward Class Declarations ###################### +class Missile; + +//################### MissileThruster SubsystemResource ################# + + struct MissileThruster__SubsystemResource: + public Subsystem::SubsystemResource + { + Scalar burnTime; + Degree maxThrusterRotationRate; + Scalar thrusterAcceleration; + Scalar thrusterClimb; + }; + + +//########################################################################### +//######################### CLASS -- MissileThruster ################## +//########################################################################### + + + class MissileThruster : + public Subsystem + { + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// + +public: + enum { + BurnTimeRemainingAttributeID = Subsystem::NextAttributeID, + MaxThrusterRotationRateAttributeID, + ThrusterAccelerationAttributeID, + NextAttributeID + }; + + public: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Scalar burnTimeRemaining; + Radian maxThrusterRotationRate; + const Scalar thrusterAcceleration; + const Scalar thrusterClimb; + Motion acceleration; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// + public: + enum { + ThrusterBurning= Subsystem::StateCount, + StateCount + }; + + typedef void + (MissileThruster::*Performance)(Scalar time_slice); + + void + MissileThrusterSimulation(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestClass Support +// + public: + + static Logical + TestClass(Missile &); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// + public: + + typedef MissileThruster__SubsystemResource SubsystemResource; + + MissileThruster( + Missile *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~MissileThruster(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local Support +// + +}; +#endif diff --git a/CODE/BT/BT/MSSCCPRJ.SCC b/CODE/BT/BT/MSSCCPRJ.SCC new file mode 100644 index 0000000..d646e74 --- /dev/null +++ b/CODE/BT/BT/MSSCCPRJ.SCC @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[bt.mak] +SCC_Aux_Path = "\\AVATAR\Mungass\VSS" +SCC_Project_Name = "$/Tesla_BT/BT", YOCAAAAA diff --git a/CODE/BT/BT/PPC.CPP b/CODE/BT/BT/PPC.CPP new file mode 100644 index 0000000..ed3fa15 --- /dev/null +++ b/CODE/BT/BT/PPC.CPP @@ -0,0 +1,166 @@ +//===========================================================================// +// File: ppc.cc // +// Project: BattleTech // +// Contents: Particle Projection Cannon // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/13/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined (PPC_HPP) +# include +#endif + +#if !defined(BTPLAYER_HPP) +# include +#endif + +#if !defined(BTMSSN_HPP) +# include +#endif + +//############################################################################# +// Shared Data Support +// +PPC::SharedData + PPC::DefaultData( + PPC::ClassDerivations, + PPC::MessageHandlers, + PPC::AttributeIndex, + PPC::StateCount + ); + +Derivation + PPC::ClassDerivations( + Emitter::ClassDerivations, + "PPC" + ); + +//############################################################################# +// Model Data Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + PPC::FireWeapon() +{ + Check(this); + + Emitter::FireWeapon(); + + + return; + + #if 0 + Check(this); + + Mech *mech = GetEntity(); + Check(mech); + + BTPlayer *bt_player = Cast_Object( + BTPlayer*, + mech->GetPlayerLink() + ); + Check(bt_player); + Enumeration experienceLevel = bt_player->GetExperienceLevel(); + + if (experienceLevel == BTMission::NoviceMode) + { + return; + } + + if (targetWithinRange) + { + Damage energy_damage(damageData); + energy_damage.damageType = Damage::EnergyDamageType; + energy_damage.damageAmount = 0.0f; + + Mech *mech = GetEntity(); + Check(mech); + + SendDamage( + mech->targetReticle.targetEntity, + energy_damage + ); + } + #endif +} +//############################################################################# +// Constructer/Destructor Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +PPC::PPC( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + Emitter(owner, subsystem_ID, subsystem_resource, shared_data) +{ + + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +PPC::~PPC() +{ + +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Create Streamed Subsystem +// +Logical + PPC::CreateStreamedSubsystem( + ResourceFile *resource_file, + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes + ) +{ + if ( + !Emitter::CreateStreamedSubsystem( + resource_file, + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + directories, + passes + ) + ) + { + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::PPCClassID; + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + PPC::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/BT/BT/PPC.HPP b/CODE/BT/BT/PPC.HPP new file mode 100644 index 0000000..0524dee --- /dev/null +++ b/CODE/BT/BT/PPC.HPP @@ -0,0 +1,67 @@ +//===========================================================================// +// File: ppc.hh // +// Project: BattleTech // +// Contents: Particle Projection Cannon // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/13/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined (PPC_HPP) +# define PPC_HPP + +#if !defined(EMITTER_HPP) + #include +#endif + +class PPC : + public Emitter +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// + public: + + PPC( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data + ); + ~PPC(); + + Logical + TestInstance() const; + + static int + CreateStreamedSubsystem( + ResourceFile *resource_file, + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes = 1 + ); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local Data +// + protected: + + void + FireWeapon(); + +}; +#endif diff --git a/CODE/BT/BT/PROJTILE.TCP b/CODE/BT/BT/PROJTILE.TCP new file mode 100644 index 0000000..ce27a9b --- /dev/null +++ b/CODE/BT/BT/PROJTILE.TCP @@ -0,0 +1,12 @@ +#include "testbt.hpp" + +//############################################################################# +// Projectile Test Class +// + +Logical Projectile::TestClass() +{ + return True; +} + + diff --git a/CODE/BT/BT/PROJWEAP.TCP b/CODE/BT/BT/PROJWEAP.TCP new file mode 100644 index 0000000..d4c0b5f --- /dev/null +++ b/CODE/BT/BT/PROJWEAP.TCP @@ -0,0 +1,20 @@ +#include "projweap.hpp" +#include "testbt.hpp" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ProjectileWeapon Test Class +// +Logical ProjectileWeapon::TestClass(Mech &) +{ + + return True; + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Reset To InitialState +// +void ProjectileWeapon::ResetToInitialState() +{ + +} \ No newline at end of file diff --git a/CODE/BT/BT/SEEKER.HPP b/CODE/BT/BT/SEEKER.HPP new file mode 100644 index 0000000..b928825 --- /dev/null +++ b/CODE/BT/BT/SEEKER.HPP @@ -0,0 +1,134 @@ +//=========================================================================// +// File: seeker.hpp // +// Project: BattleTech // +// Contents: A subsystem which guides, seek out and find a target // +//----------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ------------------------------------------------------------// +// 04/13/95 JM Initial coding. // +// 07/12/95 GDU Complied with new libraries, added seeker logic // +//----------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//============================================================================// + +#if !defined (SEEKER_HPP) +#define SEEKER_HPP + +#if !defined(SUBSYSTM_HPP) + #include +#endif + +#if !defined(POINT3D_HPP) + #include +#endif + + + +//######################### Forward Class Declarations ######################## + class Missile; + class Entity; + +//######################### Seeker Subsystem Resource ########################## + struct Seeker__SubsystemResource: + public Subsystem::SubsystemResource + { + + + }; +//########################################################################### +//######################### CLASS -- Seeker ########################## +//########################################################################### + class Seeker : public Subsystem + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messaging Support + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + TargetPositionAttributeID = Subsystem::NextAttributeID, + RangeToTargetAttributeID, + RangeFromCreationAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Point3D targetPosition; // for thruster + const Point3D creationPoint; // where the missile was fired from + Entity *targetEntity; + const Point3D targetOffset; + Scalar rangeToTarget, rangeFromCreation, startingRangeToTarget; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + enum { + Empty = Subsystem::StateCount, + StateCount}; + + typedef void + (Seeker::*Performance)(Scalar time_slice); + + + void + LeadTarget(); + void + FindTarget(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // TestClass Support + // + public: + + static Logical + TestClass(Missile &); + void + ResetToInitialState(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef Seeker__SubsystemResource SubsystemResource; + + Seeker ( + Missile *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + Entity *target, + const Point3D offset + ); + ~Seeker(); + + Logical + TestInstance() const; + }; +#endif diff --git a/CODE/BT/BT/SENSOR.HPP b/CODE/BT/BT/SENSOR.HPP new file mode 100644 index 0000000..414e968 --- /dev/null +++ b/CODE/BT/BT/SENSOR.HPP @@ -0,0 +1,143 @@ +//===========================================================================// +// File: sensor.hpp // +// Project: BattleTech // +// Contents: Sensor subsystem // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 8/10/95 GDU Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// +#if !defined(SENSOR_HPP) +# define SENSOR_HPP + +#if !defined(POWERSUB_HPP) + #include "powersub.hpp" +#endif + + +//########################################################################## +//################# SensorSubsystemResource ####################### +//########################################################################## + + struct Sensor__SubsystemResource: + public PoweredSubsystem::SubsystemResource + { + + }; + +//########################################################################## +//########################## Sensor ############################### +//########################################################################## + + class Sensor: + public PoweredSubsystem + { + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Death and Damage Support + // + public: + + void + TakeDamage(Damage &damage); + + void + DeathReset(Logical full_recovery); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// + public: + enum { + RadarPercentAttributeID = PoweredSubsystem::NextAttributeID, + SelfTestAttributeID, + BadVoltageAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + + + public: + Scalar + radarPercent; + Logical + selfTest, + badVoltage; + + +//########################################################################## +// Simulation Support +// + public: + + typedef void + (Sensor::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + SensorSimulation(Scalar time_slice); + +//########################################################################## +// Test Class Support +// + public: + static Logical + TestClass(Mech&); + void + ResetToInitialState(); + +//########################################################################## +// Construction and Destruction +// + public: + typedef Sensor__SubsystemResource SubsystemResource; + + Sensor( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Sensor(); + + Logical + TestInstance() const; + + static int + CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes = 1 + ); +}; + + + + + +#endif diff --git a/CODE/BT/BT/TESTBT.HPP b/CODE/BT/BT/TESTBT.HPP new file mode 100644 index 0000000..8225286 --- /dev/null +++ b/CODE/BT/BT/TESTBT.HPP @@ -0,0 +1,68 @@ + +#if !defined(TESTBT_HPP) +# define TESTBT_HPP + +# if !defined(APP_HPP) +# include +# endif + +# if !defined(APP_THP) +# include +# endif + +# if !defined(MISSION_HPP) +# include +# endif + +#define TEST_DEBUG + + //########################################################################## + //###################### TestBTApplication ########################## + //########################################################################## + + class TestBTApplication: + public TestApplication + { + public: + TestBTApplication(StreamableResourceFile *resource); + ~TestBTApplication(); + + static Logical + ParseCommandLine( + int argc, + char *argv[], + CString *egg_notation_file_name + ); + + private: + Registry* + MakeRegistry(); + Entity* + MakeViewpointEntity(Entity::MakeMessage *message); + }; + + //########################################################################## + //########################### TestBTMission ########################## + //########################################################################## + + class TestBTMission: + public Mission + { + public: + TestBTMission( + NotationFile *notation_file, + StreamableResourceFile *resources + ); + ~TestBTMission(); + + Logical + TestInstance() const; + + void + CreatePlayerMessage( + NotationFile *notation_file, + StreamableResourceFile *resources + ); + }; + +#endif diff --git a/CODE/BT/BT/TURRET.HPP b/CODE/BT/BT/TURRET.HPP new file mode 100644 index 0000000..32b63e0 --- /dev/null +++ b/CODE/BT/BT/TURRET.HPP @@ -0,0 +1,148 @@ +//===========================================================================// +// File: jmover.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(TURRET_HPP) +# define TURRET_HPP + +# if !defined(JMOVER_HPP) +# include +# endif + + //########################################################################## + //################## Turret::ModelResource ########################### + //########################################################################## + + struct Turret__ModelResource: + JointedMover::ModelResource + { + char turretJointName[32]; + char gunJointName[32]; + ResourceDescription::ResourceID + explosionResourceID; + Scalar + rotationSpeedMin, + rotationSpeedMax, + elevationSpeedMin, + elevationSpeedMax, + rateSkillMin, + rateSkillMax, + rateAdjMin, + rateAdjMax, + accuracySkillMin, + accuracySkillMax, + accuracyAdjMin, + accuracyAdjMax; + }; + +#if 0 + //########################################################################## + //################## Turret::ModelResource ########################### + //########################################################################## + + class Turret__MakeMessage: + JointedMover::MakeMessage + { + public: + char teamName[32]; + char roleName[32]; + }; +#endif + + //########################################################################## + //######################### Turret ################################### + //########################################################################## + + class Turret: + public JointedMover + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + #if 0 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + private: + static const HandlerEntry MessageHandlerEntries[]; + protected: + static MessageHandlerSet MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum{ + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef Turret__ModelResource ModelResource; + typedef void + (Turret::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + static Logical + CreateMakeMessage( + MemoryStream &creation_stream, + NotationFile *model_file, + const ResourceDirectories *directories + ); + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + + static Turret* + Make(MakeMessage *creation_message); + + Turret( + MakeMessage *creation_message, + SharedData &virtual_data + ); + ~Turret(); + + Logical + TestInstance() const; + }; + +#endif + diff --git a/CODE/BT/BT/VSSVER.SCC b/CODE/BT/BT/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..68c376a07b21d225405b6268412874cf260219fd GIT binary patch literal 1376 zcmXxhdrS>b90%~*Ll4qhc~mOh+vD~wjd_%4Q#4|`k)=P_#nj|gvM@%;CYzC^M(&n* z^jgCoCL5J3E$LQBvEFq{SKLaETfWEkJ^!42_B-eII49KBKq5)AeBkr6$>w&f#I;-| z{Tl9fF|ol!@_%(<4{uaVDDAd;;H0D*u9B2R(LM0}zD+K4FRTyJN$Ea#XtKSR?uXr{ zW7PBjoP6{2XL=A;v}eWBLvXfpU_PyZe?;%RMGwO_PTk(GtSOL*{zl;UJSaBh0k14q|m?MOqF9aJq90lG+#phhD#$#cGG|0;nwaPS_kjCHZP^e z;o8FfxAX+uno-n5Pr~Q)op0#B!a5f(<&?(T5dBZVJ5;50!eYK@I3P`RnVx~&O2cO9 zSvamUH;>lC>$2xM=s7t2TATwt52xpyG@vD>_}`hR6SM*RXfSeA`DCq^sBZ|r&`u=? zi}y8x*G!Mg7&nHCT)&^C7r+BkhIfU=e2d@+w?kiO3s_xb5koJAm+m`wkG6#Kj->Voi+on%ep5m) zZ4F0%n7K~dz|a3&E~aha)3v@sv>j|Ft6WXn!?p3ra(W58Cum>;?EqhmjEX;0bMy+hT6WBtc7i{>^vI!|;dgfvHqtKe#<19A zdL?{uF5@8W3Ku@sW++8=JtO48B+a7V!Fd^!+Trzo80Ab7q-|B4QVD_Zup(jl-^)3JpPh3iYUJ*NKw D^lD@K literal 0 HcmV?d00001 diff --git a/CODE/BT/BTL4.BLD b/CODE/BT/BTL4.BLD new file mode 100644 index 0000000..e8b1227 --- /dev/null +++ b/CODE/BT/BTL4.BLD @@ -0,0 +1,211 @@ +[release] +version=1.0 + +// +// Official resource maps and models should have an +// id assigned to them, as should any object that could show up on a mission +// review spool (even a test one). +// +// the format is xxxxx=xxxx.xxx /id:# +// + +// The next number to use is: 149 +// + +[resource] +name=btl4.res +dircollision=solids\ +dirmodel=models\ +dirmap=maps\ +diraudio=audio\ +dirvideo=video\ +dirgauge=gauge\ +diranimation=anims\ +// +// Player Model File +// +model=player.mod /id:75 +// +// Explosion Model Files +// +model=lzrhiti.mod /id:1 +model=ppchiti.mod /id:2 +model=canhiti.mod /id:3 +model=mslhiti.mod /id:4 +model=dam3exp.mod /id:5 +model=dam4exp.mod /id:6 +model=dam4expi.mod /id:7 +model=dam1hiti.mod /id:8 +model=dam2hiti.mod /id:9 +model=dam3hiti.mod /id:10 +model=dam4hiti.mod /id:11 +model=desthiti.mod /id:12 +static=explode.onl +model=explode.mod /id:13 +//model=mghit.mod /id:14 +model=ppchit.mod /id:15 +model=lzrhit.mod /id:16 +model=mslhit.mod /id:17 +model=canhit.mod /id:18 +model=gndhit.mod /id:19 +model=minhit.mod /id:20 +model=majhit.mod /id:21 +model=blhdead.mod /id:22 +model=lokdead.mod /id:23 +model=maddead.mod /id:76 +model=owndead.mod /id:24 +model=thrdead.mod /id:25 +model=vuldead.mod /id:77 +model=avadead.mod /id:113 +model=mechdead.mod /id:74 +model=dam1hit.mod /id:26 +model=dam2hit.mod /id:27 +model=dam3hit.mod /id:28 +model=dam4hit.mod /id:29 +model=desthit.mod /id:30 +model=stephit.mod /id:31 +model=trkdead.mod /id:32 +model=smldead.mod /id:78 +model=meddead.mod /id:34 +model=bigdead.mod /id:33 +model=msldead.mod /id:79 +model=twrdead.mod /id:80 +// +// Ballistic Ammo +// +model=projtile.mod /id:35 +model=srm.mod /id:36 +model=lrm.mod /id:37 +// +// Scenario Role Model Files +// +//model=convoy.mod /id:38 +model=dfltrole.mod /id:39 +//model=attacker.mod /id:40 +//model=defender.mod /id:41 +//model=decoy.mod /id:42 +//model=hostage.mod /id:43 +//model=ambssdor.mod /id:44 +model=NoReturn.mod /id:112 +// +// Mech Model Files +// +model=mechalrm.mod /id:83 +// + +model=madcat.mod /id:72 +model=mad1.mod /id:118 +model=loki.mod /id:45 +model=lok1.mod /id:119 +model=thor.mod /id:46 +model=thr1.mod /id:115 +model=blkhawk.mod /id:47 +model=bhk1.mod /id:116 +model=owens.mod /id:48 +model=vulture.mod /id:73 +model=vul1.mod /id:117 +model=avatar.mod /id:110 +model=ava1.mod /id:114 +model=sunder.mod /id:111 + + +//model=firstrtr.mod +//model=blkjack.mod +//model=raptor.mod +//model=wpnmech.mod +//model=strider.mod +// +// Camera Model File +// +model=camera.mod /id:49 +// +// Cultural Icons (stuff what can blow up) +// +model=tt1.mod /id:50 +model=tt2.mod /id:51 +model=snh.mod /id:52 +model=trk1.mod /id:53 +model=trk3.mod /id:54 +model=trk4.mod /id:55 +model=bpip1.mod /id:56 +model=bac1.mod /id:57 +model=awwlk1.mod /id:58 +model=adwlk1.mod /id:59 +model=adwlk2.mod /id:60 +model=adwlk3.mod /id:61 +model=arban1.mod /id:62 +model=arban2.mod /id:63 +model=arban3.mod /id:64 +model=arban4.mod /id:65 +model=arban5.mod /id:66 +model=arban6.mod /id:67 +model=bwlk1.mod /id:68 +model=bdet4.mod /id:69 +model=hn1.mod /id:85 +model=pdsh.mod /id:86 +model=sl2.mod /id:87 +model=twr.mod /id:88 +model=plit.mod /id:89 +model=gnr.mod /id:90 +model=tnt.mod /id:91 +model=bnk.mod /id:92 +model=msl.mod /id:93 +model=crt.mod /id:94 +model=hut.mod /id:95 +model=ft1.mod /id:96 +model=ft2.mod /id:97 +model=wst.mod /id:98 +model=mslg.mod /id:99 +model=fp0.mod /id:100 +model=fp1.mod /id:101 +model=fp2.mod /id:102 +model=fp3.mod /id:103 +model=hc1.mod /id:104 +model=hc2.mod /id:105 +model=hwz.mod /id:106 +//model=jax1.mod /id:107 +//model=jax2.mod /id:108 +model=ab07.mod /id:109 +model=apc.mod /id:141 +model=armrmovr.mod /id:142 +model=bulldog.mod /id:143 +model=comtruck.mod /id:123 +model=coolant.mod /id:124 +model=dozer.mod /id:125 +model=harasser.mod /id:126 +model=hummer.mod /id:127 +model=lrmcarry.mod /id:128 +model=mechmovr.mod /id:129 +model=rommel.mod /id:130 +model=semi.mod /id:131 +model=semirig.mod /id:132 +model=srmcarry.mod /id:133 +model=striker.mod /id:134 +model=swiftwnd.mod /id:135 +model=bld03.mod /id:136 +model=bld04.mod /id:137 +model=bld20.mod /id:138 +model=bld24.mod /id:139 +model=bld26.mod /id:140 +model=tree.mod /id:144 +model=calp.mod /id:146 +model=calpb.mod /id:147 +model=dish.mod /id:148 +// +// Maps +// +map=arena1.map /id:70 +map=arena2.map /id:84 +//map=polar1.map /id:71 +//map=polar2.map +map=polar3.map /id:81 +map=polar4.map /id:82 +map=rav.map /id:120 +map=grass.map /id:121 +map=dbase.map /id:122 +//map=test.map /id:145 +zone=all.zne + +[zones] +zone=all.zne + diff --git a/CODE/BT/BTL4.PTH b/CODE/BT/BTL4.PTH new file mode 100644 index 0000000..42b15a3 --- /dev/null +++ b/CODE/BT/BTL4.PTH @@ -0,0 +1,26 @@ +!ifndef BC_ROOT +!error BC_ROOT macro is not defined +!endif + +!ifndef MUNGA_ROOT +!error MUNGA_ROOT macro is not defined +!endif + +!ifndef DPL_ROOT +!error DPL_ROOT macro is not defined +!endif + +!ifndef SOS_ROOT +!error SOS_ROOT macro is not defined +!endif + +!ifndef NETNUB_ROOT +!error NETNUB_ROOT macro is not defined +!endif + +!ifndef BT_ROOT +!error BT_ROOT macro is not defined +!endif + +INCLUDE_PATH = $(BTL4_ROOT);$(BT_ROOT);$(MUNGAL4_ROOT);$(DPL_ROOT);$(DPL_ROOT)\dvs;$(DPL_ROOT)\dpl;$(SOS_ROOT)\bc4;$(NETNUB_ROOT);$(MUNGA_ROOT);$(BC_ROOT)\include +LIBRARY_PATH = $(BTL4_ROOT)\$(BTYPE);$(BT_ROOT)\$(BTYPE);$(MUNGAL4_ROOT)\$(BTYPE);$(DPL_ROOT);$(MUNGA_ROOT)\$(BTYPE);$(BC_ROOT)\lib diff --git a/CODE/BT/BT_L4/BTL4.HPP b/CODE/BT/BT_L4/BTL4.HPP new file mode 100644 index 0000000..995946d --- /dev/null +++ b/CODE/BT/BT_L4/BTL4.HPP @@ -0,0 +1,12 @@ +#if !defined(BTL4_HPP) +# define BTL4_HPP + +# if !defined(BT_HPP) +# include +# endif + +# if !defined(MUNGAL4_HPP) +# include +# endif +#endif + diff --git a/CODE/BT/BT_L4/BTL4.MAK b/CODE/BT/BT_L4/BTL4.MAK new file mode 100644 index 0000000..b88358c --- /dev/null +++ b/CODE/BT/BT_L4/BTL4.MAK @@ -0,0 +1,153 @@ +.autodepend +.cacheautodepend +.suffixes: .cpp + +!ifndef BTYPE +!error BTYPE macro not supplied +!endif + +!ifndef BPATH +!error BPATH macro not supplied +!endif + +!include make.cfg +!include $(BPATH) + +TARGET_DIR = $(BTL4_ROOT)\$(BTYPE) +TARGET_PATH = $(TARGET_DIR)\\ +.path.obj = $(TARGET_DIR) +.path.lib = $(LIBRARY_PATH) + +LIB_PREFIX = -+$(TARGET_DIR)\\ + +CFG_FILE = $(TARGET_DIR)\$(BTYPE).cfg +HEADER_FILE = btl4$(BTYPE).csm + +#------------------------------------------------------------------------------ +# Library targets +# +all:\ + $(CFG_FILE) $(TARGET_DIR)\btl4$(BTYPE).exe $(TARGET_DIR)\btl4tool.exe\ + $(TARGET_DIR)\mechbld.exe + +clean: + del $(TARGET_DIR)\*.obj + del $(TARGET_DIR)\*.lib + del $(TARGET_DIR)\*.exe + del $(TARGET_DIR)\*.bak + del $(TARGET_DIR)\*.cfg + +assemble: + @echo No assembly targets + +#------------------------------------------------------------------------------ +# Implicit rules +# +!include $(BTYPE).mak + +!ifndef STARTUP_OBJ +!error STARTUP_OBJ macro is not defined +!endif + +!ifndef STARTUP_LIBS +!error STARTUP_LIBS macro is not defined +!endif + +{$(INCLUDE_PATH)}.cpp{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(INCLUDE_PATH)}.c{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(BTL4_ROOT)}.asm{$(TARGET_DIR)}.obj: + tasm32 -ml $(TASM_OPTIONS) -i$(BTL4_ROOT) $<,$@ >>error.log + +#------------------------------------------------------------------------------ +# Game +# +$(TARGET_DIR)\btl4$(BTYPE).exe: \ + $(BTL4_ROOT)\btl4.mak l4stub.lib stub.lib $(TARGET_DIR)\btl4.lib\ + bt.lib mungal4.lib munga.lib btl4.obj $(BTYPE).mak\ + $(DPL_ROOT)\libdpl.lib + tlink32 @&&| +$(LINK_OPTIONS) + +$(STARTUP_OBJ)+ +$(TARGET_DIR)\btl4.obj +$<,$* +l4stub.lib+ +stub.lib+ +munga.lib+ +mungal4.lib+ +$(DPL_ROOT)\libdpl.lib+ +bt.lib+ +$(TARGET_DIR)\btl4.lib+ +$(STARTUP_LIBS) +| >>error.log + +btl4.obj: $(CFG_FILE) + +#------------------------------------------------------------------------------ +# Tools +# +$(TARGET_DIR)\btl4tool.exe: \ + $(BTL4_ROOT)\btl4.mak l4stub.lib stub.lib $(TARGET_DIR)\btl4.lib\ + bt.lib mungal4.lib munga.lib btl4tool.obj $(BTYPE).mak\ + $(DPL_ROOT)\libdpl.lib + tlink32 @&&| +$(LINK_OPTIONS) + +$(STARTUP_OBJ)+ +$(TARGET_DIR)\btl4tool.obj +$<,$* +l4stub.lib+ +stub.lib+ +munga.lib+ +mungal4.lib+ +$(DPL_ROOT)\libdpl.lib+ +bt.lib+ +$(TARGET_DIR)\btl4.lib+ +$(STARTUP_LIBS) +| >>error.log + +btl4tool.obj: $(CFG_FILE) + +#------------------------------------------------------------------------------ +# Mech builder +# +$(TARGET_DIR)\mechbld.exe:\ + $(BTL4_ROOT)\btl4.mak mechbld.obj stub.lib munga.lib $(BTYPE).mak + tlink32 @&&| +$(LINK_OPTIONS) + +$(STARTUP_OBJ)+ +$(TARGET_DIR)\mechbld.obj +$<,$* +stub.lib+ +munga.lib+ +$(STARTUP_LIBS) +| >>error.log + +mechbld.obj: $(BCC_CONFIG) $(BTYPE).mak + +#------------------------------------------------------------------------------ +# Battletech library +# +BTL4_OBJS = \ + ?btl4mode.obj \ + ?btl4rdr.obj \ + ?btl4gaug.obj \ + ?btl4gau2.obj \ + ?btl4gau3.obj \ + ?btl4grnd.obj \ + ?btl4galm.obj \ + ?btl4vid.obj \ + ?btl4mppr.obj \ + ?btl4arnd.obj \ + ?btl4mssn.obj \ + ?btl4app.obj \ + ?btl4pb.obj + +$(BTL4_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\btl4.lib: $(BTL4_OBJS:?=) $(BTL4_ROOT)\btl4.mak + tlib $@ $(LIB_OPTIONS) @&&| +$(BTL4_OBJS:?=$(LIB_PREFIX)) +| >>error.log diff --git a/CODE/BT/BT_L4/BTL4APP.HPP b/CODE/BT/BT_L4/BTL4APP.HPP new file mode 100644 index 0000000..612ca6e --- /dev/null +++ b/CODE/BT/BT_L4/BTL4APP.HPP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: rp4lbe4.hh // +// Project: MUNGA Brick: Red Planet LBE Application // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTL4APP_HPP) +# define BTL4APP_HPP + +# if !defined(BTL4MPPR_HPP) +# include +# endif + + //########################################################################## + //###################### BTL4Application ########################## + //########################################################################## + + //########################################################################## + //###################### RP4L4Application ############################ + //########################################################################## + + class BTL4Application: + public L4Application + { + public: + BTL4Application( + ResourceFile *resource_file, + ClassID class_ID=L4ApplicationClassID, + SharedData &shared_data=DefaultData + ); + ~BTL4Application(); + + static Derivation ClassDerivations; + static SharedData DefaultData; + + private: + Registry* + MakeRegistry(); + + VideoRenderer* + MakeVideoRenderer(); + + AudioRenderer* + MakeAudioRenderer(); + + GaugeRenderer* + MakeGaugeRenderer(); + + ModeManager* + MakeModeManager(); + + ControlsManager* + MakeControlsManager(); + + Mission* + MakeMission( + NotationFile *notation_file, + ResourceFile *resources + ); + + Entity* + MakeViewpointEntity(Entity::MakeMessage *); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + + }; + +#endif diff --git a/CODE/BT/BT_L4/BTL4ARND.CPP b/CODE/BT/BT_L4/BTL4ARND.CPP new file mode 100644 index 0000000..ee24448 --- /dev/null +++ b/CODE/BT/BT_L4/BTL4ARND.CPP @@ -0,0 +1,185 @@ +//===========================================================================// +// File: btl4arnd.cc // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BTL4ARND_HPP) +# include +#endif + +#if !defined(JMOVER_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BTL4AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +BTL4AudioHead::BTL4AudioHead(): + earToWorld(LinearMatrix::Identity) +{ + useEyepointSegment = False; + eyepointSegment = NULL; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +BTL4AudioHead::~BTL4AudioHead() +{ + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + BTL4AudioHead::LinkToEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + // Call inherited method + // + AudioHead::LinkToEntity(entity); + + #if 0 + // + // Find segment containing eyepoint + // + JointedMover *jointed_mover; + + jointed_mover = Cast_Object(JointedMover*, entity); + eyepointSegment = jointed_mover->GetSegment("siteeyepoint"); + Check(eyepointSegment); + + CalculateEarToWorld(); + #else + useEyepointSegment = False; + if (entity->IsDerivedFrom(JointedMover::ClassDerivations)) + { + // + // Find segment containing eyepoint + // + JointedMover *jointed_mover; + + jointed_mover = Cast_Object(JointedMover*, entity); + if ((eyepointSegment = jointed_mover->GetSegment("siteeyepoint")) != NULL) + { + Check(eyepointSegment); + useEyepointSegment = True; + CalculateEarToWorld(); + } + } + #endif + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + BTL4AudioHead::CalculateEarToWorld() +{ + Check(this); + + if (useEyepointSegment) + { + Verify(GetHeadEntity()->IsDerivedFrom(JointedMover::ClassDerivations)); + JointedMover *jointed_mover = Cast_Object(JointedMover*, GetHeadEntity()); + // + // Get the ear transform + // + jointed_mover->GetSegmentToWorld(*eyepointSegment, &earToWorld); + } + else + { + earToWorld = AudioHead::GetEarToWorld(); + } + Check(&earToWorld); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + BTL4AudioHead::Execute() +{ + Check(this); + AudioHead::Execute(); + CalculateEarToWorld(); + + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +LinearMatrix + BTL4AudioHead::GetEarToWorld() +{ + Check(this); + Check_Fpu(); + return earToWorld; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BTL4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +BTL4AudioRenderer::BTL4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode +): + L4AudioRenderer( + render_rate, + mission_review_mode + ) +{ + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +BTL4AudioRenderer::~BTL4AudioRenderer() +{ + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +AudioHead* + BTL4AudioRenderer::MakeAudioHead() +{ + Check_Fpu(); + return new BTL4AudioHead; +} + diff --git a/CODE/BT/BT_L4/BTL4ARND.HPP b/CODE/BT/BT_L4/BTL4ARND.HPP new file mode 100644 index 0000000..4572685 --- /dev/null +++ b/CODE/BT/BT_L4/BTL4ARND.HPP @@ -0,0 +1,112 @@ +//===========================================================================// +// File: btl4arnd.hh // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTL4ARND_HPP) +# define BTL4ARND_HPP + +# if !defined(L4AUDRND_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BTL4AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Segment; + + class BTL4AudioHead: + public AudioHead + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + BTL4AudioHead(); + ~BTL4AudioHead(); + + // + //----------------------------------------------------------------------- + // LinkToEntity + //----------------------------------------------------------------------- + // + void + LinkToEntity(Entity *entity); + + // + //----------------------------------------------------------------------- + // GetEarToWorld + //----------------------------------------------------------------------- + // + LinearMatrix + GetEarToWorld(); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + void + Execute(); + + private: + // + //-------------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------------- + // + void + CalculateEarToWorld(); + + // + //-------------------------------------------------------------------------- + // Private Data + //-------------------------------------------------------------------------- + // + Logical + useEyepointSegment; + EntitySegment* + eyepointSegment; + LinearMatrix + earToWorld; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BTL4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class BTL4AudioRenderer: + public L4AudioRenderer + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + BTL4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode + ); + ~BTL4AudioRenderer(); + + private: + // + //----------------------------------------------------------------------- + // MakeAudioHead + //----------------------------------------------------------------------- + // + AudioHead* + MakeAudioHead(); + }; + +#endif + diff --git a/CODE/BT/BT_L4/BTL4GALM.HPP b/CODE/BT/BT_L4/BTL4GALM.HPP new file mode 100644 index 0000000..8e8a5ed --- /dev/null +++ b/CODE/BT/BT_L4/BTL4GALM.HPP @@ -0,0 +1,44 @@ +//===========================================================================// +// File: gaugalrm.hpp // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/22/96 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTL4GALM_HPP) +# define BTL4GALM_HPP + +# if !defined(GAUGALRM_HPP) +# include "gaugalrm.hpp" +# endif + + //####################################################################### + // BTL4GaugeAlarmManager + //####################################################################### + class BTL4GaugeAlarmManager : + public GaugeAlarmManager + { + public: + Logical + CreateGaugeAlarmStreamItem( + MemoryStream *mem_stream, + const char *alarm_name, + const char *alarm_data + ); + void + ReadGaugeAlarmStreamItem( + GaugeAlarm *alarm, + Entity *the_entity, + Subsystem *the_subsystem, + Enumeration the_condition, + MemoryStream *mem_stream + ); + }; + +#endif diff --git a/CODE/BT/BT_L4/BTL4GRND.HPP b/CODE/BT/BT_L4/BTL4GRND.HPP new file mode 100644 index 0000000..4e0149a --- /dev/null +++ b/CODE/BT/BT_L4/BTL4GRND.HPP @@ -0,0 +1,48 @@ +//===========================================================================// +// File: rpl4grnd.hh // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/13/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTL4GRND_HPP) +# define BTL4GRND_HPP + +# if !defined(L4GREND_HPP) +# include +# endif + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ BTL4GaugeRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class BTL4GaugeRenderer: + public L4GaugeRenderer + { + public: + + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + BTL4GaugeRenderer(); + ~BTL4GaugeRenderer(); + + Logical + TestInstance() const; + + void + NotifyOfNewInterestingEntity(Entity *entity); + void + NotifyOfBecomingUninterestingEntity(Entity *entity); + }; + + +#endif + diff --git a/CODE/BT/BT_L4/BTL4MODE.CPP b/CODE/BT/BT_L4/BTL4MODE.CPP new file mode 100644 index 0000000..5eef7e0 --- /dev/null +++ b/CODE/BT/BT_L4/BTL4MODE.CPP @@ -0,0 +1,104 @@ +//==========================================================================// +// File: BTMODE.CPP // +// Project: MUNGA Brick: Controls Manager // +// Contents: Interface specification for BT LBE4 Controls // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 02/13/96 CPB Built from CONTROLS.CPP // +//--------------------------------------------------------------------------// +// Copyright (C) 1994-1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include +#pragma hdrstop + +#if !defined(BTL4MODE_HPP) +# include +#endif + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +struct ModeLookup +{ + const char *name; + ModeMask modeMask; +}; + +static ModeLookup + mode_lookup[] = + { + {"ModeMFD1Quad", BTL4ModeManager::ModeMFD1Quad}, + {"ModeMFD1Eng1", BTL4ModeManager::ModeMFD1Eng1}, + {"ModeMFD1Eng2", BTL4ModeManager::ModeMFD1Eng2}, + {"ModeMFD1Eng3", BTL4ModeManager::ModeMFD1Eng3}, + {"ModeMFD1Eng4", BTL4ModeManager::ModeMFD1Eng4}, + {"ModeMFD2Quad", BTL4ModeManager::ModeMFD2Quad}, + {"ModeMFD2Eng1", BTL4ModeManager::ModeMFD2Eng1}, + {"ModeMFD2Eng2", BTL4ModeManager::ModeMFD2Eng2}, + {"ModeMFD2Eng3", BTL4ModeManager::ModeMFD2Eng3}, + {"ModeMFD2Eng4", BTL4ModeManager::ModeMFD2Eng4}, + {"ModeMFD3Quad", BTL4ModeManager::ModeMFD3Quad}, + {"ModeMFD3Eng1", BTL4ModeManager::ModeMFD3Eng1}, + {"ModeMFD3Eng2", BTL4ModeManager::ModeMFD3Eng2}, + {"ModeMFD3Eng3", BTL4ModeManager::ModeMFD3Eng3}, + {"ModeMFD3Eng4", BTL4ModeManager::ModeMFD3Eng4}, + {"ModeMapping", BTL4ModeManager::ModeMapping}, + {"ModeNonMapping", BTL4ModeManager::ModeNonMapping}, + {"ModeIntercom", BTL4ModeManager::ModeIntercom}, + {"ModeSecondaryDamage", BTL4ModeManager::ModeSecondaryDamage}, + {"ModeSecondaryCritical", BTL4ModeManager::ModeSecondaryCritical}, + {"ModeSecondaryHeat", BTL4ModeManager::ModeSecondaryHeat}, + {"ModeEject", BTL4ModeManager::ModeEject}, + {"ModePlasmaDisplay", BTL4ModeManager::ModePlasmaDisplay}, + + {"ModeInitial", BTL4ModeManager::ModeInitial}, + {"ModeNonConfig", BTL4ModeManager::ModeNonConfig}, + {"ModeMFD1NonQuad", BTL4ModeManager::ModeMFD1NonQuad}, + {"ModeMFD1All", BTL4ModeManager::ModeMFD1All}, + {"ModeMFD2NonQuad", BTL4ModeManager::ModeMFD2NonQuad}, + {"ModeMFD2All", BTL4ModeManager::ModeMFD2All}, + {"ModeMFD3NonQuad", BTL4ModeManager::ModeMFD3NonQuad}, + {"ModeMFD3All", BTL4ModeManager::ModeMFD3All}, + {"ModeSecondaryAll", BTL4ModeManager::ModeSecondaryAll}, + { NULL, (ModeMask)0} + }; + +Logical + BTL4ModeManager::ModeStringLookup( + const char *name, + ModeMask *returned_value + ) +{ + Check(this); + Check_Pointer(name); + Check_Pointer(returned_value); + //---------------------------------------- + // Search table for match + //---------------------------------------- + ModeLookup + *lookup; + + for(lookup=mode_lookup; lookup->name!=NULL; ++lookup) + { + if (stricmp(name, lookup->name) == 0) + { + *returned_value = lookup->modeMask; + Check_Fpu(); + return True; + } + } + //---------------------------------------- + // Not found here, check next level down. + //---------------------------------------- + Check_Fpu(); + return ModeManager::ModeStringLookup(name, returned_value); +} + + diff --git a/CODE/BT/BT_L4/BTL4MODE.HPP b/CODE/BT/BT_L4/BTL4MODE.HPP new file mode 100644 index 0000000..065f488 --- /dev/null +++ b/CODE/BT/BT_L4/BTL4MODE.HPP @@ -0,0 +1,152 @@ +//===========================================================================// +// File: btl4mode.hpp // +// Project: Battletech // +// Contents: BTL4 controls // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/13/96 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTL4MODE_HPP) +# define BTL4MODE_HPP + +# if !defined(MODE_HPP) +# include +# endif + + + //######################################################################### + //########################## BTL4ControlsManager ########################## + //######################################################################### + class BTL4ModeManager: + public ModeManager + { + public: + enum + { + }; + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- + public: + BTL4ModeManager(ModeMask initial_mask): + ModeManager(initial_mask) + {} + + //------------------------------------------------------------------- + // Mode control + //------------------------------------------------------------------- + enum + { + ModeMFD1QuadBit = ModeManager::nextModeBit, + ModeMFD1Eng1Bit, + ModeMFD1Eng2Bit, + ModeMFD1Eng3Bit, + ModeMFD1Eng4Bit, + + ModeMFD2QuadBit, + ModeMFD2Eng1Bit, + ModeMFD2Eng2Bit, + ModeMFD2Eng3Bit, + ModeMFD2Eng4Bit, + + ModeMFD3QuadBit, + ModeMFD3Eng1Bit, + ModeMFD3Eng2Bit, + ModeMFD3Eng3Bit, + ModeMFD3Eng4Bit, + + ModeMappingBit, + ModeNonMappingBit, + + ModeIntercomBit, + + ModeSecondaryDamageBit, + ModeSecondaryCriticalBit, + ModeSecondaryHeatBit, + + ModeEjectBit, + + ModePlasmaDisplayBit, + }; + enum + { + // These 5 mutually exclusive + ModeMFD1Quad = 1L< +# endif + + //########################################################################## + //########################### BTL4Mission ############################ + //########################################################################## + + class BTL4Mission: + public BTMission + { + + public: + + BTL4Mission( + NotationFile *notation_file, + ResourceFile *resources + ); + ~BTL4Mission(); + + Logical + TestInstance() const; + + void + SetPlayerData(NotationFile *notation_file); + }; + +#endif diff --git a/CODE/BT/BT_L4/BTL4PB.HPP b/CODE/BT/BT_L4/BTL4PB.HPP new file mode 100644 index 0000000..8506b1a --- /dev/null +++ b/CODE/BT/BT_L4/BTL4PB.HPP @@ -0,0 +1,116 @@ +//===========================================================================// +// File: rp4lbe4.hh // +// Project: MUNGA Brick: Red Planet LBE Application // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTL4PB_HPP) +# define BTL4PB_HPP + +# if !defined(BTL4APP_HPP) +# include +# endif + +# if !defined(L4SPLR_HPP) +# include +# endif + + //########################################################################## + //####################### RPSpoolerTask ############################## + //########################################################################## + + class BTSpoolerTask: + public SpoolerTask + { + public: + BTSpoolerTask(); + ~BTSpoolerTask(); + + void + DispatchPacket(NetworkPacket *packet); + long + GetTimeBias(); + }; + + //########################################################################## + //#################### RPPlaybackApplication ########################## + //########################################################################## + + class BTL4PlaybackApplication: + public BTL4Application + { + public: + BTL4PlaybackApplication( + ResourceFile *resource, + SpoolFile *spool_file = NULL + ); + ~BTL4PlaybackApplication(); + + Logical + TestInstance() const; + + void + SetSpoolFile(SpoolFile *spool_file) + {spoolFile = spool_file;} + + MissionReviewApplicationManager* + GetApplicationManager() + { + return + (MissionReviewApplicationManager*) + Application::GetApplicationManager(); + } + + long + GetTimeBias() + {return timeBias;} + + void + DispatchPacket(NetworkPacket *packet); + + protected: + NetworkManager* + MakeNetworkManager(); + + long + timeBias; + + void + Initialize(); + void + LoadBackgroundTasks(); + Logical + ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ); + void + ExecuteBackgroundTask(); + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + }; + +#endif diff --git a/CODE/BT/BT_L4/BTL4RDR.HPP b/CODE/BT/BT_L4/BTL4RDR.HPP new file mode 100644 index 0000000..4e45a14 --- /dev/null +++ b/CODE/BT/BT_L4/BTL4RDR.HPP @@ -0,0 +1,238 @@ +//===========================================================================// +// File: btl4gaug.hh // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/13/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BTL4RDR_HPP) +# define BTL4RDR_HPP + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(L4GREND_HPP) +# include +# endif + +# if !defined(L4GAUGE_HPP) +# include +# endif + +# if !defined(ROTATION_HPP) +# include +# endif + +# if !defined(RANDOM_HPP) +# include +# endif + +# if !defined(POINT3D_HPP) +# include "point3d.hpp" +# endif + +# if !defined(HEAT_HPP) +# include +# endif + +# if !defined(POWERSUB_HPP) +# include +# endif + + struct ShadowRecord + { + int distance; + }; + + class MapDisplay; + + class MapName SIGNATURED // Used exclusively by MapDisplay + { + friend class MapDisplay; + + MapName() + {} + ~MapName() + {} + + Logical + TestInstance() const + { + return True; + } + + protected: + void + ExtractFromEntity( + Entity *entity, + AffineMatrix &worldToView, + Entity *exclude_entity=NULL, + Entity *hotbox_entity=NULL + ); + void + Draw( + GraphicsView *graphics_view, + int hotbox_color + ); + + Point3D + center; + Vector3D + direction; + BitMap + *nameBitmap; + int + color; + Logical + hotBoxed; + }; + + class MapDisplay : + public GraphicGauge + { + public: + enum OffsetPosition + { + center, + bottom + }; + + static MethodDescription + methodDescription; + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer *gauge_renderer + ); + + MapDisplay( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int left, int bottom, + int right, int top, + OffsetPosition offset_position, + int view_width_in_degrees, + int bg_color, + int static_color, + int hotbox_color, + Scalar maximum_range, + Entity *entity, + Scalar *scale_value_pointer, + Point3D **position_pointer, + Quaternion **angle_pointer, + Scalar *capabilities_ratio, + Logical allow_rock_and_roll=False + ); + + ~MapDisplay(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + Execute(); + + protected: + void + CalculateBounds(); + void + EraseDisplay(); + void + DrawDisplay(); + void + BuildRadarShadow(AffineMatrix &worldToView); + void + DrawViewWedge(); + void + DrawStatic(AffineMatrix &worldToView); + void + DrawMoving(AffineMatrix &worldToView); + void + DrawNames(AffineMatrix &worldToView); + + enum + { + maximumNames = 16 + }; + + MapName + nameArray[maximumNames]; + + OffsetPosition + offsetPosition; + Scalar + currentScale; + Point3D * + currentPositionPointer; + Quaternion * + currentAngularPointer; + Scalar + currentCapabilitiesRatio; + Scalar + LODIndex, + pixelsPerMeter, + metersPerPixel, + maximumRange, + maximumDistanceSquared, + xMin, + yMin, + zMin, + xMax, + yMax, + zMax; + + Point3D + viewingPosition; + Radian + viewHorizontalRotation; + Radian + viewHalfHorizontalWidth; + + AffineMatrix + worldToView; + + int + operatingPhase, + backgroundColor, + staticColor, + boxColor, + halfWidth, + halfHeight; + + Logical + operating, + rockAndRoll, + flashState; + + GaugeEntityList + staticEntityList, + movingEntityList; + + GraphicsViewRecord + previousDrawing; + + int + halfViewWidthInUnits; + + ShadowRecord + *shadowTable; + }; + +#endif + diff --git a/CODE/BT/BT_L4/BTL4VER.HPP b/CODE/BT/BT_L4/BTL4VER.HPP new file mode 100644 index 0000000..b82099d --- /dev/null +++ b/CODE/BT/BT_L4/BTL4VER.HPP @@ -0,0 +1,9 @@ +#if !defined(BTL4VER_HPP) +# define BTL4VER_HPP + +# define MAJOR_DATA_VERSION 1 +# define RELEASE_VERSION 0 +# define MINOR_DATA_VERSION 6 + +#endif + diff --git a/CODE/BT/BT_L4/MSSCCPRJ.SCC b/CODE/BT/BT_L4/MSSCCPRJ.SCC new file mode 100644 index 0000000..165038c --- /dev/null +++ b/CODE/BT/BT_L4/MSSCCPRJ.SCC @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[BTL4.MAK] +SCC_Aux_Path = "\\AVATAR\Mungass\VSS" +SCC_Project_Name = "$/Tesla_BT/BT_L4", ZOCAAAAA diff --git a/CODE/BT/BT_L4/VSSVER.SCC b/CODE/BT/BT_L4/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..cc895dd9f8f8de13c92821544495032d819a921a GIT binary patch literal 544 zcmXxhO(?^07zgmbVVaoiLb*5?jTp<`z0S+#Wo#@_%0JD&rp1YrR$^tf3y0m*TCxLa zhaDCv2OMO7c9@qPc2OKes6|eEf9iQ|pXb-}((`LoR7EZ6Ic5a zqLlj&Z4t+*3{Hn|ms95>qk|tW7iO4I$?4(ruQw_L&zhJGaA^I*#Vmo1@TUI4Nbe^2 z+8juc&G6Oh%`~|U_Ehjzayy)C@Gp`(;C)$mg_-s5gpC%BD4Zx-*!(W|d2*wa+zls6 zvO8o8EN*Ajfouif@qz z;DF&RMIM9;LdS>XA^23M3X+FmZ`c ..\result.txt +..\mechbld avatar.mch >> ..\result.txt +@echo Building ava1... > ..\result.txt +..\mechbld ava1.mch >> ..\result.txt +@echo Building blkhawk... >> ..\result.txt +..\mechbld blkhawk.mch >> ..\result.txt +@echo Building bhk1... >> ..\result.txt +..\mechbld bhk1.mch >> ..\result.txt +@echo Building loki... >> ..\result.txt +..\mechbld loki.mch >> ..\result.txt +@echo Building Lok1... >> ..\result.txt +..\mechbld lok1.mch >> ..\result.txt +@echo Building madcat... >> ..\result.txt +..\mechbld madcat.mch >> ..\result.txt +@echo Building mad1... >> ..\result.txt +..\mechbld mad1.mch >> ..\result.txt +@echo Building owens... >> ..\result.txt +..\mechbld owens.mch >> ..\result.txt +@echo Building sunder... >> ..\result.txt +..\mechbld sunder.mch >> ..\result.txt +@echo Building thor... >> ..\result.txt +..\mechbld thor.mch >> ..\result.txt +@echo Building thr1... >> ..\result.txt +..\mechbld thr1.mch >> ..\result.txt +@echo Building vulture... >> ..\result.txt +..\mechbld vulture.mch >> ..\result.txt +@echo Building vul1... >> ..\result.txt +..\mechbld vul1.mch >> ..\result.txt +cd .. +btl4tool -b btl4.bld >> result.txt +call arcbt f . >> result.txt diff --git a/CODE/BT/C0X32.OBJ b/CODE/BT/C0X32.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..2e99f32b452b5a2e41b6478e37a42d798bfa3381 GIT binary patch literal 1152 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"A2{jAOV>Yt?|Aw&P3C5Q;lz_ulrp#*zN{g88} zHURX%fj~>#_W~L#y?UfQdg47|sUo`NuRhbo6IDKG__|qw55Ha(K<;ELv8t@nvaO>F9JY9~T)?gfOO> zLQ}G_9M?n|x%erMTjF`7QaY5#b4Ve*R|;O$292DVKE&g%$3gafe$L{Nth?6Ws~q}i za2eOh_)DO!7RJ-KC9#jFK`EfDYUu253fl4yVfR2A)6jW=1+)D{{5PUEp`Ic+7@#3| zu9n@0RQ0B%^C%ocgSO5WXq!@nn7jo)opJ#}^&vW}`lb;93W`HEX zfVV91TS+W$C7W)-Y0=FQq^GC{d-iu=w#W9P%y^+3}vtj zo}jj3l;@L&g5XPu{|0L|a@gLwKt}YDJ(M<8=pZ%D*Azg<=_%JG`4x!#u&Y}lgu83? zZ3l372w$V;dh*KeT$c(nT=T4WUu-P1fo>VYAi1PD}cLmi`TkuUcQa?)@{KS9~ zQjZ{EeK;Oxq&XO5oE#@51RKqbA=qvc=|cH1S+6XFn-Susw5y9CXZeO0->@b6_je#W zDrPhuCE4GFE?MxGlbv|?TU{TEX^1zHb#H^)#MbM z0oRknn^{j*e?!teUXy#?ro{ti#9wmbFW&gei1^D$dJ%=ei`^KxdX*-vZ)uEj7=;j( zQ-ou({+NabO)Ka(SNwX#?+Ecb@}Fe%%Kko7{7+_Nkny%l3tqM#(@q7S?-J88qp@?z zRKteW8A~ryCA>`#Z+5(ag1%`f8m_Cw%xElKT8mITV3jX|WO2z?B(!qI+@MQoSUHX6 zY&}E#WXuQ2CR*pN>fVm6KRQE6mNKIeH(d($wQjk)or1OPM zJZ&>Roc_aUb<_E@^%K>KvG_{i8+X^*s+)5#p|;T}uvdO}H@~%;d*6vZwU6g@^WuZi zRr~nxZeF@KTDOm1-OYEqqYv-Xu3oY<;1M4Vq)W$_RIczWtX{Ba$#Ty(D+92~yJ`mC z^#)cLaqGHCGx(e2uKpo<@od>`YotT(5VZM6tJdO{r0p*a#^h%Utu4CF{3<9ZleAB& z>c_fWt|wo_O_%wHs@6_+o7Wzs3xiBumyPtT~r(d_L_-v0F zF_t@C^|_mESo5qIZKHzOaptai08KRgC11IEYS&vNsBtpQj}@gCiwPMw;~?ht)3_ab z&F8jt5CYhzk6$7czZA>pjUJ`iJQ{>HrsWnPeZ{o$E$DzUwLu7`5ym2fuLx*DKzgSU zAM=2oyT#m%6}gJqpU)%-dT&bfmIHCheVy{*Rcqa2~!G8p6dSUx-gR;KCEAUc^m5Jy#wJl{;j>6m$GOGX450e9jb# zw|mG={5N~GOppEz}S>6xHg zehXIW@cjcTbg}1$tvwa-D?Wf_V5z8V{yEsCK@AjG!9VEshMvID2ic1c!f8oFmVe~q z_E;=uaq%{N2~K^VFin%h%`S`-V=oh(PZWB?_dqu{4@;)fYBr5eg>V#y1EE}|!(JL% z-zt~!A7Ms`isJ6T(hM;IxwU-oQViR4IH*O9h0C!515pg94xHXtPy)#O3DiQO5ScEP zVfaoSsDlgcMRS2mcz(BFOG*IAB{A)Gzlb=QBI{{<8=NS&E#>L40uH(hL{1N zk9qs4xHspS0izX2zuNJJ~F#j|CKGT1fR&Gc93s>Z+N!ccHH8% z%$A^t-0~X~MLmpS_^a7n5bp+sQYmRYYuu)WIA-jLKq3V);|w+(_i|a@!;H<(=e&tn zT9C$TV!cuC5@HU8x2b!f5ZgqV^d<%D)Teq)v!VOev;7s8vZ7&zC$jZki*S+RJQ`eWxjq zR^Mq3B-eLJ0bxs;X6oKskDf5FzMI0jF*ww}W5NgZU}yR{LrBp4+xQJ~t=^_HPJG@b zXopT8CX3qjuYwotIIBdP)gD}F1&73FzqJm?N-Yz8THXupz}+|&pb zs9xL$4Y$gVWT)Z4z8l24rj13HV3cLPYb}Lx$Q&>VLfkWtxPxP+X%B^L+>I| zqi^q)iZfA_`1Y=z8Yv^;8t`M8JNi+q z$|~2JKQw{KP?~vXFvg*U8YH+YtLnoHPjmcWK)fy`3U2i5@R2A_jgxt~h5y_s9Q3K4 zH<&U_X-0m~O2%SP!z+^t-KVWk*4s!ATjkoEBCXS}*g;qHR#tU4 z;1WyLvBQqbyW*vR?IvCY-Ua$R3ze951KN(+se=TD(FNh^c`z@MGSQ)Ae6$Lt#tdyp z7eTy+>$|BpyWY(BUM6WYcH=mPFl64S%)gXs=or*+sDW`Tu&VlB+uz9HHM&rh(j5`);7o*5UIu_c=a3L=agO=1Xx*;|H_WgyDeaJ>89 zVIbbHm;4dK5JS-~n0BkW7uR!W8V6(iq<<3Ij)q%5J_D2`v;pqCQ;Q7;U^7%nQ6YxTb{9C6a_)F!}b58#IL*u_MF zw91~+NFX5)v#4Of{)86VOO-W>t`!yu3i^2^3_8TY30UZx=^RN}`KullxGGV=5WWb9 znkOPBfx3_Z|>A3A&p!;bO6RzTR?Du z1w4|PhI0`+JQ&k(T-ZbJ6ZH29OdF=Cdm(mdAQEK87oV8sL_?VAtABJR3@2x(ONz)i zhV|8Q7^To<89IUMNoG=aCtCH4NY}Oc6MEW%`H(<01NiHp8;N4q>H}CWf*)~<3~vMx zom3?~G5yjOT!xE?j^Ist#1%aee?X&;9&z^NB5L16yp-TALgYnBR2K6yIHXT95DUIM zBcZ^o&`0LvHr#=U#Qgju87yhz5!Kl@>gGh$v!qFC(&1b0fv_?gX*;m+*^tB(Tredv z6rw|9i0dtsm=hW9OJo?ACUN%DPfAZ$EHqX_#Nnv)sC~*rMSWNC$4bf84YPqHaUupg zHrS@cQIowmp(La!Vu0SUQke*V!Rsuptk-EKEKZEuG^)GjRsVP%UxO)M3X!hoE{#4& zKb{9X{=g+j5f~_7ornwISz5&9!8BaUi1Sxmin>;Rfw|maCF~v!NiAkf@rheAwj_jD zcRl$ld^-%2L3`jP8i40uC?>f$jyYYc*Wdxs@@+gMk}%_NrOoOFJRmy%#G+Oc*uCvM zag1o@>d6=c1b0T;3#QT7zFgC&Al0d&_Gr~vqgm2Tsjo}Qm zx!jm#6f%9YmRnM(RMu85Sy<@_EcGl9-!Jrhb7|1?;L;`61UySuED=Y^>+a_ZUqlsf z3xU>e`jS9p?Gl{qo>E)8v{r<_dOx2;;o8kb_yD3uSrA+t@T^!AsP+VxR6e>47w6(= z_5%w5ivr7WbXw0R@pZ&q_j8MgpQ~leT)M>2N&?~6CyU&L;&#H z41Dr8^Yw9j{aEz(7Vt{KkN*BOB0SArOSd^NUvaO^z%)~C%+S(&i)xn#biM2tJ=V4b z{054J*{EwZE*nE1P61>NxR)wxZ1^D6q1$uvCz2-GLjZL zu+Vu38wz4d*o=io*tZwDeylrBrYH@&m@#=a?h|@?Jmx4pbLf}#{VH+QTmDh~wl})w z?Q&PVb>f_KH@;15T=CZPfeKvlwhs+>nJeBxmI^etfO$7j>bv@iRve4n zD@Z3M;2r-@Y1aZCRdub;JQG4P8A2FB2$M{R0R(fAD1D$1KnGC>2`Q5RGWxakOiZn} zH!tnuropl5$-$tttxxXNf_;FsQuH#Q%D*nVCTF zyWe-k%z5pz&szJj_S);Y6`KWHh83(Mi7YduR4vowJ(_TtrqQxKUt}Vj85m%2Syken z5SOD~EYYg#5n2zFyrtY$OJsVmn0uH)%jhxg?xy7mE9VI;5ooFZ6W*^}9q)HBI==>Q zKjHoOWH8vgc~M)?AH11K>Hq?Wma5t(U@Vt^iGU{dK77a;ZUF=70578^Oeg*S3LiAb1ni%nMF6;z9B<@TGw=3x;m1sDK_94pwnP8?&eMa9GtB*MW z9ME~q%Ez`Rm|25hl>%bSA&T4{5EzW8A4*@ ztl}2>1x<8f9puI5~0eiOLaSj+*Nqy&*R9dvU`2{aW#BDu{S{y3~uBh)0AT(FpyP zcPkGFiZOAgHh4PLbY3**GtbwGYV$MZG8^R2)b#(%&RS8z1)Q#^gEX}H_QV?RrOM+Zg+cfe2cGFG}H^k_OaJtm=#z~#4}k3l$srgCLLWJIzR-jPrvo{3r-XPt>!n`WGe+M901M-syc z7fExvu>jZMBHqP+OoJXXtcQA&gf3MCNT~O>D@=@{(P&`y{O>H7KBu5+K}E&9`QMS| zR$X_?yei2HQ_7nk@ie8d09pI#&265h=6>Px5{g5$Pu|p7hpa;skC4NI!W8s(=Bs4` z=^E*k_v5cnE;4>4yVGBU*t4B}+V*1m0NJ%BQQSg~9+-v)H__DfpztZp=Da8IAv@Zv&%?cR8f1+(4)7kC28wR&bWEJuD*Q9ZXfS-+RIEu*2)4W zLbpK-%*tM5MSx9Jfm6(d2?53CXev^?xlYBE18&9ZRHo)Z?}_L5$srBsMKK79z;w{` z3SF!3X`KqBU{yep)|I11kiH+5Neqgfw43ya1}Ij5A|-*c7wKd7Ir@RJ*CDn+nP-C1 zjcg2E4rTIg}?<(GT*;e@qUQ+_v8JK@cu!1b-x2S z$PPY-fy{+*ahxuqh;fY07%GM!Nr6P$UnGFU0gW52fQ&<>NmY6PR4Ggo%F+aRW=EJ8 z5IG!m_kJobURZ;Lj>&2@aj85D-=PpIHY~MUkEZF2!R9=SOlA$r$j{>LV?^Sylzk5k zXrXWqpZai)zuEd{+(IiwGRm|I)a^zi1YofQ?)s(cXj`0JMvkR>Z$tKQoWTzU z|Mv+$x^rg)URixte&=w40sx8dt2+6BKo)>fvc{RpO%c^sZ5^Da-5%ji2+&`>OG0^jds1_ zKParx13lM6*bmnIdn@PqkVIZ_-Qk0#zVtxE;^0T{(7sKXT8w;dE#A{_UG4Zd+OZcCo!>QwD#M&Vd6(I zkw02{rmj@TF>!aX*1pacv0Hntr|*&eM{!~4qtvHbs^UUYN1UzmE!!b){1Ro zJoH8lH1twSw{$vR_8Cxvw0lxyfCw8U1c_J5KUD&~rhyVdAtxZOM~DV8LsH8>RRg`c zfs*aKW;v&4J4+=l?E*Sosu3^8utr3ri7-UI$x-i*SZl;DW0Q_xxro?m5C=>=9IKy5 ziI1mC;>WRi&zlE);b<-^J1`r&cdowlk7OGn2y$ zjbzx|SwvhI4Gbrg%Md=9eDwNbbL-)jd)ROuok=5s9V=WqS9*kd(cxn!2{#ovM6H(-DS`9D;N4i z-d9-d%fvrM;_xj|a1n<|;#oS37vG~pk+_yP)}|Ek7rGoK#$Lj~B|aRDLyD-QD=8&k z5B9zjP5V0hM0;{uFO6s%(t4?&G5z(db3M8BtP-`MIbiY?J$5(zBkPL5<9XmjAYL5> z83;V~ylQ!o4ErNc2=U+rBnL$sy6HZU7oiJEc_BQ%vZ7tz#><7mo(D>%_;=|BhbNVm z-etjV*l%{gn~hEDz?6PuPBl@7nBznuo3bgbXa^$r*%5RQ`C%k@rRB$(cZp$C-;U_g z7AzD9u>E4LMs_U7`Kkw&^N2^V1w+jULd_M~U=C+Uq7Xoatoh;}y96I3{bQIJn9E}I z`Gyq6MzbQ|FWCc9F4?WLr@Oqih!a!aDIPpuUwU?1CX()|+thbB>oE9ixc;OMjxL6O zh)41FUiQ^TM<96uHJNsn8`djc#Ru#RBi9N|*ZKNMTfFq%*we? zu{uf#TFFuoX3;q0DM2p|ZVYl9a+F{$4hWo|wgfaZ8M0v`_Uyg6>l5JWSuY9P|PEwXSG>3?B4=vejU7`a-eHlCii#&tAg% zqy*k---b;d>#+odXtuE|ZI$cyRh*|kA8i2SUNkMrx&bg+DRGGX^{Cy~K zPCIFZc=-w@tm*Ee_@ zMc~($0zjkZ^6B({Bv~Vb)Gl5paJ!G}^Qj$Y_Fo7lWdB)d7Ui(6K5f`t4Sw;2|u!l-{k-5@G zoFHq7W!_^}pJUV;{nCUHvLw)7xb~Bn)VT!a5xg*GiS}0sHP|isZ z`%OdmJ!43x$gvXauk7?&OWynUN)Ni$7WDu3BgfB%n|D^ZR=HmAzUG~fPiL!KRr&Pf z;K=_P*)x*PR^e^^$tqW?W0#Z8$0yaNaj6uP`f0{94tgWSdAiX2x3*wS&ax4w3)dE$ zF0Ay>)6Cq7*>d*&Vbe3(@y_W?lY#<302J+7W!hIzhl=gHitW3QPBb{du^)W{xnr-`(Tm5fIDAtY;X9b*cn zf-LCjUR%I<`xJb#ex&;0(r7E3StzoI^>F%p(Mu=P9E01PbA4M6+0=8WhwFg5Q^kC9 zFSs`%Im9Ojd9_y!?7NI1B^8O|&Ayny-g2(xD_>r99OMC_DkysqzQh0$)x%SZt%mI4 zHey%-3v@z-(42A{LHXXBsKai;1vy2B>5W+wTDXhjdyleEV>1NKae)S?=5MsEN zQ!p>8z2|ei_B+&aWJ^gU@KZ{6U{|PFxO4wxJRcw4W(mI|jSHlXC{MEl(ub70jL)h@ zi9t5+LSK2)s`%H_uvrxkKv92YF$)q9H30k7RO#pw(v;wtW=5`2|AgTc5=dDrJNa3aU^19V+>>By1=|NS}BRcjL%VG&wB=AHYy$ zY&?vOo3SBOKGqB@3_3+db6J#P9GDNHwMeJ*SlP40RPttO1lO$Jq@}KO%cK56glZAC zDNamBV_hhN6TG;C6y5L!V!t2b!I)yT30(Qj5vxPoqZwOb0;9&fpdr)yIY)PbBbYwl zsp`z|vykeO0pck#Ks4&jd^ikV!HHptwXM-ILqR0eZBSj^*qk?h>yu}S7y2-XZ2Kb_ zk~nj$zJ@FRmo|KSSK<*qe&85CIE$HyiWxvyK46Z5l8Q~o>I=BZotV{j@fNU34^;EH z3+E6tv2+Y>UpkfQ2X(`29p-5Xm@Q2=Uh$1Z@o&&4`cOD6P_4hY8W;V(Vf0fm^%IXF zFd~JJH9;;)ZICX$^HrkTioqb6iZlxJT_|40Q0Ib!#qkSfPwGqqLQ&D$)#*81NPqfD zrvH9-_;sGr18w`UV3m5zUS=oZr*HJ|28y<>)8QZhmb?$Hp!)6=+lWIfz7X(4Q2YmZ z+j_*{XLgB~2N5!0ir^n4NQ43Qs!QML^oa#j8SRzhJ5?62K*oy>U@i;WHc+kB^S3r; zw4T4Gk=(Or1w@D$u^wTR4M_03X)skz&gUV;nGBCoe#8W{`A{4zmkHKTfE7M}kN$c{ zbrpvciXSF6QtbnPcAp8Fu|+KowWUltqV5M%ULlI;C3Wv(qpFSMSftNG3TgOWkhtKi z@s6DNKXWYMtu|_g`J#eeVwMW)N~Osa$DJ%80e}SOBsXq?O)Mu?)qe~LC}~JSn}m14 zD^$Yb-tWXt;$&?sCVo8#HOor*8T6OZLRl>!)&w0R;e}d$k{l4Gl%Ij6mRb&1s}l@! zB}QkhG)>$OJP`|sH^Ek|gofQ{c^opyS^O6;`AA!Rk}D(a3M3&EDruGW2N-cdY)K9H zWBNF$WRMVog-6`ApwraX$OVTUHikLD>qS%&;;OT*z~lsBvXe~WfeB(z0+Zt=Cd-27 zSc;=!yQG$%05+!?o71p0ATpNK9;9|}InFy9wX2C6$J-pNoyg*w}y5j=K zX=1&8r^{B}T`BG~z>7!$Y##LKbJCneExp)_LoR0V@Ak%JXtZPGMt-}QTD-gqqai=O zsd>>s+wBn5YD&gnldaG7d(4J{v_*%MBz18}^9@MDThl8A+((Tm|2};rF2bWPlkm<2 zF>nY8U8F_ajtNqf>oD5UQzv<0$G08uq%uiTPf`u)e$WCMx|`@T#@yF|tOJnbPR!FZ zX^JK~>8}XLm{2OHEhk|EfXP2n?82*%v?kI{VmGILEbchckjBfdG4_kF?ebLAN_paW zdO_=f*E)14m`xtiu0&s|hK#IGeyPfb*#aT%O{AqrQp|{(0Kf^DUaJ0&AVWw<8$JRu z=<4m^trIFm81~`1K&69cLA97m`tES&1ZvOia-~-Wzm$d%;S@Vi)=l3iXM{gBhJotu za9~%TB$M1`Guky@-Y_1cl4e|oTp61T@MDv!e5h0Wj4DI5UE&})qS0`uAy}xDxrsp+ z#5ii@ zL+T>`F=G!8aV25nGO=kR7(j|Afv*QGCWv#{RUVWZ-JcjJzp{cJ(njKn9{dSJ9Z5Y{ zA^r}NeI2jus(-s%#A7VzLAOB;6z&*HL!p2F1;kqbg^Y<&0xJX)5ig>wnuk$eJyTfi_T5a>2o z4E;TV=S!*=@Wj{a)@jg{prJGyS_#M?9$&S15Flci^+xNUL5ZtR$P0w;vi>GclT@IH zDb+;_X>o|^gGpHjYJ_8PhffM`9a||zB+v4khmTvSM6HB9;+zDC>=`3p= zcB9jwe~1s&YF)ZV9nnp#L*1kkaO#cW_@lBC1&MF{dX(na- z0^cgr_4;M3*WbK^LILIFLyJb!BaTeFg;e-w5p;~XjDC}AN3=RnRoUsxLDt&HENN4& zw0VN`=2S^>I9jDnd#luuB2l=I4lCS#|Nl27OQ&73Tvn%K#ZBwwH|@A-zx-w@Zl+#- z(~X<%;bEmX**^63jdur>$7Dn8Jl)@>ij;Y(WCl z@U$|*PF51RFgQRr%`I?fl*AmuP@}&g&vk%uk&GCUKpgV0!N36{D;I|xtVlRyV{yeH zRS(CBDTDziSJF5qZek?HmX!u57|r)tW>23rJ{Qbqj!+*h6bcHvMT!9h9nP(Jn1eWA zDnN&GD}qx(hjVK-g1_Pba*;-ncR+ZF&w-K`(~yzH=PPL9115PxY&iuL3cVVMEg!#C z?K0#o{q#Qwh78S|otL>y05z4kUcS1Xu1q~pulVOhnofqE2B0B#)DoIhFMxUxwMRpP zlYp46bl=+n`|E?2?d+Kd3C|)U8)yY+f7|vg!Y=Zpw(Vj#_OW)la?uHVyI(87JO^V{~mZlxL_G>XPcSnb~s;}AgR8i^tW=eNC06&{MU zy)6#J+P2cgyEuy7F;tG_bADyT#&fptHpgdwC}{i&r!~hHE{c+1a_LuFNOuRr9-CO9 zTYi{RlUA=S;=eICj~Pq*7(=A}s{^LEco@3ZlxPRM38D5VNfdqkzxBoRypDepC9fGH ziVS(_uZkcqO_L0H>2Heqla1<2!Xb$*mv%%e2clMLa4hJJPOVCJh{GR(RHb3EEbOlX z9C9gX3``+$3imo?Foe6J5_pfoB=&+C69JUmC00WYKs}y3j(Q-vNvjkk^ayY3ODxrZ zP$S@xQA0~FYu6UQmLr|irzvQ(=H1#5Y%}!pUXAi~H|v^#c7Guia&puq)?v`82eL=C zC5yw>rqL84a7NNMsk=}yeS#+wUT#bQt<8s86hYTA*CRP4RHOQ79!|Yb+%^u@uiYd; z&`)!4noBz$<54!QJ^CYrZDai@2`X|iLojU$#T&F|iso@gf6}iT_w>7>&P_+R>i#A z!&+B{qTq81ga}4M&#+u;j$5pP|$K5&ZXX8lWka&`Ou9Cpyn`1CyYc3fh z_S<6!75XUXRH1l;M0l{p45>~UnAe6>P&}MWC=P{Zm5|J0Rvv!ta^q)S4t}b$@$&#Z znC5jdZ&tneakiI(x-gsK6W!GayJ7F+z7&vBd5`9%&`EbS+Ra;gzV1`r09U!`ao^1z z1f)^Z0n5A`bq>Ka&#lhEcNL^~8qUxtc&g5GEA&*IXIJJRqd03VouJ}-G+Qu#4|_H( z2%tVv%c|IRRDbJVSp{WHq9lUn&DWK3WU|nw)`hRc8|NWk@H!#;fU<<@{G(Cl z2ynwx=g05Cb`MgcA(3~Xm@HOYBN4OJGr|I^N-TYg7N+D!#q(b+sL z?k&Pawp=$1>2h(FCfAkLJ`DUd$x9)?NO zq4wZJyfx{r;PM&SRNn Nj$4i6RJVTre*xxKygvW{ literal 0 HcmV?d00001 diff --git a/CODE/BT/EXAMPLE.BAT b/CODE/BT/EXAMPLE.BAT new file mode 100644 index 0000000..5cbe574 --- /dev/null +++ b/CODE/BT/EXAMPLE.BAT @@ -0,0 +1,11 @@ +@echo off +del error.log +make -r -DBTYPE=opt -DBPATH=btl4.pth -fmunga\munga.mak %1 %2 %3 %4 %5 +if errorlevel 1 goto done +make -r -DBTYPE=opt -DBPATH=btl4.pth -fmunga_l4\mungal4.mak %1 %2 %3 %4 %5 +if errorlevel 1 goto done +make -r -DBTYPE=opt -DBPATH=btl4.pth -fbt\bt.mak %1 %2 %3 %4 %5 +if errorlevel 1 goto done +make -r -DBTYPE=opt -DBPATH=btl4.pth -fbt_l4\btl4.mak %1 %2 %3 %4 %5 +:done + diff --git a/CODE/BT/EXAMPLE.CFG b/CODE/BT/EXAMPLE.CFG new file mode 100644 index 0000000..09aa522 --- /dev/null +++ b/CODE/BT/EXAMPLE.CFG @@ -0,0 +1,12 @@ +BC_ROOT = d:\bc5 +DPL_ROOT = g:\tesla_bt\munga_l4\libdpl +SOS_ROOT = g:\tesla_bt\munga_l4\sos +NETNUB_ROOT = g:\tesla_bt\munga_l4\netnub +STARTUP_ROOT = g:\tesla_bt +MUNGA_ROOT = g:\tesla_bt\munga +BT_ROOT = g:\tesla_bt\bt + +MUNGAL4_ROOT = g:\tesla_bt\munga_l4 +BTL4_ROOT = g:\tesla_bt\bt_l4 + +BCC_OPT = bcc32i diff --git a/CODE/BT/EXCLUDE.LST b/CODE/BT/EXCLUDE.LST new file mode 100644 index 0000000..001f660 --- /dev/null +++ b/CODE/BT/EXCLUDE.LST @@ -0,0 +1,7 @@ +joystick.ini +anims\vcs.cfg +audio\vcs.cfg +gauge\vcs.cfg +maps\vcs.cfg +models\vcs.cfg +solids\vcs.cfg diff --git a/CODE/BT/HMIDET.386 b/CODE/BT/HMIDET.386 new file mode 100644 index 0000000000000000000000000000000000000000..6f5478f6ef84003ec6fe6f5c2c61f030e252d85e GIT binary patch literal 87624 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 literal 0 HcmV?d00001 diff --git a/CODE/BT/HMIDRV.386 b/CODE/BT/HMIDRV.386 new file mode 100644 index 0000000000000000000000000000000000000000..8429a7dedb3310133c30fed09b38f7a69d576fff GIT binary patch literal 261257 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

$XK3&kOlIM6<+A#fD=x})1P&?#P~QK78Q+ce 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 c); + #endif + + return True; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Degree::TestClass() +{ + DEBUG_STREAM << "Starting Degree test...\n"; + + const Degree a(DEG_PER_RAD); + Degree + b,c; + + Radian + r(1.0f),s; + + s = a; + Test(r == s); + b = r; + s = b; + Test(r == s); + c = DEG_PER_RAD; + s = c; + Test(r == s); + b = c; + s = b; + Test(r == s); + + return True; +} + +// +//############################################################################# +//############################################################################# +// +Logical + SinCosPair::TestClass() +{ + DEBUG_STREAM << "Starting SinCos test...\n"; + Radian + s,r(PI_OVER_2); + + SinCosPair a; + a = r; + + Test(Close_Enough(a.sine,1.0f)); + Test(Small_Enough(a.cosine)); + + s = a; + Test(s == r); + + return True; +} diff --git a/CODE/BT/MUNGA/APP.THP b/CODE/BT/MUNGA/APP.THP new file mode 100644 index 0000000..c96d6c9 --- /dev/null +++ b/CODE/BT/MUNGA/APP.THP @@ -0,0 +1,45 @@ +//===========================================================================// +// File: tstapp.hh // +// Project: MUNGA Brick: Application // +// Contents: Interface specification for Application // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 ECH Added event utilities. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(APP_THP) +# define APP_THP + +# if !defined(APP_HPP) +# include "app.hpp" +# endif + +# if !defined(RENDERER_THP) +# include "renderer.thp" +# endif + +# if !defined(VIDREND_HPP) +# include "vidrend.hpp" +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TestApplication ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class TestApplication: + public Application + { + public: + TestApplication(ResourceFile *resource_file); + ~TestApplication(); + + void + Initialize(); + void + Terminate(); + }; + +#endif diff --git a/CODE/BT/MUNGA/APPMGR.HPP b/CODE/BT/MUNGA/APPMGR.HPP new file mode 100644 index 0000000..bfe5cdc --- /dev/null +++ b/CODE/BT/MUNGA/APPMGR.HPP @@ -0,0 +1,33 @@ +#if !defined(APPMGR_HPP) +# define APPMGR_HPP + +# if !defined(APP_HPP) +# include +# endif + + class ApplicationManager: + public Node + { + public: + ApplicationManager(Scalar frame_rate); + ~ApplicationManager(); + + void + StartApplication(Application *new_app); + + void + RunMissions(); + + Scalar + GetFrameRate() + {Check(this); return frameRate;} + + protected: + Scalar + frameDuration, + frameRate; + SChainOf + runningApplications; + }; + +#endif diff --git a/CODE/BT/MUNGA/AUDTIME.CPP b/CODE/BT/MUNGA/AUDTIME.CPP new file mode 100644 index 0000000..ad9f401 --- /dev/null +++ b/CODE/BT/MUNGA/AUDTIME.CPP @@ -0,0 +1,87 @@ +//===========================================================================// +// File: audtime.cpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: Interface declarations for AudioTim // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/08/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDIO_HPP) + #include +#endif + +#if !defined(AUDTIME_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(AUDREND_HPP) + #include +#endif + +//############################################################################# +//############################# AudioTime ############################### +//############################################################################# + +const AudioTime + AudioTime::Null; + +// +//############################################################################# +//############################################################################# +// +Logical + AudioTime::TestInstance() const +{ + return True; +} + +// +//############################################################################# +//############################################################################# +// +AudioTime + AudioTime::Now() +{ + Check(application); + Check(application->GetAudioRenderer()); + return AudioTime(application->GetAudioRenderer()->GetAudioFrameCount()); +} + +// +//############################################################################# +//############################################################################# +// +AudioFrameCount + AudioTime::Seconds_To_Frames(Scalar seconds) const +{ + Check(application); + Check(application->GetAudioRenderer()); + return + (seconds * application->GetAudioRenderer()->GetCalibrationRate() + 0.5f); +} + +// +//############################################################################# +//############################################################################# +// +Scalar + AudioTime::Frames_To_Seconds(AudioFrameCount frames) const +{ + Check(application); + Check(application->GetAudioRenderer()); + return + ((Scalar)frames / application->GetAudioRenderer()->GetCalibrationRate()); +} + diff --git a/CODE/BT/MUNGA/AUDTOOLS.HPP b/CODE/BT/MUNGA/AUDTOOLS.HPP new file mode 100644 index 0000000..37e76f5 --- /dev/null +++ b/CODE/BT/MUNGA/AUDTOOLS.HPP @@ -0,0 +1,51 @@ +//===========================================================================// +// File: audtools.hpp // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/10/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDTOOLS_HPP) +# define AUDTOOLS_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(CSTR_HPP) +# include +# endif + + //########################################################################## + //##################### AudioCreateSymbols ########################### + //########################################################################## + + class AudioCreateSymbols + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + AudioCreateSymbols(); + ~AudioCreateSymbols(); + + void Execute(); + + private: + static void + MakeFileReadWrite(const CString &file_name); + + protected: + virtual void + WriteEntryStream(ofstream &symbol_file); + }; + +#endif + diff --git a/CODE/BT/MUNGA/AUDWGT.CPP b/CODE/BT/MUNGA/AUDWGT.CPP new file mode 100644 index 0000000..83d72d9 --- /dev/null +++ b/CODE/BT/MUNGA/AUDWGT.CPP @@ -0,0 +1,38 @@ +//===========================================================================// +// File: audwgt.cpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: Implementation for audio weighting // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/02/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDWGT_HPP) +# include +#endif + +//############################################################################# +//########################## AudioWeighting ############################# +//############################################################################# + +const AudioWeighting + AudioWeighting::Null; + +// +//############################################################################# +//############################################################################# +// +Logical + AudioWeighting::TestInstance() const +{ + return True; +} + diff --git a/CODE/BT/MUNGA/AVERAGE.CPP b/CODE/BT/MUNGA/AVERAGE.CPP new file mode 100644 index 0000000..97e3dcc --- /dev/null +++ b/CODE/BT/MUNGA/AVERAGE.CPP @@ -0,0 +1,21 @@ +//===========================================================================// +// File: average.cpp // +// Project: MUNGA Brick: Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AVERAGE_HPP) +# include +#endif + diff --git a/CODE/BT/MUNGA/BOXLIST.HPP b/CODE/BT/MUNGA/BOXLIST.HPP new file mode 100644 index 0000000..41f80f8 --- /dev/null +++ b/CODE/BT/MUNGA/BOXLIST.HPP @@ -0,0 +1,177 @@ +//===========================================================================// +// File: bndgbox.hh // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Interface specification of bounding-box based spatialization // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/08/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BOXLIST_HPP) +# define BOXLIST_HPP + +# if !defined(BNDGBOX_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + +# if !defined(POINT3D_HPP) +# include +# endif + + //########################################################################## + //####################### BoundingBoxListNode ######################## + //########################################################################## + + class BoundingBoxList; + class BoxedSolidList; + class BoundingBoxTree; + + class BoundingBoxListNode SIGNATURED + { + friend class BoundingBoxList; + friend class BoxedSolidList; + + //########################################################################## + // Memory Allocation + // + private: + static MemoryBlock + AllocatedMemory; + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + + //########################################################################## + // Construction and Destruction + // + protected: + BoundingBox + *boundingBox; + BoundingBoxListNode + *previousNode; + + BoundingBoxListNode( + BoundingBox *volume, + const ExtentBox &slice + ): + boundingBox(volume), + solidSlice(slice), + previousNode(NULL) + {Check_Pointer(this); Check(volume);} + ~BoundingBoxListNode() + {Check(this);} + + public: + ExtentBox + solidSlice; + BoundingBox* + GetBoundingBox() + {Check(this); return boundingBox;} + BoundingBoxListNode* + GetNextNode() + {Check(this); return previousNode;} + + //########################################################################## + // Test Support + // + public: + Logical + TestInstance() const; + }; + + //########################################################################## + //######################## BoundingBoxList ########################### + //########################################################################## + + class BoundingBoxList SIGNATURED + { + + //########################################################################## + // Construction and Destruction + // + protected: + BoundingBoxListNode + *root; + int + nodeCount; + int* + scoreBoard; + BoundingBox + **boundingBoxIndex; + Logical + isXMajorAxis; + + public: + BoundingBoxList(); + ~BoundingBoxList(); + + void + Add( + BoundingBox* volume, + const ExtentBox &slice + ); + void + Remove(BoundingBox* volume); + void + EraseList(); + + BoundingBoxListNode* + GetRoot() + {Check(this); return root;} + + //########################################################################## + // Tree Traversal Functions + // + public: + BoundingBox* + FindBoundingBoxContaining(const Point3D &point); + + void + FindBoundingBoxesContaining( + BoundingBox *volume, + BoundingBoxCollisionList &list + ); + + BoundingBox* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ); + + BoundingBox* + FindBoundingBoxHitBy(Line *line); + + void + Reduce(); + void + SortForTree(); + + protected: + void + Sort( + BoundingBoxList &active_solids, + ExtentBox &clipping_box, + BoundingBoxTree &tree_so_far + ); + + //########################################################################## + // Test Support + // + public: + Logical + TestInstance() const; + }; + +#endif diff --git a/CODE/BT/MUNGA/CMPNNT.HPP b/CODE/BT/MUNGA/CMPNNT.HPP new file mode 100644 index 0000000..b0d0c90 --- /dev/null +++ b/CODE/BT/MUNGA/CMPNNT.HPP @@ -0,0 +1,73 @@ +//===========================================================================// +// File: cmpnnt.hh // +// Project: MUNGA Brick: Watcher // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(CMPNNT_HPP) +# define CMPNNT_HPP + +# if !defined(RECEIVER_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Component: + public Receiver + { + public: + // + //----------------------------------------------------------------------- + // Destructor + //----------------------------------------------------------------------- + // + ~Component(); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + virtual void + Execute(); + + // + //----------------------------------------------------------------------- + // Shared Data Support + //----------------------------------------------------------------------- + // + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + Logical + TestInstance() const; + + protected: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + Component( + ClassID class_id = TrivialComponentClassID, + SharedData &shared_data = DefaultData + ); + Component( + PlugStream *stream, + SharedData &shared_data = DefaultData + ); + }; + +#endif + diff --git a/CODE/BT/MUNGA/COLOR.CPP b/CODE/BT/MUNGA/COLOR.CPP new file mode 100644 index 0000000..dc566f1 --- /dev/null +++ b/CODE/BT/MUNGA/COLOR.CPP @@ -0,0 +1,106 @@ +//===========================================================================// +// File: Color.cpp // +// Project: MUNGA Brick: Utility Library // +// Contents: Implementation details for color classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/12/95 GDU Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(COLOR_HPP) +# include +#endif + +#if !defined(CSTR_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile RGBColor *) + { + return False; + } + +#endif + +// +//########################################################################### +//########################################################################### +// +void + Convert_From_Ascii( + const char *str, + RGBColor *color + ) +{ + Check_Pointer(str); + Check_Signature(color); + + CString parse_string(str); + + Check_Pointer(parse_string.GetNthToken(0)); + color->Red = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + color->Green = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + color->Blue = atof(parse_string.GetNthToken(2)); + + Check(color); +} + +// +//########################################################################### +//########################################################################### +// +Logical + RGBColor::TestInstance() const +{ + return True; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +void + Convert_From_Ascii( + const char *str, + RGBAColor *color + ) +{ + Check_Pointer(str); + Check_Signature(color); + + CString parse_string(str); + + Check_Pointer(parse_string.GetNthToken(0)); + color->Red = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + color->Green = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + color->Blue = atof(parse_string.GetNthToken(2)); + + Check_Pointer(parse_string.GetNthToken(3)); + color->Alpha = atof(parse_string.GetNthToken(3)); + + Check(color); +} + diff --git a/CODE/BT/MUNGA/COLOR.HPP b/CODE/BT/MUNGA/COLOR.HPP new file mode 100644 index 0000000..1df9e24 --- /dev/null +++ b/CODE/BT/MUNGA/COLOR.HPP @@ -0,0 +1,190 @@ +//===========================================================================// +// File: color.hh // +// Title: Declaration of Color classes. // +// Project: Tool Architecture II // +// Author: Jerry Edsall & Ken Olsen (based on work by J.M. Albertson) // +// Purpose: Stores color information. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/15/94 KEO Added RGBAColor class. // +// 11/12/95 GDU Added MUNGA signatures and stream IO, moved to MUNGA // +//---------------------------------------------------------------------------// +// Copyright (c) 1994 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(COLOR_HPP) + #define COLOR_HPP + + #if !defined(MEMSTRM_HPP) + #include + #endif + + #if !defined(SCALAR_HPP) + #include + #endif + + //########################################################################## + //############## RGBColor ############################################ + //########################################################################## + + class RGBColor + { + friend class RGBAColor; + + public: + Scalar + Red, + Green, + Blue; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile RGBColor *p); + #endif + + + RGBColor() + { + Red = Green = Blue = -1.0f; + } + + RGBColor( + Scalar r, + Scalar g, + Scalar b + ) + { + Red = r; + Green = g; + Blue = b; + } + + Logical + operator==(const RGBColor &a_RGBColor) const + { return !memcmp(this, &a_RGBColor, sizeof(RGBColor)); } + Logical + operator!=(const RGBColor &a_RGBColor) const + { return memcmp(this, &a_RGBColor, sizeof(RGBColor)); } + + Logical + TestInstance() const; + + RGBColor + operator+(const RGBColor &a_RGBColor) const + { + return RGBColor ( + min(this->Red + a_RGBColor.Red, 1.0), + min(this->Green + a_RGBColor.Green, 1.0), + min(this->Blue + a_RGBColor.Blue, 1.0)); + } + Scalar + Infrared() const + { return 0.3 * this->Red + 0.5 * this->Green + 0.2 * this->Blue; } + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const RGBColor& C + ); + + + private: + Scalar + min(Scalar x, Scalar y) const + { return x < y ? x : y; } + + + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + RGBColor *color + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + RGBColor *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const RGBColor *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + //########################################################################## + //############## RGBAColor ########################################### + //########################################################################## + + class RGBAColor: + public RGBColor + { + public: + Scalar + Alpha; + + RGBAColor(): + RGBColor() + { Alpha = -1.0f; } + + RGBAColor( + Scalar r, + Scalar g, + Scalar b, + Scalar a + ): + RGBColor(r, g, b) + { Alpha = a; } + + Logical + operator==(const RGBAColor &a_RGBAColor) const + { return !memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); } + Logical + operator!=(const RGBAColor &a_RGBAColor) const + { return memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); } + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const RGBAColor& c + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + RGBAColor *color + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + RGBAColor *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const RGBAColor *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + +#endif + +//============================================================================= diff --git a/CODE/BT/MUNGA/CSTR.TCP b/CODE/BT/MUNGA/CSTR.TCP new file mode 100644 index 0000000..2943322 --- /dev/null +++ b/CODE/BT/MUNGA/CSTR.TCP @@ -0,0 +1,79 @@ + +#define TEST_STRING "Test String" +#define TEST_STRING_2 "Test StringTest String" +#define TEST_STRING_3 "Test StringZ" + +Logical + CString::TestClass() +{ +#if 1 + CString string_a; + + //Verify(string_a.stringSize == 0); + //Verify(string_a.stringLength == 0); + //Verify(string_a.stringText == NULL); + + CString string_b(TEST_STRING); + CString string_c(string_b); + + Verify(string_b.Length() == strlen(TEST_STRING)); + Verify(string_b.Length() == strlen(string_c)); + Verify(string_b == string_c); + + CString string_d(TEST_STRING_2); + CString string_e; + + string_e = string_b + string_c; + Verify(string_e == string_d); + + CString string_f(TEST_STRING_3); + CString string_g; + + string_g = string_b + 'Z'; + Verify(string_g == string_f); + + CString string_h(TEST_STRING); + + string_h += string_b; + Verify(string_h == string_d); + + CString string_i(TEST_STRING); + + string_i += 'Z'; + Verify(string_i == string_f); + + CString string_j("aaa"); + CString string_k("aab"); + CString string_l("abb"); + CString string_m("bbb"); + CString string_n("aaa"); + + Verify(string_j < string_k); + Verify(string_l > string_k); + Verify(string_l <= string_m); + Verify(string_m >= string_j); + Verify(string_j == string_n); + Verify(string_j != string_k); + + Verify(string_k[0] == 'a'); + Verify(string_k[1] == 'a'); + Verify(string_k[2] == 'b'); + + CString string_o("0.1,0.2,0.3"); + CString string_p("0.1 0.2 0.3"); + CString string_q("0.1"); + CString string_r("0.2"); + CString string_s("0.3"); + + Verify(string_o.GetNthToken(0) == string_q); + Verify(string_o.GetNthToken(1) == string_r); + Verify(string_o.GetNthToken(2) == string_s); + + Verify(string_p.GetNthToken(0) == string_q); + Verify(string_p.GetNthToken(1) == string_r); + Verify(string_p.GetNthToken(2) == string_s); +#endif + + return True; +} + diff --git a/CODE/BT/MUNGA/DEBUGOFF.HPP b/CODE/BT/MUNGA/DEBUGOFF.HPP new file mode 100644 index 0000000..57c3006 --- /dev/null +++ b/CODE/BT/MUNGA/DEBUGOFF.HPP @@ -0,0 +1,72 @@ +//=======================================================================// +// File: debugoff.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +// 4-12-95 CPB added Str_Cat macro // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(OLD_DEBUG_LEVEL) +# define OLD_DEBUG_LEVEL 0 +#else +# undef OLD_DEBUG_LEVEL +# if DEBUG_LEVEL>=3 +# define OLD_DEBUG_LEVEL 3 +# elif DEBUG_LEVEL==2 +# define OLD_DEBUG_LEVEL 2 +# elif DEBUG_LEVEL==1 +# define OLD_DEBUG_LEVEL 1 +# endif +#endif + +#undef DEBUG_LEVEL +#undef Verify +#undef Verify_And_Dump +#undef Warn +#undef Warn_And_Dump +#undef Dump +#undef Tell +#undef Check_Signature +#undef Check_Pointer +#undef Mem_Copy +#undef Str_Copy +#undef Str_Cat +#undef Check +#undef Check_Fpu +#undef Fail +#undef Cast_Object +#undef DEBUG_CODE +#undef Sqrt +#undef Arctan +#undef Arccos +#undef Arcsin + +#define DEBUG_LEVEL 0 +#define DEBUG_CODE(x) +#define Verify(c) +#define Verify_And_Dump(c,v) +#define Warn(c) +#define Warn_And_Dump(c,v) +#define Dump(v) +#define Tell(m) +#define Check_Pointer(p) +#define Check_Fpu() +#define Mem_Copy(destination, source, length, available)\ + memcpy(destination, source, length) +#define Str_Copy(destination, source, available)\ + strcpy(destination, source); +#define Str_Cat(destination, source, available)\ + strcat(destination, source); +#define Sqrt(value) sqrt(value) +#define Arctan(y,x) atan2(y,x) +#define Arccos(x) acos(x) +#define Arcsin(x) asin(x) +#define Power(x,y) pow(x,y) + +#define Check(p) +#define Check_Signature(p) +#define Fail(m) Fail_To_Debugger(m,__FILE__,__LINE__) +#define Cast_Object(type, ptr) ((type)(ptr)) + diff --git a/CODE/BT/MUNGA/DEBUGOLD.HPP b/CODE/BT/MUNGA/DEBUGOLD.HPP new file mode 100644 index 0000000..d1b2fac --- /dev/null +++ b/CODE/BT/MUNGA/DEBUGOLD.HPP @@ -0,0 +1,24 @@ +//=======================================================================// +// File: debug2on.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +// 4-12-95 CPB added Str_Cat macro // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(OLD_DEBUG_LEVEL) +# error Cannot revert to old debug level! +#else +# if OLD_DEBUG_LEVEL>=3 +# include +# elif OLD_DEBUG_LEVEL==2 +# include +# elif OLD_DEBUG_LEVEL==1 +# include +# else +# include +# endif +#endif + diff --git a/CODE/BT/MUNGA/EVTSTAT.CPP b/CODE/BT/MUNGA/EVTSTAT.CPP new file mode 100644 index 0000000..c69edf3 --- /dev/null +++ b/CODE/BT/MUNGA/EVTSTAT.CPP @@ -0,0 +1,168 @@ +//===========================================================================// +// File: evtstat.cpp // +// Project: MUNGA Brick: Event Manager // +// Contents: interface specification of event manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/15/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(EVTSTAT_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#if !defined(REGISTRY_HPP) +# include +#endif + +#if !defined(ENTITY_HPP) +# include +#endif + +//############################################################################# +//########################## EventStatistics ############################ +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +EventStatistics::EventStatistics( + ClassID class_ID, + Receiver::MessageID message_ID +): + classID(class_ID), + messageID(message_ID), + eventCount(0) +{ +} + +//############################################################################# +//######################## EventStatisticsManager ####################### +//############################################################################# + +EventStatisticsManager + event_statistics_manager; + +// +//############################################################################# +//############################################################################# +// +EventStatisticsManager::EventStatisticsManager(): + eventStatisticsSocket(NULL, True) +{ + printedReport = False; +} + +// +//############################################################################# +//############################################################################# +// +void + EventStatisticsManager::Maintain(Event *event) +{ + Check(this); + Check(event); + + // + // If the application is not running then it is not time to collect + // statistics yet + // + Check(application); + if (application->GetApplicationState() != Application::RunningMission) + return; + + // + // Add statistics for this event + // + ClassID + class_ID; + Receiver::MessageID + message_ID; + long + index_value; + EventStatistics + *event_statistics; + + message_ID = event->messageToSend->messageID; + class_ID = event->targetReceiver.GetCurrent()->GetClassID(); + index_value = class_ID * 1000 + message_ID; // HACK to create unique key + if ((event_statistics = eventStatisticsSocket.Find(index_value)) == NULL) + { + event_statistics = new EventStatistics(class_ID, message_ID); + eventStatisticsSocket.AddValue(event_statistics, index_value); + } + Check(event_statistics); + event_statistics->eventCount++; +} + +// +//############################################################################# +//############################################################################# +// +void + EventStatisticsManager::Report() +{ + Check(this); + + // + // Print Report + // + TableIteratorOf + iterator(&eventStatisticsSocket); + EventStatistics + *event_statistics; + + DEBUG_STREAM << "EventStatisticsManager::Report - event_count=" + << iterator.GetSize() << "\n"; + while ((event_statistics = iterator.ReadAndNext()) != NULL) + { + Check(event_statistics); + + Registry + *registry; + Entity::SharedData + *shared_data; + Derivation + *derivation; + Receiver::MessageHandlerSet + *handlers; + + DEBUG_STREAM << "EventStatisticsManager::Report -\t"; + DEBUG_STREAM << event_statistics->classID << "\t"; + DEBUG_STREAM << event_statistics->messageID << "\t"; + DEBUG_STREAM << event_statistics->eventCount << "\t"; + + Check(application); + if ((registry = application->GetRegistry()) != NULL) + { + Check(registry); + shared_data = registry->GetStaticData(event_statistics->classID); + if (shared_data != NULL) + { + Check(shared_data); + derivation = shared_data->derivedClasses; + Check(derivation); + handlers = shared_data->activeMessageHandlers; + Check(handlers); + + DEBUG_STREAM << derivation->className << "::" + << handlers->GetName(event_statistics->messageID) << "\t"; + } + } + DEBUG_STREAM << "\n"; + } + iterator.DeletePlugs(); +} + diff --git a/CODE/BT/MUNGA/EVTSTAT.HPP b/CODE/BT/MUNGA/EVTSTAT.HPP new file mode 100644 index 0000000..71c108e --- /dev/null +++ b/CODE/BT/MUNGA/EVTSTAT.HPP @@ -0,0 +1,96 @@ +//===========================================================================// +// File: evtstat.hpp // +// Project: MUNGA Brick: Event Manager // +// Contents: interface specification of event manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/15/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(EVTSTAT_HPP) +# define EVTSTAT_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(RECEIVER_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + + //######################################################################### + //######################## EventStatistics ########################## + //######################################################################### + + class EventStatistics: + public Plug + { + friend class EventStatisticsManager; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction + // + public: + EventStatistics::EventStatistics( + ClassID class_ID, + Receiver::MessageID message_ID + ); + ~EventStatistics() {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + ClassID + classID; + Receiver::MessageID + messageID; + long + eventCount; + }; + + //######################################################################### + //##################### EventStatisticsManager ###################### + //######################################################################### + + class EventStatisticsManager: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction + // + public: + EventStatisticsManager::EventStatisticsManager(); + ~EventStatisticsManager() {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Statistic collection and reporting + // + public: + void + Maintain(Event *event); + void + Report(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + TableOf + eventStatisticsSocket; + Logical + printedReport; + }; + + extern EventStatisticsManager + event_statistics_manager; + +#endif \ No newline at end of file diff --git a/CODE/BT/MUNGA/FILESTRM.CPP b/CODE/BT/MUNGA/FILESTRM.CPP new file mode 100644 index 0000000..6ba166a --- /dev/null +++ b/CODE/BT/MUNGA/FILESTRM.CPP @@ -0,0 +1,152 @@ +#include +#pragma hdrstop + +#if !defined(FILESTRM_HPP) +# include +#endif + +//############################################################################# +//########################### FileStream ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +FileStream::FileStream( + const char* file_name, + Logical writable +): + MemoryStream(NULL, 0) +{ + Open(file_name, writable); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::Open( + const char* file_name, + Logical writable + ) +{ + readOnly = !writable; + (int)fileHandle = -1; + currentPosition = streamStart = NULL; + streamSize = 0; + if (file_name) + { + Check_Pointer(file_name); + fileHandle = OpenImplementation(file_name, readOnly); + } + + if ((int) fileHandle != -1) + { + if (readOnly) + { + streamSize = SeekImplementation(fileHandle, 0, True); + SeekImplementation(fileHandle, 0); + } + else + { + streamSize = 0xFFFFFFFFU; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::Close() +{ + Check(this); + + // + //--------------------------------- + // If the file was opened, close it + //--------------------------------- + // + if ((int) fileHandle != -1) + { + CloseImplementation(fileHandle); + } + (int)fileHandle = -1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::SetPointer(size_t index) +{ + Check(this); + Verify((int) fileHandle != -1); + + currentPosition = (char*)SeekImplementation(fileHandle, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::AdvancePointer(size_t index) +{ + Check(this); + Verify((int)fileHandle != -1); + + currentPosition = + (char*)SeekImplementation(fileHandle, (size_t)currentPosition + index); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::RewindPointer(size_t index) +{ + Check(this); + Verify((int)fileHandle != -1); + + currentPosition = + (char*)SeekImplementation(fileHandle, (size_t)currentPosition + index); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::ReadBytes( + void *ptr, + size_t number_of_bytes + ) +{ + Check(this); + Verify((int)fileHandle != -1); + Verify(readOnly); + size_t read = ReadImplementation(fileHandle, ptr, number_of_bytes); + Verify(read == number_of_bytes); + currentPosition += read; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::WriteBytes( + const void *ptr, + size_t number_of_bytes + ) +{ + Check(this); + Verify((int)fileHandle != -1); + Verify(!readOnly); + size_t written = WriteImplementation(fileHandle, ptr, number_of_bytes); + Verify(written == number_of_bytes); + currentPosition += written; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + FileStream::TestInstance() const +{ + return True; +} + diff --git a/CODE/BT/MUNGA/FILESTRM.HPP b/CODE/BT/MUNGA/FILESTRM.HPP new file mode 100644 index 0000000..534aad0 --- /dev/null +++ b/CODE/BT/MUNGA/FILESTRM.HPP @@ -0,0 +1,121 @@ +//===========================================================================// +// File: filestrm.hpp // +// Project: MUNGA Brick: Resource Manager // +// Contents: Implementation Details of resource management // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(FILESTRM_HPP) +# define FILESTRM_HPP + +# if !defined(MEMSTRM_HPP) +# include +# endif + + //########################################################################## + //######################## FileStream ################################ + //########################################################################## + + class FileStream: + public MemoryStream + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructors + // + public: + FileStream( + const char* file_name = NULL, + Logical writable = False + ); + ~FileStream() + {Close();} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Status functions + // + public: + void* + GetPointer() const + { + Fail("No implementation possible for FileStream::GetPointer()"); + return NULL; + } + + void + SetPointer(void *new_pointer) + {Fail("No implementation possible for FileStream::SetPointer(void*)");} + void + SetPointer(size_t index); + + MemoryStream& + AdvancePointer(size_t count); + + MemoryStream& + RewindPointer(size_t count); + + MemoryStream& + ReadBytes( + void *ptr, + size_t number_of_bytes + ); + MemoryStream& + WriteBytes( + const void *ptr, + size_t number_of_bytes + ); + + void + Open( + const char* file_name = NULL, + Logical writable = False + ); + void + Close(); + Logical + IsFileOpened() + {return ((int) fileHandle) != -1;} + + Logical + TestInstance() const; + + static Logical + TestClass(); + + protected: + void * fileHandle; + Logical readOnly; + + static void* + OpenImplementation( + const char* file_name, + Logical read_only + ); + static void + CloseImplementation(void * file_handle); + static size_t + SeekImplementation( + void * file_handle, + size_t where, + Logical from_end = False + ); + static size_t + ReadImplementation( + void * file_handle, + void *buffer, + size_t length + ); + static size_t + WriteImplementation( + void * file_handle, + const void* buffer, + size_t length + ); + }; + +#endif + diff --git a/CODE/BT/MUNGA/FILESTRM.TCP b/CODE/BT/MUNGA/FILESTRM.TCP new file mode 100644 index 0000000..f897d09 --- /dev/null +++ b/CODE/BT/MUNGA/FILESTRM.TCP @@ -0,0 +1,52 @@ +//===========================================================================// +// File: filestrm.tcp // +// Project: MUNGA Brick: Filestream Manager // +// Contents: Test stuff for MMIO class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 4/25/96 JTR Initial Creation // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MMIOstream ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// + +#include + +Logical +FileStream::TestClass() +{ + char buffer[65535]; + int i; + float total = 0; + Time s; + + FileStream Testit; + + memset(buffer,'A',65535); + + DEBUG_STREAM << "Starting FileStream test...\n"; + for(i=0; i < 1024; i++) + { + s = Now(); + Testit.Open("mmiotest.tst",1); + Testit.WriteBytes(buffer,65535); + Testit.Close(); + Testit.Open("mmiotest.tst",0); + Testit.ReadBytes(buffer,65535); + Testit.Close(); + total += Now() - s; + } + for(i=0; i < 65535; i++) Verify(buffer[i] == 'A'); + DEBUG_STREAM << "Opening, writing, closing, opening, reading, and closing\n 64K file 1024 times, averaging out to " << total / 1024.0f << " ticks apiece...\n"; + DEBUG_STREAM << "File data checks out, as well...\n"; + DEBUG_STREAM << "Leaving FileStream test...\n"; + return True; +}; diff --git a/CODE/BT/MUNGA/FILESTUB.CPP b/CODE/BT/MUNGA/FILESTUB.CPP new file mode 100644 index 0000000..2170a1e --- /dev/null +++ b/CODE/BT/MUNGA/FILESTUB.CPP @@ -0,0 +1,78 @@ +#include +#pragma hdrstop + +#if !defined(FILESTRM_HPP) +# include +#endif + +#include +#include +#include + +//############################################################################# +//########################### FileStream ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void* + FileStream::OpenImplementation( + const char *file_name, + Logical read_only + ) +{ + if (read_only) + { + return (void*)open(file_name, O_BINARY|O_RDONLY); + } + else + { + return (void*) + open(file_name, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, S_IWRITE); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::CloseImplementation(void * file_handle) +{ + close((int)file_handle); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::SeekImplementation( + void * file_handle, + size_t where, + Logical from_end + ) +{ + return lseek((int)file_handle, (long)where, (from_end) ? SEEK_END : SEEK_SET); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::ReadImplementation( + void * file_handle, + void *buffer, + size_t length + ) +{ + return read((int)file_handle, buffer, length); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::WriteImplementation( + void * file_handle, + const void *buffer, + size_t length + ) +{ + return write((int)file_handle, buffer, length); +} + diff --git a/CODE/BT/MUNGA/HEAP.HPP b/CODE/BT/MUNGA/HEAP.HPP new file mode 100644 index 0000000..179d241 --- /dev/null +++ b/CODE/BT/MUNGA/HEAP.HPP @@ -0,0 +1,125 @@ +//--------------------------------------------------------------------------- +// +// Heap.h -- This file contains the definition for the Base HEAP +// Manager Class. The Base HEAP manager creates, +// manages and destroys block of memory using Win32 +// virtual memory calls. +// +// Honor Bound -- FASA Interactive Technologies +// +// Copyright (c) 1995 FASA Interactive Technologies +// +//--------------------------------------------------------------------------- + +#if !defined(HEAP_HPP) +# define HEAP_HPP + + #if !defined(STYLE_HPP) + #include + #endif + +# if !defined(MEMREG_HPP) +# include +# endif + +#if defined(MW3) + extern fstream debugfile; +#endif + + struct HeapBlock; + struct HeapFreeBlock; + + class UserHeap SIGNATURED + { + protected: + char + *bigHeap; + const char + *heapName; + HeapBlock + *heapStart, + *firstNearBlock; + size_t + heapSize, + lowestTotalHeapLeft; + size_t + allocateCount, + releaseCount; + + protected: + void + Relink(HeapBlock *newBlock); + void + Unlink(HeapBlock *oldBlock); + void + Sort(HeapBlock *sortBlock); + void + MergeWithLower(HeapBlock *block); + + public: + UserHeap( + const char* heap_name, + size_t mem_size + ); + ~UserHeap(); + + size_t + GetTotalHeapLeft(); + size_t + GetBiggestHeapLeft(); + size_t + GetLowestTotalHeapLeft() + {return lowestTotalHeapLeft;} + size_t + GetHeapUsed() + {return heapSize - GetTotalHeapLeft();} + size_t + GetMostHeapUsed() + {return heapSize - lowestTotalHeapLeft;} + + Logical + TestHeap( + Logical print_it = False, + Logical skip_allocated = False, + Logical skip_free = False + ); + + void* + Allocate(size_t mem_size); + void + Release(void *where); + void + ReleaseAll(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Global memory allocation + // + protected: + static LWord + HeapMark; + Logical + mainHeap; + + public: + static UserHeap + MainStorage; + + static size_t + GetMainHeapInitialSize(); + + friend void* + operator new(size_t mem_size); + friend void* + operator new(size_t mem_size, void* where); + friend void + operator delete(void *mem_block); + }; + + void* + Get_Caller(int levels); + +#endif + diff --git a/CODE/BT/MUNGA/HOST.TCP b/CODE/BT/MUNGA/HOST.TCP new file mode 100644 index 0000000..cfc587f --- /dev/null +++ b/CODE/BT/MUNGA/HOST.TCP @@ -0,0 +1,56 @@ +//===========================================================================// +// File: host.tst // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for base Host class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/07/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +void + HostManager::TestClass() +{ + DEBUG_STREAM << "Starting Host test...\n"; + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Host *local_host; + + local_host = new Host( + FirstLegalHostID, + GameMachineHostType, + (NetworkAddress)1 + ); + Register_Object(local_host); + + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptLocalHost(local_host); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + HostID localHostID; + + Check(application); + localHostID = application->GetHostManager()->GetLocalHostID(); + Verify(localHostID != NullHostID); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + EntityID newEntityID; + + Check(application); + newEntityID = application->GetHostManager()->MakeUniqueEntityID(); + Verify(newEntityID != EntityID::Null); +} diff --git a/CODE/BT/MUNGA/HOSTID.HPP b/CODE/BT/MUNGA/HOSTID.HPP new file mode 100644 index 0000000..24ddf22 --- /dev/null +++ b/CODE/BT/MUNGA/HOSTID.HPP @@ -0,0 +1,34 @@ +//===========================================================================// +// File: network.hh // +// Project: MUNGA Brick: Network Manager // +// Contents: Interface specification for network brick // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/01/94 JMA Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/03/94 ECH Changed NetworkClient to inherit from Node // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(HOSTID_HPP) +# define HOSTID_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + // + //--------------------------------------------------- + // Support types for host manager + //--------------------------------------------------- + // + typedef Enumeration HostID; + + const HostID NullHostID = 0; + const HostID MapHostID = -1; + const HostID FirstLegalHostID = 1; + +#endif diff --git a/CODE/BT/MUNGA/LINE.CPP b/CODE/BT/MUNGA/LINE.CPP new file mode 100644 index 0000000..b2f9f3f --- /dev/null +++ b/CODE/BT/MUNGA/LINE.CPP @@ -0,0 +1,87 @@ +//=======================================================================// +// File: line.cpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#include +#pragma hdrstop + +#if !defined(LINE_HPP) +# include +#endif + +#if !defined(PLANE_HPP) +# include +#endif + +// +//########################################################################### +//########################################################################### +// +Line& + Line::operator=(const Vector3D &vector) +{ + Check_Pointer(this); + Check(&vector); +// +// Make sure length of vector is non-zero +// + length = vector.Length(); + Verify(length); +// +// Normalize the vector and put it into the line +// + direction.x = vector.x/length; + direction.y = vector.y/length; + direction.z = vector.z/length; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Line& + Line::operator=(const Point3D &point) +{ + Check_Pointer(this); + Check(&point); +// +// Copy the point over into the line. +// + origin.x = point.x; + origin.y = point.y; + origin.z = point.z; + return *this; +} + +Scalar + Line::DistanceTo( + const Plane &plane, + Scalar *product + ) const +{ + *product = direction * plane.normal; + if (Small_Enough(*product)) + { + Check_Fpu(); + return -1.0f; + } + Scalar result = -plane.DistanceTo(origin) / *product; + Check_Fpu(); + return result; +} + +Scalar + Line::DistanceTo( + const Sphere &,//sphere, + Scalar *//penetration + ) const +{ + return -1.0f; // HACK +} + diff --git a/CODE/BT/MUNGA/LINE.HPP b/CODE/BT/MUNGA/LINE.HPP new file mode 100644 index 0000000..87e65d3 --- /dev/null +++ b/CODE/BT/MUNGA/LINE.HPP @@ -0,0 +1,70 @@ +//=======================================================================// +// File: line.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainments, // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(LINE_HPP) +# define LINE_HPP + +# if !defined(RAY_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Line3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Line: + public Ray + { + public: + Scalar + length; + + Line() {} + Line( + const Ray &ray, + Scalar length + ): + Ray(ray), + length(length) + {} + Line( + const Point3D &start, + const UnitVector &direction, + Scalar length + ): + Ray(start,direction), + length(length) + {} + + void + FindEnd(Point3D *result) + {Check(this); Check_Pointer(result); Ray::Project(length, result);} + + // + // Assignment operators + // + Line& + operator=(const Vector3D &vector); + Line& + operator=(const Point3D &point); + // + // Ray intersection functions + // + Scalar + DistanceTo( + const Plane &plane, + Scalar *product + ) const; + Scalar + DistanceTo( + const Sphere &sphere, + Scalar *penetration + ) const; + + }; + +#endif diff --git a/CODE/BT/MUNGA/LINK.CPP b/CODE/BT/MUNGA/LINK.CPP new file mode 100644 index 0000000..2780348 --- /dev/null +++ b/CODE/BT/MUNGA/LINK.CPP @@ -0,0 +1,136 @@ +//===========================================================================// +// File: link.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of base Link // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/28/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(LINK_HPP) + #include +#endif + +#if !defined(PLUG_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Link ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Link +//############################################################################# +// +Link::Link( + Socket *socket, + Plug *plug +) +{ + this->socket = socket; + this->plug = plug; + + // + //---------------------------------------------------- + // Add this new link to the plugs current set of links + //---------------------------------------------------- + // + AddToPlug(plug); +} + +// +//############################################################################# +// ~Link +//############################################################################# +// +Link::~Link() +{ + // + //----------------------------------------------------- + // Remove this link from the plugs current set of links + //----------------------------------------------------- + // + ReleaseFromPlug(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Link::TestInstance() const +{ + Check_Signature(socket); + Check_Signature(plug); + return True; +} + +// +//############################################################################# +// ReleaseFromPlug +//############################################################################# +// +void + Link::ReleaseFromPlug() +{ + // + //----------------------------------------------------- + // Remove this link from the plugs current set of links + //----------------------------------------------------- + // + Check(plug); + if (plug->linkHead == this) + { + plug->linkHead = nextLink; + } + if (prevLink != NULL) + { + Check(prevLink); + prevLink->nextLink = nextLink; + } + if (nextLink != NULL) + { + Check(nextLink); + nextLink->prevLink = prevLink; + } + prevLink = nextLink = NULL; +} + +// +//############################################################################# +// AddToPlug +//############################################################################# +// +void + Link::AddToPlug(Plug *plug) +{ + Verify(plug); + Verify_And_Dump(!Is_Signature_Bad(plug),Is_Signature_Bad(plug));\ + + Verify((plug)->TestInstance()); + Verify(Fpu_Ok()); + Check_All_Signatures(); + + +// Check(plug); + if ((nextLink = plug->linkHead) != NULL) + { + Check(nextLink); + nextLink->prevLink = this; + } + this->prevLink = NULL; + plug->linkHead = this; +} diff --git a/CODE/BT/MUNGA/LINMTRX.TCP b/CODE/BT/MUNGA/LINMTRX.TCP new file mode 100644 index 0000000..7fef7b3 --- /dev/null +++ b/CODE/BT/MUNGA/LINMTRX.TCP @@ -0,0 +1,23 @@ +//===========================================================================// +// File: linmtrx.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the linear matrices // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#include "random.hpp" +// +//########################################################################### +//########################################################################### +// +Logical LinearMatrix::TestClass() +{ + return False; +} + diff --git a/CODE/BT/MUNGA/MATRIX.TCP b/CODE/BT/MUNGA/MATRIX.TCP new file mode 100644 index 0000000..e84d3ca --- /dev/null +++ b/CODE/BT/MUNGA/MATRIX.TCP @@ -0,0 +1,22 @@ +//===========================================================================// +// File: matrix.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the matrix class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + Matrix4x4::TestClass() +{ + DEBUG_STREAM << "Starting Matrix4x4 test...\n"; + Tell(" Matrix4x4::TestClass() is stubbed out!\n"); + return False; +} + diff --git a/CODE/BT/MUNGA/MEMBLOCK.TCP b/CODE/BT/MUNGA/MEMBLOCK.TCP new file mode 100644 index 0000000..fbaaea4 --- /dev/null +++ b/CODE/BT/MUNGA/MEMBLOCK.TCP @@ -0,0 +1,43 @@ +//===========================================================================// +// File: memblock.tst // +// Project: MUNGA Brick: Memory Manager // +// Contents: Test functions for memoryblock classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/23/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + MemoryBlock::TestClass() +{ + DEBUG_STREAM << "Starting MemoryBlock test...\n"; + + Tell(" MemoryBlock::TestClass() is stubbed out!\n"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +Logical + MemoryStack::TestClass() +{ + DEBUG_STREAM << "Starting MemoryStack test...\n"; + + Tell(" MemoryStack::TestClass() is stubbed out!\n"); + return False; +} + diff --git a/CODE/BT/MUNGA/MODE.CPP b/CODE/BT/MUNGA/MODE.CPP new file mode 100644 index 0000000..ce8cc31 --- /dev/null +++ b/CODE/BT/MUNGA/MODE.CPP @@ -0,0 +1,75 @@ +//==========================================================================// +// File: mode.cpp // +// Project: MUNGA Brick: Controls Manager // +// Contents: Interface specification for Controls/Gauges // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 02/13/96 CPB First created // +//--------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include +#pragma hdrstop + +#if !defined(MODE_HPP) +# include +#endif + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//############################################################################ +//############################ ModeManager ############################# +//############################################################################ +ModeManager::ModeManager(ModeMask initial_mask) +{ + Check_Pointer(this); + + modeMask = initial_mask; + + Check_Fpu(); +} + +ModeManager::~ModeManager() +{ + Check(this); + Check_Fpu(); +} + +Logical + ModeManager::TestInstance() const +{ + Check_Fpu(); + return True; +} + +Logical + ModeManager::ModeStringLookup( + const char *name, + ModeMask *returned_value + ) +{ + Check(this); + + // There's only one mode value available at this level. + + if (stricmp(name, "ModeAlwaysActive") == 0) + { + *returned_value = ModeManager::ModeAlwaysActive; + Check_Fpu(); + return True; + } + else + { + *returned_value = (ModeMask) 0; + } + Check_Fpu(); + return False; +} diff --git a/CODE/BT/MUNGA/MOTION.HPP b/CODE/BT/MUNGA/MOTION.HPP new file mode 100644 index 0000000..d4ee506 --- /dev/null +++ b/CODE/BT/MUNGA/MOTION.HPP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: motion.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the position class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MOTION_HPP) +# define MOTION_HPP + +# if !defined(VECTOR3D_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Motion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Motion + { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Motion *); + #endif + + Vector3D + linearMotion; + Vector3D + angularMotion; + + static const Motion + Identity; + + // + // Constructors + // + Motion() + {} + Motion(const Motion& motion); + Motion( + const Vector3D& t, + const Vector3D& q + ) + {Check(&t); Check(&q); linearMotion = t; angularMotion = q;} + + // + // Assignment operators + // + Motion& + operator=(const Motion& p); + + // + // Equality operator + // + Logical + operator==(const Motion&) const; + + // + // Origin motion + // + Motion& + AddScaled( + const Motion& source, + const Motion& delta, + Scalar t + ); + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const Motion& p + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + +#endif diff --git a/CODE/BT/MUNGA/MSSCCPRJ.SCC b/CODE/BT/MUNGA/MSSCCPRJ.SCC new file mode 100644 index 0000000..b337d03 --- /dev/null +++ b/CODE/BT/MUNGA/MSSCCPRJ.SCC @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[MUNGA.MAK] +SCC_Aux_Path = "\\AVATAR\Mungass\VSS" +SCC_Project_Name = "$/Tesla_BT/MUNGA", WOCAAAAA diff --git a/CODE/BT/MUNGA/MTRXSTK.CPP b/CODE/BT/MUNGA/MTRXSTK.CPP new file mode 100644 index 0000000..d6160b0 --- /dev/null +++ b/CODE/BT/MUNGA/MTRXSTK.CPP @@ -0,0 +1,65 @@ +//===========================================================================// +// File: mtrxstk.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for the matrix class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 JMA Initial coding. // +// 12/01/94 JMA Changed Matrix to FullMatrix, based both matrix classes on // +// Matrix44Base // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include + +#if !defined(MTRXSTK_HPP) +# include +#endif + +AffineMatrixStack& + AffineMatrixStack::Concatenate(const AffineMatrix& matrix) +{ + AffineMatrix *old_top = Cast_Object(AffineMatrix*,Peek()); + AffineMatrix *new_top = (AffineMatrix*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +LinearMatrixStack& + LinearMatrixStack::Concatenate(const LinearMatrix& matrix) +{ + LinearMatrix *old_top = Cast_Object(LinearMatrix*,Peek()); + LinearMatrix *new_top = (LinearMatrix*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4Stack& + Matrix4x4Stack::Concatenate(const Matrix4x4& matrix) +{ + Matrix4x4 *old_top = Cast_Object(Matrix4x4*,Peek()); + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4Stack& + Matrix4x4Stack::Concatenate(const AffineMatrix& matrix) +{ + Matrix4x4 *old_top = Cast_Object(Matrix4x4*,Peek()); + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4& + Matrix4x4Stack::Push(const AffineMatrix& matrix) +{ + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + return *new_top = matrix; +} + diff --git a/CODE/BT/MUNGA/MUNGA.HPP b/CODE/BT/MUNGA/MUNGA.HPP new file mode 100644 index 0000000..0481ec5 --- /dev/null +++ b/CODE/BT/MUNGA/MUNGA.HPP @@ -0,0 +1,82 @@ +#if !defined(MUNGA_HPP) +# define MUNGA_HPP +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# if defined(__BCPLUSPLUS__) +# include +# endif + +# if defined(LBE4) +# include +# else +# include +# endif + + enum { + NullExitCodeID = 0, + AbortExitCodeID + }; + +# if !defined(TRACE_HPP) +# include +# endif + +# if !defined(NO_PRECOMPILED_HEADERS) +# if !defined(CSTR_HPP) +# include +# endif + +# if !defined(NAMELIST_HPP) +# include +# endif + +# if !defined(NOTATION_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(VCHAIN_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + +# if !defined(TREE_HPP) +# include +# endif + +# if !defined(HASH_HPP) +# include +# endif + +# if !defined(ORIGIN_HPP) +# include +# endif + +# endif + +#endif diff --git a/CODE/BT/MUNGA/NODE.CPP b/CODE/BT/MUNGA/NODE.CPP new file mode 100644 index 0000000..6c55e27 --- /dev/null +++ b/CODE/BT/MUNGA/NODE.CPP @@ -0,0 +1,52 @@ +//===========================================================================// +// File: node.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of Node class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++, moved ReleaseSocketLink into // +// the virtual data field // +// 11/08/94 ECH Made compatible with BC4.0 // +// 12/01/94 JMA Made compatible with SGI CC // +// 12/12/94 ECH Changed release handler // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(NODE_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Node ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Node::Node(ClassID class_id): + Plug(class_id) +{ +} + +Node::Node(PlugStream *stream): + Plug(stream) +{ +} + +Node::~Node() +{ +} + +void + Node::ReleaseLinkHandler(Socket*, Plug*) +{ +} + + diff --git a/CODE/BT/MUNGA/NORMAL.CPP b/CODE/BT/MUNGA/NORMAL.CPP new file mode 100644 index 0000000..dbc4bd3 --- /dev/null +++ b/CODE/BT/MUNGA/NORMAL.CPP @@ -0,0 +1,69 @@ +//===========================================================================// +// File: normal.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the normal class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(NORMAL_HPP) + #include +#endif + +#if !defined(AFFNMTRX_HPP) + #include +#endif + +// +//############################################################################# +//############################################################################# +// +Normal& + Normal::Multiply_Inverse( + const Normal &Source, + const AffineMatrix &M + ) +{ + Check(this); + Check(&Source); + Check(&M); + + x = Source.x*M(0,0) + Source.y*M(0,1) + Source.z*M(0,2); + y = Source.x*M(1,0) + Source.y*M(1,1) + Source.z*M(1,2); + z = Source.x*M(2,0) + Source.y*M(2,1) + Source.z*M(2,2); + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Normal& + Normal::Multiply( + const Normal &Source, + const AffineMatrix &M + ) +{ + Check(this); + Check(&Source); + Check(&M); + + AffineMatrix m; + m.Invert(M); + return Multiply_Inverse(Source,m); +} + +#if defined(TEST_CLASS) +# include "normal.tcp" +#endif + diff --git a/CODE/BT/MUNGA/NORMAL.TCP b/CODE/BT/MUNGA/NORMAL.TCP new file mode 100644 index 0000000..2d51150 --- /dev/null +++ b/CODE/BT/MUNGA/NORMAL.TCP @@ -0,0 +1,22 @@ +//===========================================================================// +// File: normal.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the normal class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + Normal::TestClass() +{ + DEBUG_STREAM << "Starting Normal Test...\n"; + Tell(" Normal::TestClass() is stubbed out!\n"); + return False; +} + diff --git a/CODE/BT/MUNGA/ORIGIN.TCP b/CODE/BT/MUNGA/ORIGIN.TCP new file mode 100644 index 0000000..9d7ccf4 --- /dev/null +++ b/CODE/BT/MUNGA/ORIGIN.TCP @@ -0,0 +1,67 @@ +//===========================================================================// +// File: origin.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the position class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LINMTRX_HPP) + #include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + Origin::TestClass() +{ + DEBUG_STREAM << "Starting Origin test...\n"; + + Point3D p(1.0f,2.0f,3.0f); + Quaternion q(0.0f, 1.0f, 0.0f, 0.0f); + + Quaternion r; + r = q; + const Origin + a(p,r); + Origin + b; + + Quaternion t; + t = a.angularPosition; + Test( + a.linearPosition == p + && t.x == q.x + && t.w == q.w + ); + + LinearMatrix + m; + + m = a; + b = m; + t = b; + Test( + a.linearPosition == b.linearPosition + && t.y == q.y + ); + + b = Point3D(3.0f,2.0f,1.0f); + p = b; + Test(p == Point3D(3.0f,2.0f,1.0f)); + Quaternion s(1.0f, 0.0f, 0.0f, 0.0f); + b = s; + q = b; + Test(q.x == s.x && q.y == s.y && q.z == s.z && q.w == s.w); + + return True; +} + diff --git a/CODE/BT/MUNGA/POINT2D.HPP b/CODE/BT/MUNGA/POINT2D.HPP new file mode 100644 index 0000000..3efce15 --- /dev/null +++ b/CODE/BT/MUNGA/POINT2D.HPP @@ -0,0 +1,149 @@ +//===========================================================================// +// File: point.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification of the point class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(POINT2D_HPP) +# define POINT2D_HPP + +# if !defined(VECTOR3D_HPP) +# include +# endif + +# if !defined(VECTOR4D_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Point2D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class Point2DOf: + public Vector2DOf + { + public: + // + // Constructors + // + Point2DOf() + {} + Point2DOf( + T x, + T y + ): + Vector2DOf(x,y) + {} + Point2DOf(const Vector2DOf &v): + Vector2DOf(v) + {} + + // + // Assignment operators + // + Point2DOf& operator=(const Vector2DOf& v) + {Vector2DOf::operator=(v); return *this;} + + // + // Math operators + // + Point2DOf& + Negate(const Vector2DOf &v) + {Vector2DOf::Negate(v); return *this;} + + Point2DOf& + Add( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) + {Vector2DOf::Add(v1,v2); return *this;} + Point2DOf& + operator+=(const Vector2DOf& v) + {return Add(*this,v);} + + Point2DOf& + Subtract( + const Point2DOf& p, + const Vector2DOf& v + ) + {Vector2DOf::Subtract(p,v); return *this;} + Point2DOf& + operator-=(const Vector2DOf& v) + {return Subtract(*this,v);} + + float + operator*(const Vector2DOf& v) const + {return Vector2DOf::operator*(v);} + + Point2DOf& + Multiply( + const Point2DOf& p, + float scale + ) + {Vector2DOf::Multiply(p,scale); return *this;} + Point2DOf& + operator*=(float value) + {return Multiply(*this,value);} + + Point2DOf& + Multiply( + const Point2DOf& p, + const Vector2DOf& v + ) + {Vector2DOf::Multiply(p,v); return *this;} + Point2DOf& + operator*=(const Vector2DOf &v) + {return Multiply(*this,v);} + + Point2DOf& + Divide( + const Vector2DOf& v, + float scale + ) + {Vector2DOf::Divide(v,scale); return *this;} + Point2DOf& + operator/=(float value) + {return Divide(*this,value);} + + Point2DOf& + Divide( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) + {Vector2DOf::Divide(v1,v2); return *this;} + Point2DOf& + operator/=(const Vector2DOf &v) + {return Divide(*this,v);} + + // + // Miscellaneous functions + // + Point2DOf& + Combine( + const Vector2DOf& v1, + float t1, + const Vector2DOf& v2, + float t2 + ) + {Vector2DOf::Combine(v1,t1,v2,t2); return *this;} + + // + // Template support functions + // + Point2DOf& + Lerp( + const Vector2DOf& v1, + const Vector2DOf& v2, + float t + ) + {Vector2DOf::Lerp(v1,v2,t); return *this;} + }; + +#endif + diff --git a/CODE/BT/MUNGA/RANDOM.HPP b/CODE/BT/MUNGA/RANDOM.HPP new file mode 100644 index 0000000..9e03af1 --- /dev/null +++ b/CODE/BT/MUNGA/RANDOM.HPP @@ -0,0 +1,74 @@ +//===========================================================================// +// File: random.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for the random number generator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/93 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RANDOM_HPP) +# define RANDOM_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Random ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class RandomGenerator SIGNATURED + { + private: + static int + Numbers[250]; // the random number table + static int + Index; // the current entry within the table + + static void + Init(); + + static int + GetRandomInt(); + + public: + RandomGenerator() + {if (Index == -1) Init();} + + // + //------------------------ + // Random number functions + //------------------------ + // + int + GetInt() // returns 0 .. RAND_MAX + {return GetRandomInt();} + operator Scalar(); // returns 0.0f <= x < 1.0f + int // returns 0 .. Range-1 + operator ()(int Range); + + static Logical + TestClass(); + }; + + extern RandomGenerator Random; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Die ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Die SIGNATURED + { + private: + int + highestRandom, // the highest random number giving a uniform dist. + dieSides; // the number of sides on the die (starting from 1) + + public: + Die(int sides); + operator int(); // returns 1 .. dieSides + }; + +#endif diff --git a/CODE/BT/MUNGA/RANDOM.TCP b/CODE/BT/MUNGA/RANDOM.TCP new file mode 100644 index 0000000..0e957d0 --- /dev/null +++ b/CODE/BT/MUNGA/RANDOM.TCP @@ -0,0 +1,44 @@ +//===========================================================================// +// File: random.tst // +// Project: MUNGA Brick: Math Library // +// Contents: test function for the random number generator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/93 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + RandomGenerator::TestClass() +{ + DEBUG_STREAM << "Starting Random test...\n"; + +#define RANDOM_TEST_COUNT 10000 + + int i; + for (i=0; i= 0.0f && r < 1.0f,r); + } + + int array[10]; + for (i = 0; i= 0 && r < ELEMENTS(array)); + ++array[r]; + } + + return True; +} + diff --git a/CODE/BT/MUNGA/RAY.HPP b/CODE/BT/MUNGA/RAY.HPP new file mode 100644 index 0000000..3406a54 --- /dev/null +++ b/CODE/BT/MUNGA/RAY.HPP @@ -0,0 +1,101 @@ +//########################################################################### +// +// $Workfile: RAY.HPP $ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Copyright(c) 1993 J. M. Albertson - All Rights Reserved +// +//########################################################################### + +#if !defined(RAY_HPP) +# define RAY_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + +# if !defined(UNITVEC_HPP) +# include +# endif + + class Plane; + class Sphere; + class Cylinder; + class Cone; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ray ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Ray SIGNATURED + { + public: + Point3D + origin; + UnitVector + direction; + + Ray() + {} + Ray( + const Point3D &origin, + const UnitVector &direction + ): + origin(origin), + direction(direction) + {} + + // + // Ray projection functions + // + void + Project( + Scalar length, + Point3D *result + ); + Scalar + LengthToClosestPointTo(const Point3D &point); + void + ClosestPointTo( + const Point3D &point, + Point3D *result + ) + { + Check(this); Check(result); Check(&point); + Project(LengthToClosestPointTo(point),result); + } + + // + // Ray intersection functions + // + Scalar + DistanceTo( + const Plane &plane, + Scalar *product + ) const; + Scalar + DistanceTo( + const Sphere &sphere, + Scalar *penetration + ) const; + + // + // Test support + // + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + extern Scalar + Find_Closest_Approach( + const Point3D& origin1, + const Vector3D& velocity1, + Point3D *result1, + const Point3D& origin2, + const Vector3D& velocity2, + Point3D *result2, + Scalar *time, + Logical *constant + ); + +#endif diff --git a/CODE/BT/MUNGA/RAY.TCP b/CODE/BT/MUNGA/RAY.TCP new file mode 100644 index 0000000..5ff72d9 --- /dev/null +++ b/CODE/BT/MUNGA/RAY.TCP @@ -0,0 +1,22 @@ +//===========================================================================// +// File: ray.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the ray class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/25/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + Ray::TestClass() +{ + DEBUG_STREAM << "Starting Ray test...\n"; + Tell(" Ray::TestClass is stubbed out!\n"); + return True; +} + diff --git a/CODE/BT/MUNGA/RECT2D.HPP b/CODE/BT/MUNGA/RECT2D.HPP new file mode 100644 index 0000000..834b52c --- /dev/null +++ b/CODE/BT/MUNGA/RECT2D.HPP @@ -0,0 +1,90 @@ +//===========================================================================// +// File: Rect2D.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for two-dimensional rectangle class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 2/01/95 CPB Initial coding (started from Vector2D.hh) // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RECT2D_HPP) +# define RECT2D_HPP + +# if !defined(VECTOR2D_HPP) +# include +# endif + + // Note that the coordinate system used here is such that + // (0,0) is in the lower left corner. + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rectangle2D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Rectangle2D SIGNATURED + { + public: + Vector2DOf bottomLeft, topRight; + + Rectangle2D(); + Rectangle2D(Vector2DOf bl, Vector2DOf tr); + Rectangle2D(int x1, int y1, int x2, int y2); + ~Rectangle2D() + {} + + Logical + operator==(const Rectangle2D& r) const + {return ((bottomLeft == r.bottomLeft) && (topRight == r.topRight));} + Logical + operator!=(const Rectangle2D& r) const + {return ((bottomLeft != r.bottomLeft) || (topRight != r.topRight));} + + void + Union( + const Rectangle2D& r1, + const Rectangle2D& r2 + ); + + void + Intersection( + const Rectangle2D& r1, + const Rectangle2D& r2 + ); + + void + MakeEmpty() + { + Check(this); + bottomLeft.x = 1; + topRight.x = 0; + } + + Logical + IsEmpty() const + { + if ((bottomLeft.x > topRight.x) || (bottomLeft.y > topRight.y)) + { + return True; + } + else + { + return False; + } + } + + + friend ostream& + operator<<( + ostream& stream, + const Rectangle2D& r + ); + + Logical + TestInstance() const; + + static Logical + TestClass(); + }; +#endif diff --git a/CODE/BT/MUNGA/RENDERER.TCP b/CODE/BT/MUNGA/RENDERER.TCP new file mode 100644 index 0000000..9480cee --- /dev/null +++ b/CODE/BT/MUNGA/RENDERER.TCP @@ -0,0 +1,57 @@ +//===========================================================================// +// File: renderer.tst // +// Project: MUNGA Brick: Renderer Manager // +// Contents: Interface specification Renderer and Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "renderer.thp" + +TestRenderer::TestRenderer(): + Renderer( + 30.0f, + MaxRendererComplexity, + DefaultRendererPriority, + VisualInterestType, + DefaultInterestDepth + ) +{ +} + +TestRenderer::~TestRenderer() +{ +} + +Logical + TestRenderer::TestInstance() const +{ + Renderer::TestInstance(); + return True; +} + +void + TestRenderer::ExecuteImplementation( + RendererComplexity, + RendererOrigin::InterestingEntityIterator *interesting_entity_iterator + ) +{ + Check(interesting_entity_iterator); + + // + // HACK - Just step through the entities + // + Entity *entity; + + while ((entity = interesting_entity_iterator->ReadAndNext()) != NULL) + { + Check(entity); + } +} + diff --git a/CODE/BT/MUNGA/RENDERER.THP b/CODE/BT/MUNGA/RENDERER.THP new file mode 100644 index 0000000..6cd0f53 --- /dev/null +++ b/CODE/BT/MUNGA/RENDERER.THP @@ -0,0 +1,48 @@ +//===========================================================================// +// File: tstrend.hh // +// Project: MUNGA Brick: Renderer Manager // +// Contents: Interface specification Renderer and Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(TSTREND_THP) +# define TSTREND_THP + +# if !defined(RENDERER_HPP) +# include +# endif + + class TestRenderer: + public Renderer + { + public: + TestRenderer(); + ~TestRenderer(); + + Logical + TestInstance() const; + + private: + void + LoadMissionImplementation(Mission*) {}; + void + ShutdownImplementation() {}; + void + SuspendImplementation() {}; + void + ResumeImplementation() {}; + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + }; + +#endif diff --git a/CODE/BT/MUNGA/RESVER.HPP b/CODE/BT/MUNGA/RESVER.HPP new file mode 100644 index 0000000..702a834 --- /dev/null +++ b/CODE/BT/MUNGA/RESVER.HPP @@ -0,0 +1,7 @@ +#if !defined(RESVER_HPP) +# define RESVER_HPP + +# define RESOURCE_FORMAT_VERSION 1 + +#endif + diff --git a/CODE/BT/MUNGA/SCALAR.CPP b/CODE/BT/MUNGA/SCALAR.CPP new file mode 100644 index 0000000..abc759e --- /dev/null +++ b/CODE/BT/MUNGA/SCALAR.CPP @@ -0,0 +1,246 @@ +//===========================================================================// +// File: scalar.cpp // +// Project: MUNGA Brick: None assigned - coding styles, etc. // +// Contents: Base information used by all MUNGA source files // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SCALAR_HPP) + #include +#endif + +int + Round(Scalar value) +{ + int whole_part = floor(value); + Scalar fractional_part = value - whole_part; + if (fractional_part >= 0.5) + { + return whole_part + 1; + } + else + { + return whole_part; + } +} + + + +void + Find_Roots( + Scalar a, // a*x*x + b*x + c = 0 + Scalar b, + Scalar c, + Scalar *center, + Scalar *range + ) +{ + + // + //--------------------------------- + // See if the quadratic is solvable + //--------------------------------- + // + *range = b*b - 4.0f*a*c; + if (*range < 0.0f || Small_Enough(a)) + { + *range = -1.0f; + } + + else + { + // + //--------------------------- + // Solve the single root case + //--------------------------- + // + a *= 2.0f; + *center = -b / a; + if (*range < SMALL) + { + *range = 0.0f; + } + + // + //-------------------------- + // Find the two-root extents + //-------------------------- + // + else + { + *range = Sqrt(*range); + *range /= a; + } + } +} + +static void + Verify_Arguments( + const char *str, + void *value + ) +{ + if (str == NULL) + { + Fail("Convert_From_Ascii - str == NULL"); + } + if (value == NULL) + { + Fail("Convert_From_Ascii - value == NULL"); + } + if (isalpha(*str)) + { + DEBUG_STREAM << "Convert_From_Ascii - str == " << str << "\n"; + Fail("Convert_From_Ascii - isalpha(*str)"); + } +} + +void + Convert_From_Ascii( + const char *str, + char *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = (char)atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + unsigned char *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = (unsigned char)atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + int *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + unsigned int *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + long *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atol(str); +} + +void + Convert_From_Ascii( + const char *str, + unsigned long *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atol(str); +} + +void + Convert_From_Ascii( + const char *str, + Scalar *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atof(str); +} + + diff --git a/CODE/BT/MUNGA/SCALAR.HPP b/CODE/BT/MUNGA/SCALAR.HPP new file mode 100644 index 0000000..089f7f3 --- /dev/null +++ b/CODE/BT/MUNGA/SCALAR.HPP @@ -0,0 +1,72 @@ +//===========================================================================// +// File: scalar.hpp // +// Project: MUNGA Brick: None assigned - coding styles, etc. // +// Contents: Base information used by all MUNGA source files // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SCALAR_HPP) +# define SCALAR_HPP + +# if !defined(MEMSTRM_HPP) +# include +# endif + +# if !defined(M_PI) +# define M_PI 3.14159265358979323846 +# endif + + typedef float Scalar; + +# define PI ((Scalar)(M_PI)) +# define PI_OVER_2 ((Scalar)(M_PI/2.0)) +# define PI_OVER_3 ((Scalar)(M_PI/3.0)) +# define PI_OVER_4 ((Scalar)(M_PI/4.0)) +# define PI_OVER_6 ((Scalar)(M_PI/6.0)) +# define TWO_PI ((Scalar)(2.0*M_PI)) +# define DEG_PER_RAD ((Scalar)(180.0/M_PI)) +# define RAD_PER_DEG ((Scalar)(M_PI/180.0)) + + inline Scalar Lerp(Scalar a, Scalar b, Scalar t) + {return a*(1.0f - t) + b*t;} + inline Logical Small_Enough(Scalar x,Scalar e=SMALL) + {return fabs(x) <= e;} + inline Logical Close_Enough(Scalar x,Scalar y,Scalar e=SMALL) + {return fabs(x-y) <= e;} + + int + Round(Scalar value); + + void + Find_Roots( + Scalar a, // a*x*x + b*x + c = 0 + Scalar b, + Scalar c, + Scalar *center, + Scalar *range + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + Scalar *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const Scalar *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + void + Convert_From_Ascii(const char *str, Scalar *value); + + +#endif + diff --git a/CODE/BT/MUNGA/SCNROLE.HPP b/CODE/BT/MUNGA/SCNROLE.HPP new file mode 100644 index 0000000..446e051 --- /dev/null +++ b/CODE/BT/MUNGA/SCNROLE.HPP @@ -0,0 +1,175 @@ +//===========================================================================// +// File: scnrole.hpp // +// Project: MUNGA // +// Contents: Scenario Mission Specific Data // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/9/96 JM initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined (SCNROLE_HPP) +# define SCNROLE_HPP + +# if !defined (NODE_HPP) +# include +# endif + +# if !defined (CSTR_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(SCALAR_HPP) +# include +# endif + + class NotationFile; + +//############################################################################## +//##################### ScenarioRole::ModelResource ###################### +//############################################################################## + + struct ScenarioRole__ModelResource + { + Scalar + killBonus, + specialCaseDeathPenalty, + damageReceivedModifier, + damageInflictedModifier, + damageBias, + friendlyFirePenalty; + + int + returnFromDeath; + }; + +//########################################################################### +//##################### Class ScenarioRole ############################# +//########################################################################### + +class ScenarioRole : + public Node +{ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Score Support + // + public: + + Scalar + CalcDamageReceivedScore(const Scalar &damage_received); + + protected: + + Scalar + damageInflictedModifier, + damageReceivedModifier, + friendlyFirePenalty, + damageBias, + killBonus, + specialCaseDeathPenalty; + + + CString + roleName; + + int + returnFromDeath; + + public: + + const int + GetReturnFromDeath() + { Check(this); return returnFromDeath; } + + Scalar + GetDamageInflictedModifier() const + { Check(this); return damageInflictedModifier; } + + Scalar + GetDamageReceivedModifier() const + { Check(this); return damageReceivedModifier; } + + Scalar + GetFriendlyFirePenalty() const + { Check(this); return friendlyFirePenalty; } + + Scalar + GetDamageBias() const + { Check(this); return damageBias; } + + Scalar + GetKillBonus() const + { Check(this); return killBonus; } + + + Scalar + GetSpecialCaseDeathPenalty() const + { Check(this); return specialCaseDeathPenalty; } + + + CString + GetRoleName() const + {Check(this); return roleName; } + + void + SetDamageInflictedModifier(const Scalar &value) + { Check(this); damageInflictedModifier = value; } + + void + SetDamageReceivedModifier(const Scalar value) + { Check(this); damageReceivedModifier = value; } + + void + SetFriendlyFirePenalty(const Scalar &value) + { Check(this); friendlyFirePenalty = value; } + + void + SetDamageBias(const Scalar &value) + { Check(this); damageBias = value; } + + void + SetKillBonus(const Scalar &value) + { Check(this); killBonus = value; } + + void + SetSpecialCaseDeathPenalty(const Scalar &value) + { Check(this); specialCaseDeathPenalty = value; } + + void + SetReturnFromDeath(const int &value) + { Check(this); returnFromDeath = value ; } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction + + public: + + typedef ScenarioRole__ModelResource ModelResource; + + ScenarioRole( + const CString &role_name, + const CString &model_file + ); + + ScenarioRole(const CString &role_name); + + ~ScenarioRole(); + + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model = NULL + ); +}; +#endif diff --git a/CODE/BT/MUNGA/SET.CPP b/CODE/BT/MUNGA/SET.CPP new file mode 100644 index 0000000..8fb21f7 --- /dev/null +++ b/CODE/BT/MUNGA/SET.CPP @@ -0,0 +1,165 @@ +//===========================================================================// +// File: set.cpp // +// Project: MUNGA Brick: Connection Engine // +// Contents: Implementation of Sets and useful set operations // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 GDU Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996 Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SET_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Set +//############################################################################# +// +Set::Set(Node *node): + Socket(node), + contents(NULL) +{ + +} + + + + +// +//############################################################################# +// ~Set +//############################################################################# +// +Set::~Set() +{ + SetReleaseNode(NULL); + if (contents) + { + delete contents; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Set::TestInstance() const +{ + Socket::TestInstance(); + Check(contents); + return True; +} + + +// +//############################################################################# +// Union +// +// Merge contents of this with rhs. Items that occur in either set are placed +// in the resulting set, with no duplication. It is assumed that both operands +// are proper sets, ie. they contain no duplicates. +//############################################################################# +// + +Set + Set::Union(const Set &) const +{ + Check(this); + + + Set result(NULL); + + return result; +} + + +// +//############################################################################# +// Intersection +// +// Merge contents of this with rhs. Items that occur in both sets are placed +// only once in the resulting set. It is assumed that both operands are proper +// sets, ie. they contain no duplicates. +// +// This implementation of set intersection is dumb and slow. +//############################################################################# +// + +Set + Set::Intersection(const Set &rhs) const +{ + Check(this); + Check(rhs); + + // Contents iterator is a SetIterator and not a ChainIterator in order to + // have access to the ChainIterator::ReadAndNextImplentation. + // We circumvent encapsulation protections by declaring Set a friend of SetIterator + // (which derives from ChainIterator). Set is not a friend of ChainIterator. + + SetIterator contents_iterator(contents); + + // Casting away const is safe since our local iterator is not going to insert or + // remove items from rhs. + SetIterator rhs_iterator((Set *) &rhs); + Plug *lhs_plug; + Plug *rhs_plug; + Set result(NULL); + + + while ((lhs_plug = Cast_Object(Plug *, contents_iterator.ReadAndNextImplementation())) != NULL) + { + while ((rhs_plug = Cast_Object(Plug *,rhs_iterator.ReadAndNextImplementation())) != NULL) + { + if (lhs_plug == rhs_plug) + { + result.AddImplementation(lhs_plug); + } + } + } + return result; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// SetIterator +//############################################################################# +// +SetIterator::SetIterator(Set *set): + ChainIterator(set->contents) +{ + Check(set); +} + +SetIterator::SetIterator(const SetIterator &iterator): + ChainIterator(Cast_Object(Chain*, (Cast_Object(Set *,iterator.socket)->contents))) +{ + Check(&iterator); +} + +SetIterator::SetIterator(Chain *chain): + ChainIterator(chain) +{ + Check(chain); +} + +SetIterator::~SetIterator() +{ +} + + + + diff --git a/CODE/BT/MUNGA/SFESKT.HPP b/CODE/BT/MUNGA/SFESKT.HPP new file mode 100644 index 0000000..a68a0b5 --- /dev/null +++ b/CODE/BT/MUNGA/SFESKT.HPP @@ -0,0 +1,86 @@ +//===========================================================================// +// File: sfeskt.hh // +// Project: MUNGA Brick: Connection Engine // +// Contents: Interface definition for safe socket class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC and merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release mechanism // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SFESKT_HPP) +# define SFESKT_HPP + +# if !defined(SOCKET_HPP) +# include +# endif + + class SafeIterator; + + typedef int IteratorMemo; + + enum + { + PlugAdded = 0, + PlugRemoved, + NextSafeSocketMemo + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SafeSocket ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SafeSocket: + public Socket + { + friend class SafeIterator; + + public: + ~SafeSocket(); + Logical + TestInstance() const; + + protected: + SafeSocket(Node *node); + + void + SendIteratorMemo( + IteratorMemo memo, + void *content + ); + + private: + SafeIterator *iteratorHead; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SafeIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SafeIterator: + public SocketIterator + { + friend class SafeSocket; + + public: + ~SafeIterator(); + Logical + TestInstance() const; + + protected: + SafeIterator(SafeSocket *safeSocket); + + private: + virtual void + ReceiveMemo( + IteratorMemo memo, + void *content + ); + + SafeIterator *nextIterator; + SafeIterator *prevIterator; + }; + +#endif diff --git a/CODE/BT/MUNGA/SPHERE.CPP b/CODE/BT/MUNGA/SPHERE.CPP new file mode 100644 index 0000000..5546312 --- /dev/null +++ b/CODE/BT/MUNGA/SPHERE.CPP @@ -0,0 +1,55 @@ +//=======================================================================// +// File: sphere.cpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#include +#pragma hdrstop + +#if !defined(SPHERE_HPP) +# include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + Sphere::Contains(const Point3D &A_Point) const +{ + Vector3D + diff; + + diff.Subtract(center,A_Point); + return radius*radius >= diff.LengthSquared(); +} + +// +//########################################################################### +//########################################################################### +// +Logical + Sphere::Intersects(const Sphere &sphere) const +{ + Vector3D temp; + Scalar r; + + r = radius + sphere.radius; + temp.Subtract(center, sphere.center); + return temp.LengthSquared() <= r*r; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator<<(ostream& Stream, const Sphere &A_Sphere) +{ + Stream << "\n\tSphere Centerpoint: " << A_Sphere.center; + return Stream << "\n\tRadius: " << A_Sphere.radius; +} diff --git a/CODE/BT/MUNGA/SPHERE.HPP b/CODE/BT/MUNGA/SPHERE.HPP new file mode 100644 index 0000000..f8db86d --- /dev/null +++ b/CODE/BT/MUNGA/SPHERE.HPP @@ -0,0 +1,62 @@ +//=======================================================================// +// File: sphere.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainments, // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(SPHERE_HPP) +# define SPHERE_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + + class Plane; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sphere ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Sphere SIGNATURED + { + public: + Point3D + center; + Scalar + radius; + + Sphere() + {} + Sphere( + const Point3D &A_Point, + Scalar Radius + ): + center(A_Point), + radius(Radius) + {} + Sphere( + Scalar X, + Scalar Y, + Scalar Z, + Scalar Radius + ): + center(X,Y,Z), + radius(Radius) + {} + + // + // Intersection functions + // + Logical + Contains(const Point3D &point) const; + Logical + Intersects(const Sphere &sphere) const; + Logical + Intersects(const Plane &plane) const; + + friend ostream& + operator<<(ostream& Stream, const Sphere &A_Sphere); + }; + +#endif diff --git a/CODE/BT/MUNGA/SPLINE.HPP b/CODE/BT/MUNGA/SPLINE.HPP new file mode 100644 index 0000000..e3a0def --- /dev/null +++ b/CODE/BT/MUNGA/SPLINE.HPP @@ -0,0 +1,43 @@ +#if !defined(SPLINE_HPP) +# define SPLINE_HPP + +# if !defined(AFFNMTRX_HPP) +# include +# endif + + class CubicCurve { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile CubicCurve *); + #endif + + CubicCurve( // Hermite form + const Point3D& p1, + const Vector3D& r1, + const Point3D& p4, + const Vector3D& r4 + ); + CubicCurve( // Bezier form + const Point3D& p1, + const Point3D& p2, + const Point3D& p3, + const Point3D& p4 + ); + + void + Evaluate( + Scalar t, + Point3D *p, + Vector3D *v + ); + + Logical + TestInstance() const; + + protected: + AffineMatrix + basisMatrix; + }; + +#endif \ No newline at end of file diff --git a/CODE/BT/MUNGA/SPOOLER.HPP b/CODE/BT/MUNGA/SPOOLER.HPP new file mode 100644 index 0000000..976f8c7 --- /dev/null +++ b/CODE/BT/MUNGA/SPOOLER.HPP @@ -0,0 +1,76 @@ +#if !defined(SPOOLER_HPP) +# define SPOOLER_HPP + +# if !defined(APPMGR_HPP) +# include +# endif + + //########################################################################## + //########################### SpoolFile ################################ + //########################################################################## + + class SpoolFile: + public MemoryStream + { + public: + SpoolFile( + void *stream_start, + size_t stream_size, + size_t initial_offset=0 + ); + SpoolFile(SpoolFile& spool); + ~SpoolFile(); + + enum SpoolState { + Empty, + Spooling, + Stored, + Playing + }; + SpoolState + spoolState; + + void + SaveAs(const char *name); + void + Read(const char *name); + + void + SpoolPacket(NetworkPacket *packet); + NetworkPacket* + NextPacket(); + }; + + //########################################################################## + //############## MissionReviewApplicationManager ##################### + //########################################################################## + + class MissionReviewApplicationManager: + public ApplicationManager + { + public: + MissionReviewApplicationManager( + Scalar frame_rate, + int spool_count, + size_t spool_size + ); + ~MissionReviewApplicationManager(); + + SpoolFile* + GetEmptySpoolFile(); + SpoolFile* + GetStoredSpoolFile(); + void + StoreSpoolFile(SpoolFile *spool_file); + void + ReleaseSpoolFile(SpoolFile *spool_file); + + protected: + int spoolCount; + SpoolFile **spoolFiles; + char **spoolBuffers; + size_t spoolSize; + }; + +#endif + diff --git a/CODE/BT/MUNGA/SRTSKT.CPP b/CODE/BT/MUNGA/SRTSKT.CPP new file mode 100644 index 0000000..76c0305 --- /dev/null +++ b/CODE/BT/MUNGA/SRTSKT.CPP @@ -0,0 +1,75 @@ +//===========================================================================// +// File: srtskt.cc // +// Project: MUNGA Brick: Connection Engine // +// Contents: Implementation of sorted socket class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/02/94 ECH Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SRTSKT_HPP) + #include +#endif + +SortedSocket::SortedSocket( + Node *node, + Logical has_unique_entries +): + SafeSocket(node) +{ + hasUniqueEntries = has_unique_entries; +} + +SortedSocket::~SortedSocket() +{ +} + +void + SortedSocket::AddValueImplementation( + Plug*, + const void* + ) +{ + Fail("SortedSocket::AddValueImplementation - Should never reach here"); +} + +Plug* + SortedSocket::FindImplementation(const void*) +{ + Fail("SortedSocket::FindImplementation - Should never reach here"); + return NULL; +} + +SortedIterator::SortedIterator(SortedSocket *sortedSocket): + SafeIterator(sortedSocket) +{ +} + +SortedIterator::~SortedIterator() +{ +} + +Plug* + SortedIterator::FindImplementation(const void*) +{ + Fail("SortedIterator::FindImplementation - Should never reach here"); + return NULL; +} + +void* + SortedIterator::GetValueImplementation() +{ + Fail("SortedIterator::GetValueImplementation - Should never reach here"); + return NULL; +} + diff --git a/CODE/BT/MUNGA/SRTSKT.HPP b/CODE/BT/MUNGA/SRTSKT.HPP new file mode 100644 index 0000000..6ad2169 --- /dev/null +++ b/CODE/BT/MUNGA/SRTSKT.HPP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: srtskt.hh // +// Project: MUNGA Brick: Connection Engine // +// Contents: Interface definition for sorted socket class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/02/94 ECH Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SRTSKT_HPP) +# define SRTSKT_HPP + +# if !defined(SFESKT_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedSocket ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SortedSocket: + public SafeSocket + { + public: + ~SortedSocket(); + + void + AddValuePlug( + Plug *plug, + const void *value + ) + {AddValueImplementation(plug, value);} + + Plug* + FindPlug(const void *value) + {return FindImplementation(value);} + + protected: + SortedSocket( + Logical has_unique_entries = True + ); + SortedSocket( + Node *node, + Logical has_unique_entries = True + ); + + Logical + HasUniqueEntries() + {return hasUniqueEntries;} + + virtual void + AddValueImplementation( + Plug *plug, + const void *value + ); + + virtual Plug* + FindImplementation(const void *value); + + private: + Logical + hasUniqueEntries; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SortedIterator: + public SafeIterator + { + public: + ~SortedIterator(); + + virtual Plug* + FindImplementation(const void *value); + + virtual void* + GetValueImplementation(); + + protected: + SortedIterator(SortedSocket *sortedSocket); + }; + +#endif diff --git a/CODE/BT/MUNGA/TEAM.HPP b/CODE/BT/MUNGA/TEAM.HPP new file mode 100644 index 0000000..6755941 --- /dev/null +++ b/CODE/BT/MUNGA/TEAM.HPP @@ -0,0 +1,197 @@ +//===========================================================================// +// File: team.hpp // +// Project: MUNGA // +// Contents: Team Specifications // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/96 JM initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined (TEAM_HPP) +# define TEAM_HPP + +# if !defined (ENTITY_HPP) +# include +# endif + + //########################################################################## + //################# Team__MakeMessage ########################## + //########################################################################## + + class Team__MakeMessage : + public Entity::MakeMessage + { + public: + + char + teamName[64]; + + int + initialScore; + + + + Team__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + char *team_name + ) : + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ) + { + Str_Copy(teamName, team_name, sizeof(teamName)); + } + + }; + //########################################################################## + //################# Team__ScoreMessage ########################## + //########################################################################## + + class Team__ScoreMessage : + public Entity::Message + { + public: + + Scalar + scoreAward; + + Team__ScoreMessage( + Receiver::MessageID message_ID, + size_t length, + Scalar score + ): + Entity::Message(message_ID, length), + scoreAward(score) + {} + }; + //########################################################################## + //######################## CLASS Team ################################ + //########################################################################## + class Team : + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation + ClassDerivations; + + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + + public: + + enum { + ScoreMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef Team__ScoreMessage ScoreMessage; + + void + ScoreMessageHandler(ScoreMessage *message); + + private: + + static const HandlerEntry MessageHandlerEntries[]; + + protected: + + static MessageHandlerSet MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + private: + + static const IndexEntry + AttributePointers[]; + + protected: + + static AttributeIndexSet + AttributeIndex; + + public: + + enum { + TeamNameAttributeID = Entity::NextAttributeID, + TeamScoreAttributeID, + NextAttributeID + }; + + char + teamName[64]; + + Scalar + teamScore; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + typedef void + (Team::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + virtual void + TeamSimulation(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction Support + // + public: + + typedef Team__MakeMessage MakeMessage; + + Team( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + + ~Team(); + + Logical + TestInstance() const; + + static Team* + Make(MakeMessage *creation_message); + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + }; +#endif diff --git a/CODE/BT/MUNGA/TESTCLAS.HPP b/CODE/BT/MUNGA/TESTCLAS.HPP new file mode 100644 index 0000000..811ea3c --- /dev/null +++ b/CODE/BT/MUNGA/TESTCLAS.HPP @@ -0,0 +1,137 @@ +//===========================================================================// +// File: testclas.hh // +// Project: MUNGA Brick: Dynamic Dispatch, Event and Journalling // +// Contents: defines test classes for use by Dispatch and Events // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/03/94 JMA Initial coding. // +// 11/05/94 JMA Made compatible with GNU C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(TESTCLAS_HPP) +# define TESTCLAS_HPP) + +# if !defined(RECEIVER_HPP) +# include +# endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Alpha ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Alpha: + public Receiver +{ +protected: + static SharedData + DefaultData; + +public: + int + x; + + enum { + message0ID = Receiver::NextMessageID, + message1ID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Alpha( + ClassID class_ID = TrivialReceiverClassID, + SharedData &vdata = DefaultData); + ~Alpha(); + + void + Method0Handler(Message*); + void + Method1Handler(Message*); + + inline void Method0() + {Message m(message0ID,sizeof(Message)); Dispatch(&m);} + inline void Method1() + {Message m(message1ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Beta ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Beta: + public Alpha +{ +protected: + static SharedData + DefaultData; + +public: + enum { + message2ID=Alpha::NextMessageID, + message3ID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Beta( + ClassID class_id = TrivialReceiverClassID, + SharedData &vdata = DefaultData + ); + ~Beta(); + + void + Method1aHandler(Message*); + void + Method2Handler(Message*); + void + Method3Handler(Message*); + + inline void Method1() + {Message m(message1ID,sizeof(Message)); Dispatch(&m);} + inline void Method2() + {Message m(message2ID,sizeof(Message)); Dispatch(&m);} + inline void Method3() + {Message m(message3ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Gamma ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Gamma: + public Beta +{ +public: + enum { + message4ID=Beta::NextMessageID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Gamma(); + ~Gamma(); + + void + Method4Handler(Message*); + + inline void Method4() + {Message m(message4ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; + +protected: + static SharedData + DefaultData; +}; + +#endif diff --git a/CODE/BT/MUNGA/TIME.TCP b/CODE/BT/MUNGA/TIME.TCP new file mode 100644 index 0000000..6fcba5b --- /dev/null +++ b/CODE/BT/MUNGA/TIME.TCP @@ -0,0 +1,100 @@ +//===========================================================================// +// File: time.tst // +// Project: MUNGA Brick: Time Manager // +// Contents: Test stuff for time // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/24/94 JMA Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + Time::TestClass() +{ + DEBUG_STREAM << "Starting Time test...\n"; + + Time + a, + b, + c; + Scalar f; + long + t; + + // + //---------------- + // Test assignment + //---------------- + // + a = 1.0f; + b = 2.0f; + c = Null; + + c = a; + Test(a <= c); + Test(a >= c); + + c = 1.0f; + Test(c <= a); + Test(c >= a); + + c = b.ticks; + Test(c <= b); + Test(c >= b); + + // + //---------------------- + // Test time comparators + //---------------------- + // + Test(a < b); + Test(a <= b); + Test(b > a); + Test(b >= a); + + // + //------------- + // Test casting + //------------- + // + f = c; + Test(Close_Enough(f,2.0f)); + t = a; + Test(t == a.ticks); + + // + //-------------------- + // Test math functions + //-------------------- + // + c = a; + c += 1.0f; + Test(c.ticks == b.ticks); + c -= a; + Test(c.ticks == a.ticks); + + c = b; + c -= 1.0f; + Test(c.ticks == a.ticks); + c += a; + Test(c.ticks == b.ticks); + + // + // This test checks to see if the Scalar value is within the resolution + // of half a tick + // + f = b - a; + Test(Close_Enough(f, 1.0f, 0.5f * (1.0f / SystemClock::ticksPerSecond))); + return True; +} diff --git a/CODE/BT/MUNGA/TIMESTUB.CPP b/CODE/BT/MUNGA/TIMESTUB.CPP new file mode 100644 index 0000000..056db60 --- /dev/null +++ b/CODE/BT/MUNGA/TIMESTUB.CPP @@ -0,0 +1,56 @@ +//===========================================================================// +// File: time.cc // +// Project: MUNGA Brick: Time Manager // +// Contents: Implementation details of the Time Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 10/24/94 JMA Added Lester's IBM RTC code in as SystemClock class // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(TIME_HPP) + #include +#endif + +//############################################################################# +//########################### System Clock ############################## +//############################################################################# + +SystemClock + SystemClock::timer; +Scalar + SystemClock::ticksPerSecond = 1000.0f; + +long + SystemClock::GetRTC() +{ + static long time=0L; + return time++; +} + +SystemClock::SystemClock() +{ + pauseStart = 0L; + pauseTime = 0L; +} + +void + SystemClock::Shutdown() +{ +} + +float + Get_Frame_Percent_Used() +{ + return 0.5f; +} + diff --git a/CODE/BT/MUNGA/TRACSTUB.CPP b/CODE/BT/MUNGA/TRACSTUB.CPP new file mode 100644 index 0000000..fb75f71 --- /dev/null +++ b/CODE/BT/MUNGA/TRACSTUB.CPP @@ -0,0 +1,38 @@ +#include +#pragma hdrstop + +#if !defined(HEAP_HPP) + #include +#endif + +void* + Get_Caller(int) +{ + return NULL; +} + +size_t + UserHeap::GetMainHeapInitialSize() +{ + return 0x200000; +} + +#if defined(USE_ACTIVE_PROFILE) + + void + BitTrace::SetLineImplementation(Byte) + { + } + + void + BitTrace::ClearLineImplementation(Byte) + { + } + + Logical + BitTrace::IsLineValidImplementation(Byte) + { + return True; + } + +#endif diff --git a/CODE/BT/MUNGA/UNITVEC.CPP b/CODE/BT/MUNGA/UNITVEC.CPP new file mode 100644 index 0000000..53eecff --- /dev/null +++ b/CODE/BT/MUNGA/UNITVEC.CPP @@ -0,0 +1,66 @@ +//===========================================================================// +// File: unitvec.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for unit vector class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(UNITVEC_HPP) + #include +#endif + +// +//############################################################################# +//############################################################################# +// +UnitVector& + UnitVector::Lerp( + const UnitVector&, // v1, + const UnitVector&, // v2, + Scalar // t + ) +{ + Check_Pointer(this); + Tell("UnitVector::Lerp stubbed out!\n"); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Logical + UnitVector::TestInstance() const +{ + Scalar length = Vector3D::LengthSquared(); + Scalar diff = 1.0f - length; + if (!Small_Enough(diff,2e-5)) + { + length = x*x + y*y + z*z; + diff = 1.0f - length; + if (!Small_Enough(diff,2e-5)) + { + Dump(*this); + Dump(length); + Dump(x*x + y*y + z*z); + Dump(diff); + return False; + } + } + return True; +} + +#if defined(TEST_CLASS) +# include "unitvec.tcp" +#endif + diff --git a/CODE/BT/MUNGA/UNITVEC.TCP b/CODE/BT/MUNGA/UNITVEC.TCP new file mode 100644 index 0000000..45a605d --- /dev/null +++ b/CODE/BT/MUNGA/UNITVEC.TCP @@ -0,0 +1,77 @@ +//===========================================================================// +// File: unitvec.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for unit vector class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LINMTRX_HPP) + #include +#endif + +#if !defined(ROTATION_HPP) + #include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + UnitVector::TestClass() +{ + DEBUG_STREAM << "Starting UnitVector test...\n"; + + UnitVector + b; + const UnitVector + c(0.6f,0.0f,0.8f); + UnitVector + d(0.8f,-0.6f,0.0f); + + Test(c.x == 0.6f && c.y == 0.0f && c.z == 0.8f); + + Test(c[2] == c.z); + + b = c; + Test(b.x == c.x && b.y == c.y && b.z == c.z); + Test(Close_Enough(b,c)); + Test(b == c); + + b.Negate(c); + Test(b == UnitVector(-c.x,-c.y,-c.z)); + + Scalar f = c*d; + Test(Close_Enough(f,c.x*d.x + c.y*d.y + c.z*d.z)); + + LinearMatrix + m; + EulerAngles + r(PI_OVER_4,0.0f,0.0f); + m = r; + b.Multiply(c,m); + Test(b == UnitVector(c.x,c.y*m(1,1)+c.z*m(2,1),c.y*m(1,2)+c.z*m(2,2))); + b = c; + b *= m; + Test(b == UnitVector(c.x,c.y*m(1,1)+c.z*m(2,1),c.y*m(1,2)+c.z*m(2,2))); + + f = c.LengthSquared(); + Test(f == 1.0f); + f = c.Length(); + Test(f == 1.0f); + + Vector3D v(0.0f,1.2f,1.6f); + f = v.Length(); + b = v; + Test(b == UnitVector(v.x/f, v.y/f, v.z/f)); + + return True; +} + diff --git a/CODE/BT/MUNGA/VECTOR4D.HPP b/CODE/BT/MUNGA/VECTOR4D.HPP new file mode 100644 index 0000000..1e0b657 --- /dev/null +++ b/CODE/BT/MUNGA/VECTOR4D.HPP @@ -0,0 +1,228 @@ +//===========================================================================// +// File: vector4d.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(VECTOR4D_HPP) +# define VECTOR4D_HPP + +# if !defined(VECTOR3D_HPP) +# include +# endif + + class Point3D; + class AffineMatrix; + class Matrix4x4; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector4D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Vector4D + { + public: + Scalar + x, + y, + z, + w; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Vector4D *); + #endif + + static const Vector4D + Identity; + + // + // Constructors + // + Vector4D() + {} + Vector4D( + Scalar X, + Scalar Y, + Scalar Z, + Scalar W) + {x=X; y=Y; z=Z; w=W;} + + // + // Assignment operators + // + Vector4D& + operator=(const Vector4D &v); + Vector4D& + operator=(const Vector3D &v); + Vector4D& + operator=(const Point3D &p); + + // + // Index operators + // + const Scalar& + operator[](size_t index) const + {Check_Pointer(this); Warn(index>W_Axis); return (&x)[index];} + Scalar& + operator[](size_t index) + {Check_Pointer(this); Warn(index>W_Axis); return (&x)[index];} + + friend Logical + Small_Enough(const Vector4D &v,Scalar e=SMALL); + Logical + operator!() const + {return Small_Enough(*this);} + + // + // "Close-enough" comparison operators + // + friend Logical + Close_Enough( + const Vector4D &v1, + const Vector4D &v2, + Scalar e=SMALL + ); + Logical + operator==(const Vector4D& v) const + {return Close_Enough(*this,v);} + Logical + operator!=(const Vector4D& v) const + {return !Close_Enough(*this,v);} + + // + // The following operators all assume that this points to the destination + // of the operation results + // + Vector4D& + Negate(const Vector4D &v); + + Vector4D& + Add( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator+=(const Vector4D& v) + {return Add(*this,v);} + + Vector4D& + Subtract( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator-=(const Vector4D& v) + {return Subtract(*this,v);} + + Scalar + operator*(const Vector4D& v) const + {Check(this); return x*v.x + y*v.y + z*v.z + w*v.w;} + + Vector4D& + Multiply( + const Vector4D& v, + Scalar scale + ); + Vector4D& + operator*=(Scalar v) + {return Multiply(*this,v);} + + Vector4D& + Multiply( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator*=(const Vector4D &v) + {return Multiply(*this,v);} + + Vector4D& + Divide( + const Vector4D& v, + Scalar scale + ); + Vector4D& + operator/=(Scalar v) + {return Divide(*this,v);} + + Vector4D& + Divide( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator/=(const Vector4D &v) + {return Divide(*this,v);} + + // + // Transforms + // + Vector4D& + Multiply( + const Vector4D &v, + const AffineMatrix &m + ); + Vector4D& + operator*=(const AffineMatrix &M) + {Vector4D src(*this); return Multiply(src,M);} + Vector4D& Multiply( + const Vector4D &v, + const Matrix4x4 &m + ); + Vector4D& + operator*=(const Matrix4x4 &m) + {Vector4D src(*this); return Multiply(src,m);} + Vector4D& Multiply( + const Vector3D &v, + const Matrix4x4 &m + ); + Vector4D& Multiply( + const Point3D &p, + const Matrix4x4 &m + ); + + // + // Support functions + // + Scalar + LengthSquared() const + {return operator*(*this);} + Scalar + Length() const + {return Sqrt(LengthSquared());} + + Vector4D& + Combine( + const Vector4D& v1, + Scalar t1, + const Vector4D& v2, + Scalar t2 + ); + + Vector4D& + Lerp( + const Vector4D& v1, + const Vector4D& v2, + Scalar t + ) + {return Combine(v1,1.0f-t,v2,t);} + + friend ostream& + operator<<( + ostream& stream, + const Vector4D& v + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + +#endif diff --git a/CODE/BT/MUNGA/VERIFY.HPP b/CODE/BT/MUNGA/VERIFY.HPP new file mode 100644 index 0000000..8ea27d1 --- /dev/null +++ b/CODE/BT/MUNGA/VERIFY.HPP @@ -0,0 +1,61 @@ +//===========================================================================// +// File: verify.hpp // +// Contents: verification fail routines // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 JMA Initial coding. // +// 11/01/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(VERIFY_HPP) +# define VERIFY_HPP + +# if defined(__BCPLUSPLUS__) + extern int + _matherr(struct exception *a); +# endif + + extern int + Fpu_Ok(); + extern void + Verify_Failed(char *message, char *file, int line); + extern void + Fail_To_Debugger(char *message, char *file, int line); + + class Signature + { + private: +# if DEBUG_LEVEL>0 + enum Mark + { + ok, + destroyed, + corrupted, + noMagic=(int)0xAB135795L, + magic=(int)0xFFED1231L + } mark; +# endif + + protected: + Signature(); + ~Signature(); + + public: + friend int + Is_Signature_Bad(const volatile Signature *p); + }; + +# if defined(USE_SIGNATURE) +# define SIGNATURED : public Signature +# else +# define SIGNATURED +# define Is_Signature_Bad(p) (False) +# endif + +#endif + diff --git a/CODE/BT/MUNGA/VIDREND.TCP b/CODE/BT/MUNGA/VIDREND.TCP new file mode 100644 index 0000000..1a0f020 --- /dev/null +++ b/CODE/BT/MUNGA/VIDREND.TCP @@ -0,0 +1,21 @@ +//===========================================================================// +// File: vidrend.tst // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + VideoRenderer::TestClass() + +{ + Tell("Starting VideoRenderer::TestClass\n"); + return False; +} diff --git a/CODE/BT/MUNGA_L4/L4APP.THP b/CODE/BT/MUNGA_L4/L4APP.THP new file mode 100644 index 0000000..2449e63 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4APP.THP @@ -0,0 +1,50 @@ +//===========================================================================// +// File: l4app.thp // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/09/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4APP_THP) +# define L4APP_THP + +# if !defined(L4APP_HPP) +# include +# endif + +# if !defined(MISSION_HPP) +# include +# endif + + class L4TestApplication: + public L4Application + { + public: + L4TestApplication(StreamableResourceFile *resource_file); + ~L4TestApplication(); + + private: + Registry* + MakeRegistry(); + + Entity* + MakeViewpointEntity(Entity__MakeMessage*); + }; + + class L4TestMission: + public Mission + { + public: + L4TestMission( + NotationFile *notation_file, + StreamableResourceFile *resources + ); + ~L4TestMission(); + }; + +#endif diff --git a/CODE/BT/MUNGA_L4/L4AUDTUL.CPP b/CODE/BT/MUNGA_L4/L4AUDTUL.CPP new file mode 100644 index 0000000..14fc13d --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4AUDTUL.CPP @@ -0,0 +1,83 @@ +//===========================================================================// +// File: l4audres.cpp // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/10/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDRES_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +#if !defined(L4AUDIO_HPP) +# include +#endif + +ResourceDescription::ResourceID + L4Tool::CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + return + L4AudioResourceManager::CreateModelAudioStreamResource( + resource_file, + model_name, + model_file, + directories + ); +} + +ResourceDescription::ResourceID + L4Tool::CreateStaticAudioStreamResource( + ResourceFile *resource_file + ) +{ + return + L4AudioResourceManager::CreateStaticAudioStreamResource( + resource_file + ); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioCreateSymbols::WriteEntryStream(ofstream &symbol_file) +{ + AudioCreateSymbols::WriteEntryStream(symbol_file); + + #define WRITE_ENTRY(name)\ + {\ + Verify(symbol_file);\ + symbol_file << #name;\ + symbol_file << "=";\ + symbol_file << name;\ + symbol_file << "\n";\ + } + + WRITE_ENTRY(FrontDirectPatchPosition); + WRITE_ENTRY(RearDirectPatchPosition); + WRITE_ENTRY(FrontLeftDirectPatchPosition); + WRITE_ENTRY(FrontRightDirectPatchPosition); + WRITE_ENTRY(RearLeftDirectPatchPosition); + WRITE_ENTRY(RearRightDirectPatchPosition); +} + diff --git a/CODE/BT/MUNGA_L4/L4CTLTUL.CPP b/CODE/BT/MUNGA_L4/L4CTLTUL.CPP new file mode 100644 index 0000000..98b3d64 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4CTLTUL.CPP @@ -0,0 +1,31 @@ +//===========================================================================// +// File: l4video.cpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +// 07/11/95 KEO Modify video resource format. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include + +#if !defined(L4CTRL_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +PlatformTool::FindNameFunction + L4Tool::GetControlMappingFunction() +{ + return &LBE4ControlsManager::SetControlMappingID; +} + diff --git a/CODE/BT/MUNGA_L4/L4DPLMEM.CPP b/CODE/BT/MUNGA_L4/L4DPLMEM.CPP new file mode 100644 index 0000000..2018661 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4DPLMEM.CPP @@ -0,0 +1,45 @@ +/* +This block of code is expected to override the memory allocater in the DPL library +*/ +#include +#pragma hdrstop + +#if !defined(L4VIDEO_HPP) +# include +#endif + +extern "C" +{ + void + *dpl_malloc ( int n_bytes ), + *dpl_calloc ( size_t n, size_t n_bytes ), + dpl_free ( void *ptr ), + dpl_free_all ( void ); +}; + +void *dpl_malloc ( int n_bytes ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + return DPLRenderer::DPLHeap->Allocate(n_bytes); +} + +void *dpl_calloc ( size_t n, size_t n_bytes ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + void *p = DPLRenderer::DPLHeap->Allocate(n * n_bytes); + memset ( p, 0x0, n_bytes*n ); + return p; +} + +void dpl_free ( void *ptr ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + DPLRenderer::DPLHeap->Release(ptr); +} + +void dpl_free_all ( void ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + DPLRenderer::DPLHeap->ReleaseAll(); +} + diff --git a/CODE/BT/MUNGA_L4/L4GAUIMM.HPP b/CODE/BT/MUNGA_L4/L4GAUIMM.HPP new file mode 100644 index 0000000..7d2d545 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4GAUIMM.HPP @@ -0,0 +1,7 @@ +//===========================================================================// +// File: l4gaures.hpp // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//===========================================================================// + +// OBSOLETED ON 8-4-95 by cpb. Functionality now contained in L4WRHOUS.HPP diff --git a/CODE/BT/MUNGA_L4/L4HOST.CPP b/CODE/BT/MUNGA_L4/L4HOST.CPP new file mode 100644 index 0000000..bde4310 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4HOST.CPP @@ -0,0 +1,61 @@ +//===========================================================================// +// File: l4host.cpp // +// Project: MUNGA Brick: Connection Library // +// Contents: additional L4 data types and functions for hosts // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/09/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4HOST_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for l4host +// +L4Host::L4Host( + HostID host_ID, + HostType host_type, + NetworkAddress network_address, + unsigned long network_socket, + const CString &net_name): + Host( + host_ID, + host_type, + network_address), + SymbolicName(net_name) +{ + NetworkSocket = network_socket; + // ConnectStatus = NoNetworkConnectionStatus; + pad_head = 0; + pad_tail = 0; + pad_size = L4HOST_PAD_BUFFER_SIZE; + #if defined(TRACE_SEND_BUFFER) + sprintf(sendBufferTraceName,"Send Buffer %d",network_address&0xff); + sendBufferTrace = + new TraceOf( + sendBufferTraceName, + 0, + Trace::IntegerType, + TraceSample::IntegerSnapshot + ); + Register_Object(sendBufferTrace); + sendBufferTrace->TakeSnapshot(4096); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for l4host +// +L4Host::~L4Host() +{ +} + diff --git a/CODE/BT/MUNGA_L4/L4KEYBD.CPP b/CODE/BT/MUNGA_L4/L4KEYBD.CPP new file mode 100644 index 0000000..97ecbe3 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4KEYBD.CPP @@ -0,0 +1,37 @@ +//===========================================================================// +// File: PCkeybd.cc // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC keyboard interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/19/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#include +#include + +int PC_Keyboard_Read(void) +{ + int c; + + if (!kbhit()) // if keyboard has not been hit, return zero + { + return(0); + } + else + { + c = getch(); // keyboard was hit, get code + if (c == 0) // zero: next character is extended code + { + c = getch() | 0x0100; // flag as extended + } + return(c); // return the value + } +} diff --git a/CODE/BT/MUNGA_L4/L4MOUSE.HPP b/CODE/BT/MUNGA_L4/L4MOUSE.HPP new file mode 100644 index 0000000..9474fc5 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4MOUSE.HPP @@ -0,0 +1,37 @@ +//===========================================================================// +// File: PCMouse.hh // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC mouse interface class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/30/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(L4MOUSE_HPP) + + #define L4MOUSE_HPP + + #if !defined(STYLE_HPP) + #include + #endif + + class Mouse SIGNATURED + { + public: + Mouse(); + ~Mouse() + {} + void ReadCounters(int *xp, int *yp); + int ButtonPressed(int buttonNum); + int ButtonReleased(int buttonNum); + Logical + TestInstance() const; + + int ButtonCount; // number of buttons on mouse + int Errors; // non-zero if bad things happened + }; + +#endif diff --git a/CODE/BT/MUNGA_L4/L4MSSN.HPP b/CODE/BT/MUNGA_L4/L4MSSN.HPP new file mode 100644 index 0000000..7014ba1 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4MSSN.HPP @@ -0,0 +1,50 @@ +//===========================================================================// +// File: l4mssn.hh // +// Project: MUNGA Brick: Application // +// Contents: Implementation Details for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/19/95 JMA Initial coding. // +// 09/12/95 JM Put Back in Munga & Added Munga L4 level Player Data // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined (L4MSSN_HPP) + #define L4MSSN_HPP + +# if !defined(MISSION_HPP) +# include "mission.hpp" +# endif + +#if 0 +// THIS FILE IS OBSOLETE AS OF 11-1-95 cpb + +//########################################################################## +//########################## L4Mission ################################ +//########################################################################## + + +class L4Mission : + public Mission +{ + public: + + L4Mission( + NotationFile *notation_file, + ResourceFile *resources + ); + ~L4Mission(); + + void + SetPlayerData(NotationFile *notation_file); + + Logical + TestInstance() const; + +}; + +#endif +#endif diff --git a/CODE/BT/MUNGA_L4/L4PLASMA.HPP b/CODE/BT/MUNGA_L4/L4PLASMA.HPP new file mode 100644 index 0000000..c6bb04c --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4PLASMA.HPP @@ -0,0 +1,70 @@ +//===========================================================================// +// File: L4plasma.hpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for plasma display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 04/20/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4PLASMA_HPP) +# define L4PLASMA_HPP + +# if !defined(L4VB8_HPP) +# include +# endif + +# if !defined(L4SERIAL_HPP) +# include +# endif + + //######################################################################## + //################################ Plasma ################################ + //######################################################################## + class PlasmaDisplay : + public Video8BitBuffered + { + public: + enum + { + plasmaWidth=128, + plasmaHeight=32 + }; + + PlasmaDisplay(Word port, Word int_num); + + ~PlasmaDisplay(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + Logical + Update(Logical forceall); + + void + WaitForUpdate(); + + protected: + void + Scan(Logical forceall); + + Logical + forceAll, + updateInProgress; + + PCSerial + *pc_serial; + int + currentTransferLine; + char + updateFlag[32]; + }; + +#endif diff --git a/CODE/BT/MUNGA_L4/L4TIME.HPP b/CODE/BT/MUNGA_L4/L4TIME.HPP new file mode 100644 index 0000000..f94c572 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4TIME.HPP @@ -0,0 +1,12 @@ + +#if !defined(L4TIME_HPP) +# define L4TIME_HPP + +# if !defined(TIME_HPP) +# include +# endif + +# define TIMER_ENV "L4TIMER" +# define USE_SOS_TIMER "FAST" + +#endif diff --git a/CODE/BT/MUNGA_L4/L4VIDEO.TCP b/CODE/BT/MUNGA_L4/L4VIDEO.TCP new file mode 100644 index 0000000..1ca787c --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4VIDEO.TCP @@ -0,0 +1,75 @@ +//===========================================================================// +// File: vidrend.tst // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "entity.thh" + +Logical + VideoRenderer::TestClass() + +{ + + Tell("Starting VideoRenderer::TestClass\n"); +#if 0 +// Create the message that will be used to make my entities + + TestEntity::MakeMessage + message1( + TestEntity::MakeMessageID, + sizeof(TestEntity::MakeMessage), + TestEntity::TrivialEntityClassID, + TestEntity::DefaultFlags, + LinearOrigin::Identity + ); + +// Send the message that creates the entity in Entity_1 + + message1.localOrigin.translation.z = -30.0f; + + Entity* Entity_1 = TestEntity::Make(&message1); + + Register_Object(Entity_1); + + // Push the origin in the message forward 30 meters + + message1.localOrigin.translation.z = 30.0f; + + // Create the second entity 30 meters in front of the first + + Entity* Entity_2 = TestEntity::Make(&message1); + + Register_Object(Entity_2); + +// create more + + message1.localOrigin.translation.z = 0.0f; + message1.localOrigin.translation.x = 30.0f; + Entity* Entity_3 = TestEntity::Make(&message1); + Register_Object(Entity_3); + + + message1.localOrigin.translation.x = -30.0f; + Entity* Entity_4 = TestEntity::Make(&message1); + Register_Object(Entity_4); + + message1.localOrigin.translation.x = 0.0f; + message1.localOrigin.translation.y = 30.0f; + Entity* Entity_5 = TestEntity::Make(&message1); + Register_Object(Entity_5); + + message1.localOrigin.translation.y = -30.0f; + Entity* Entity_6 = TestEntity::Make(&message1); + Register_Object(Entity_6); +#endif + return False; +} diff --git a/CODE/BT/MUNGA_L4/L4VIDTUL.CPP b/CODE/BT/MUNGA_L4/L4VIDTUL.CPP new file mode 100644 index 0000000..edd5607 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4VIDTUL.CPP @@ -0,0 +1,43 @@ +//===========================================================================// +// File: l4video.cpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +// 07/11/95 KEO Modify video resource format. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4VIDEO_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +ResourceDescription::ResourceID + L4Tool::CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + return + DPLRenderer::CreateModelVideoStreamResource( + resource_file, + model_name, + model_file, + directories + ); +} + diff --git a/CODE/BT/MUNGA_L4/L4WRHOUS.CPP b/CODE/BT/MUNGA_L4/L4WRHOUS.CPP new file mode 100644 index 0000000..7f283a3 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4WRHOUS.CPP @@ -0,0 +1,63 @@ +//===========================================================================// +// File: wrhous.cc // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +// This object manages creation and deletion of dynamically-created objects // +// of which only on instantiation should exist. It is currently used // +// only by the gauge renderer. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/01/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include + +#if !defined(L4WRHOUS_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//####################################################################### +// Warehouse +//####################################################################### +L4Warehouse::L4Warehouse() : + Warehouse() +{ + Check_Pointer(this); + Check_Fpu(); +} + +L4Warehouse::~L4Warehouse() +{ + Check(this); + Check_Fpu(); +} + +void + L4Warehouse::Purge() +{ + Check(this); + + gaugeImageBin.Purge(); + Warehouse::Purge(); + + Check_Fpu(); +} + +Logical + L4Warehouse::TestInstance() const +{ + return Warehouse::TestInstance(); +} + diff --git a/CODE/BT/MUNGA_L4/L4WRHOUS.HPP b/CODE/BT/MUNGA_L4/L4WRHOUS.HPP new file mode 100644 index 0000000..15905d3 --- /dev/null +++ b/CODE/BT/MUNGA_L4/L4WRHOUS.HPP @@ -0,0 +1,42 @@ +//===========================================================================// +// File: wrhous.hh // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/01/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4WRHOUS_HPP) +# define L4WRHOUS_HPP + +# if !defined(WRHOUS_HPP) +# include "wrhous.hpp" +# endif + +# if !defined(L4GAUIMA_HPP) +# include "l4gauima.hpp" +# endif + + //####################################################################### + // L4Warehouse + //####################################################################### + class L4Warehouse : + public Warehouse + { + public: + L4Warehouse(); + ~L4Warehouse(); + Logical + TestInstance() const; + void + Purge(); + + WarehouseBinOf + gaugeImageBin; + }; +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/MATRIX.H b/CODE/BT/MUNGA_L4/LIBDPL/DPL/MATRIX.H new file mode 100644 index 0000000..593d92c --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DPL/MATRIX.H @@ -0,0 +1,47 @@ +#ifndef matrix_h +#define matrix_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpl.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Introduces all the datatypes and functions + used by the dpl interface + + History : Rev 1.0, 18 / 06 / 1994 + +**************************** */ + +#include +#include +#include + +extern void dpl_SetAngleMode( int degrees ); +extern void dpl_IdMatrix ( dpl_MATRIX m ); +extern void dpl_Translate ( dpl_MATRIX m, float32 dx, float32 dy, float32 dz ); +extern void dpl_Rotate ( dpl_MATRIX m, float32 angle, int32 axis ); +extern void dpl_Scale ( dpl_MATRIX m, float32 x, float32 y, float32 z ); +extern void dpl_Concat ( dpl_MATRIX m, dpl_MATRIX a, dpl_MATRIX b ); +extern void dpl_Invert ( dpl_MATRIX inverse, dpl_MATRIX mat ); +extern void dpl_XformPoint ( dpl_POINT q, dpl_POINT p, dpl_MATRIX m ); + +extern void dpl_IdMatrixDCS ( dpl_DCS *d ); +extern void dpl_TranslateDCS ( dpl_DCS *d, float32 dx, float32 dy, float32 dz ); +extern void dpl_RotateDCS ( dpl_DCS *d, float32 angle, int32 axis ); +extern void dpl_ScaleDCS ( dpl_DCS *d, float32 x, float32 y, float32 z ); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL2DTAG.H b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL2DTAG.H new file mode 100644 index 0000000..5987cd5 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL2DTAG.H @@ -0,0 +1,33 @@ +#ifndef dpl_2dtag_h +#define dpl_2dtag_h + +typedef enum { + dpl2d_open_polyline, + dpl2d_close_polyline, + dpl2d_open_polypoint, + dpl2d_close_polypoint, + dpl2d_open_polygon, + dpl2d_close_polygon, + dpl2d_open_lines, + dpl2d_close_lines, + dpl2d_point, + dpl2d_circle, + + dpl2d_open_clip_polygon, + dpl2d_close_clip_polygon, + dpl2d_clip_circle, + dpl2d_clip_full, + dpl2d_clip_none, + + dpl2d_set_drawcolor, + dpl2d_set_matrix, + dpl2d_concat_matrix, + dpl2d_push_state, + dpl2d_pop_state, + + dpl2d_call_displaylist, + dpl2d_set_linewidth, + dpl2d_set_alpha +} dpl_2d_tag; + +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL_MEM.H b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL_MEM.H new file mode 100644 index 0000000..a41f650 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/DPL_MEM.H @@ -0,0 +1,24 @@ +#ifndef dpl_mem_h +#define dpl_mem_h + +#ifdef __cplusplus +extern "C" { +#endif + +extern void *dpl_malloc ( int n_bytes ); +extern void *dpl_calloc ( size_t n, size_t size ); +extern void dpl_free ( void *ptr ); +extern void dpl_free_all ( void ); + +extern void dpl_tracemem ( void ); + +#ifndef dpl_mem_c +#define free dpl_free +#define malloc dpl_malloc +#define calloc dpl_calloc +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/MATRIX.H b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/MATRIX.H new file mode 100644 index 0000000..593d92c --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/MATRIX.H @@ -0,0 +1,47 @@ +#ifndef matrix_h +#define matrix_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpl.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Introduces all the datatypes and functions + used by the dpl interface + + History : Rev 1.0, 18 / 06 / 1994 + +**************************** */ + +#include +#include +#include + +extern void dpl_SetAngleMode( int degrees ); +extern void dpl_IdMatrix ( dpl_MATRIX m ); +extern void dpl_Translate ( dpl_MATRIX m, float32 dx, float32 dy, float32 dz ); +extern void dpl_Rotate ( dpl_MATRIX m, float32 angle, int32 axis ); +extern void dpl_Scale ( dpl_MATRIX m, float32 x, float32 y, float32 z ); +extern void dpl_Concat ( dpl_MATRIX m, dpl_MATRIX a, dpl_MATRIX b ); +extern void dpl_Invert ( dpl_MATRIX inverse, dpl_MATRIX mat ); +extern void dpl_XformPoint ( dpl_POINT q, dpl_POINT p, dpl_MATRIX m ); + +extern void dpl_IdMatrixDCS ( dpl_DCS *d ); +extern void dpl_TranslateDCS ( dpl_DCS *d, float32 dx, float32 dy, float32 dz ); +extern void dpl_RotateDCS ( dpl_DCS *d, float32 angle, int32 axis ); +extern void dpl_ScaleDCS ( dpl_DCS *d, float32 x, float32 y, float32 z ); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/TRICODER.H b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/TRICODER.H new file mode 100644 index 0000000..1b36a00 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/TRICODER.H @@ -0,0 +1,35 @@ +#ifndef tricoder_h +#define tricoder_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define triangle_intro_bits 0x0f + +#define triangle_opacity_intro 0x01 +#define triangle_unopacity_intro 0x02 +#define triangle_dmg_set_intro 0x03 +#define triangle_dmg_clear_intro 0x04 +#define triangle_sca_intro 0x05 +#define triangle_dmg2enbl_intro 0x06 +#define triangle_undmg2enbl_intro 0x07 +#define triangle_bright32_intro 0x08 +#define triangle_dark32_intro 0x09 +#define triangle_fifty_intro 0x0a +#define triangle_surfopacity_intro 0x0b +#define triangle_albright32_intro 0x0c +#define triangle_aldark32_intro 0x0d +#define triangle_albrightfog_intro 0x0e + +#define triangle_texture_bit 0x010 +#define triangle_dither_bit 0x020 +#define triangle_gouraud_bit 0x040 +#define triangle_enbl2dmg_bit 0x080 +#define triangle_white_bit 0x100 +#define triangle_emiss_bit 0x200 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VR_PROT.H b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VR_PROT.H new file mode 100644 index 0000000..bcd5b4c --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VR_PROT.H @@ -0,0 +1,95 @@ +#ifndef vr_prot_h +#define vr_prot_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum vr_action { + vr_init_action, + + vr_create_action, + vr_delete_action, + vr_flush_action, + + vr_sect_pixel_action, + vr_sect_vector_action, + + vr_dcs_nest_action, + vr_dcs_link_action, + vr_dcs_prune_action, + + vr_draw_scene_action, + vr_draw_scene_complete_action, + + vr_list_add_action, + vr_list_remove_action, + + vr_morph_action, + + vr_version_action, + vr_statistics_action, + vr_readpixels_action, + + vr_hspcode_action, + vr_860code_action, + vr_860data_action, + vr_860bss_action, + vr_860args_action, + + vr_set_geom_text_action, + vr_update_geom_verts_action, + vr_get_geom_verts_action, + vr_add_geom_connections_action, + vr_set_texmap_texels_action, + vr_sfx_action, + vr_install_sfx_action, + vr_psfx_action, + vr_install_psfx_action, + vr_flush_dcs_artic_action, + vr_damage_action, + vr_random_table_action, + vr_gamma_table_action, + vr_kill_sfx_action, + vr_geometrize_action, + vr_clone_object_action, + vr_set_sect_pixel_action, + vr_set_warning_action, + vr_set_render_prop_action, + vr_create_2d_display_action, + vr_delete_2d_display_action, + vr_flush_2d_display_action, + vr_freemem_action, + vr_sync_action, + vr_get_bounds_action, + vr_get_geom_connections_action, + vr_get_geom_numconnections_action, + vr_cleanup_gg_action, + vr_clear_dcs_action, + vr_remove_dcs_action, + vr_add_dcs_action +} vr_action; + +/* some i860 states for transputer-side monitoring */ + +#define state_vr_rcv_wait_lock 0 +#define state_vr_rcv_wait_ack 1 +#define state_vr_send_wait_lock 2 +#define state_vr_send_wait_ack 3 +#define state_vr_dma_wait_lock 4 +#define state_vr_dma_wait_ack 5 +#define state_vr_dma_spin_lock 6 +#define state_vr_texels_wait_lock 7 +#define state_vr_texels_wait_ack 8 +#define state_vr_texels_spin_lock 9 +#define state_vr_cull 10 +#define state_vr_draw 11 + +#define state_monitor 0 + +#define set_state(a,b,c) if (state_monitor) set_i860_state(a,b,c) +#define aux_state(a,b,c) if (state_monitor) set_i860_auxstate(a,b,c) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VSSVER.SCC b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VPX/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..09366a3600c68e938728145024f90b55ebc15b02 GIT binary patch literal 160 zcmXpJVq{<_<6Ee;`hwt8Uj~KsYN|KOJS+cRU}FFSX&~J*-LNR_-}5~{l?*aK{?E>n zHZZ;{kT3Fj&ovld4#>~aJKzfA%LDoMKZvoVot?24q+bEZuicVR50h5}@_pUJZo~LW MK)!51WGajg0D4z34FCWD literal 0 HcmV?d00001 diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DPL/VSSVER.SCC b/CODE/BT/MUNGA_L4/LIBDPL/DPL/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..c5e94523f78dbfb935c7157d7a771c787a538ddc GIT binary patch literal 144 zcmXpJVq{<_<6Ee;`hwt8Uj~KsYN|KSdkAu$XJY^ZVIXZhlUXY5?2NrYl?)<4e$RBn yA{bv3$QOCN=NgPJ2IOby9dL#5#ew|!92Q+Lz66jzGeBS(j4uh~*KSFuhw%ZO5hiE= literal 0 HcmV?d00001 diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.DEF b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.DEF new file mode 100644 index 0000000..0b14825 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.DEF @@ -0,0 +1,75 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: VL + * MODULE: basictypes.def + * + * File: $RCSfile: divtypes.def,v $ + * Revision: $Revision: 2.3 $ + * Date: $Date: 1995/04/27 10:40:16 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divtypes.def,v 2.3 1995/04/27 10:40:16 jeff beta $ + * + * FUNCTION: + * This module is used to hold the parameterised definitions of the basic + * types used throughout the system for all the machines supported. When + * porting to a new architecture all type stuff should be modified in + * here. There should be no machine dependant code anywhere else! + * + * each of the basic type int8 uint8 etc, etc is defined in terms of + * standard ansi 'C' types here, and given a enum name for conveniance. + * + * char8 is used for cases where the signedness of the byte is irelevent + * such as in character strings etc. + * The format is DEF_TYPE ( , , ) + * + * $Log: divtypes.def,v $ + * Revision 2.3 1995/04/27 10:40:16 jeff + * *** empty log message *** + * + * Revision 2.2 1994/09/08 12:35:33 jeff + * added windows basic types. + * + * Revision 2.1 1994/04/08 13:50:14 jeff + * Importded from 2.0 tree. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#if defined (_WIN31) + +DEF_TYPE( CHAR8, char8, char) +DEF_TYPE( INT8, int8, signed char) +DEF_TYPE( UINT8, uint8, unsigned char) +DEF_TYPE( INT16, int16, signed int) +DEF_TYPE( UINT16, uint16, unsigned int) +DEF_TYPE( INT32, int32, signed long) +DEF_TYPE( UINT32, uint32, unsigned long) +DEF_TYPE( FLOAT32, float32, float) +DEF_TYPE( FLOAT64, float64, double) + +#else + +DEF_TYPE( CHAR8, char8, char) +DEF_TYPE( INT8, int8, signed char) +DEF_TYPE( UINT8, uint8, unsigned char) +DEF_TYPE( INT16, int16, signed short) +DEF_TYPE( UINT16, uint16, unsigned short) +DEF_TYPE( INT32, int32, signed int) +DEF_TYPE( UINT32, uint32, unsigned int) +DEF_TYPE( FLOAT32, float32, float) +DEF_TYPE( FLOAT64, float64, double) + +#endif + +/* + * Note we may need to put ifdefs back in here for some machines IE 64Bit + * processors ? + */ diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.H b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.H new file mode 100644 index 0000000..694be94 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVTYPES.H @@ -0,0 +1,73 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: vl + * MODULE: divtypes.h + * + * File: $RCSfile: divtypes.h,v $ + * Revision: $Revision: 2.11 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divtypes.h,v 2.11 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * + * This file contains standard type definitions used by all higher + * levels in the system. + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DIVTYPES_H +#define _DIVTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * mangle the divtypes.def file to get machine specific low level + * definitions for all our basic types. + */ +#define DEF_TYPE(a,b,c) typedef c b; +#include +#undef DEF_TYPE + +/* + * generate an enum list of all the symbolic values for the types. + */ +#define DEF_TYPE(a,b,c) a, +typedef enum dpDivType { +#include +LAST_TYPE +} dpDivType; +#undef DEF_TYPE +#define BASIC_TYPE_CNT ((int)LAST_TYPE) + +/* + * A structure to define the names etc of the basic types for internal + * use. + */ +typedef struct dpTypeSpec{ + char8 endian16[3]; + char8 endian32[5]; + struct { + char8 *name; + uint32 size; + uint32 alignment; + }Sizes[BASIC_TYPE_CNT]; +} dpTypeSpec; + +extern void dpGenDivTypes(dpTypeSpec *spec); + +#ifdef __cplusplus +} +#endif +#endif /* _DIVTYPES_H */ + + diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVVERS.H b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVVERS.H new file mode 100644 index 0000000..a7d07a5 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DIVVERS.H @@ -0,0 +1,54 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: dp + * MODULE: divvers.c + * + * File: $RCSfile: divvers.h,v $ + * Revision: $Revision: 1.6 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divvers.h,v 1.6 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * macro to aid the printing of version no's for components. + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DIVVERS_H +#define _DIVVERS_H + +#include +#define divVersion(filep,module,description,version) \ +do { \ + static int done = 0; \ + static char *vstring = "@(#)Division dVS. " module " - " description \ + ". Version " version ". " __DATE__ ; \ + if (done == 0) { \ + fprintf (stdout, "%s\n", &vstring [4]); \ + if (filep) \ + fprintf (filep, "%s\n", &vstring [4]); \ + } \ + done = 1; \ +} while (0) + +#define div3rdPartyVersion(filep,party,description,version,date) \ +do { \ + static int done = 0; \ + static char *vstring = party ". " description \ + ". Version " version ". " date ; \ + if (done == 0) { \ + fprintf (stdout, "%s\n", vstring); \ + if (filep) \ + fprintf (filep, "%s\n", vstring ); \ + } \ + done = 1; \ +} while (0) + +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DP.H b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DP.H new file mode 100644 index 0000000..c9660c9 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DP.H @@ -0,0 +1,47 @@ +/* + * PROJECT: dVS + * SUBSYSTEM: dp + * MODULE: dp.h + * + * + * File: $RCSfile: dp.h,v $ + * Revision: $Revision: 2.9 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: dp.h,v 2.9 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, photocopied, + * reproduced, translated, or reduced to any electronic medium or + * machine readable form without prior written consent from Division + * Ltd. + */ + +#ifndef _DP_H +#define _DP_H 1 + +#ifdef _cplusplus +extern "C" { +#endif + +#if defined (_UNIX) +#include +#elif defined (_TRANSPUTER) || defined (_I860) +#include +#elif defined (_WIN31) +#include +#else +#error "Unknown processor type " +#endif + +#ifdef _cplusplus +} +#endif + +#endif /* _DP_H */ diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DS.H b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DS.H new file mode 100644 index 0000000..b5fd2f6 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/DS.H @@ -0,0 +1,48 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: ds.h,v $ + * REVISION: $Revision: 1.6 $ + * Date: $Date: 1995/05/18 09:39:38 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: ds.h,v 1.6 1995/05/18 09:39:38 jeff beta $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#ifndef _DS_H +#define _DS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + char *string; +}DStringTraverseInfo; + +extern void dsVersion(FILE *fp); +char *dStringFromOptions (char *string, int *size, char *name, ...); +char *dStringFirstString (char *string, DStringTraverseInfo *info); +char *dStringNextOption (char *option, DStringTraverseInfo *info); + + +#define DS_END_OF_OPTIONS '\0' + + +#ifdef __cplusplus +} +#endif +#endif /*_DS_H */ diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/GETPARAM.H b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/GETPARAM.H new file mode 100644 index 0000000..4bb85b9 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/GETPARAM.H @@ -0,0 +1,73 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: getparam.h,v $ +-- Revision : $Revision: 1.6 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __GETPARAM_H__ +#define __GETPARAM_H__ + +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +/*****************************************************************************/ +/* getparam error numbers */ +#define dgpENO_STREXP 0x3001 +#define dgpENO_UNKOPT 0x3002 +#define dgpENO_USAGE 0x3003 +#define dgpENO_RSRCF 0x3004 + +/**************************************************************************** + * getparam monitor numbers */ +#define dgpMON_OPTIONS 0x00001000 +#define dgpMON_FILES 0x00002000 + + +#define dgp_END 0 +#define dgp_NO_STR 1 +#define dgp_D_STR 2 +#define dgp_DJOIN_STR 3 +#define dgp_DAFTER_STR 4 +#define dgp_DBOTH_STR 5 +#define dgp_O_STR 6 +#define dgp_OJOIN_STR 7 +#define dgp_OAFTER_STR 8 +#define dgp_OBOTH_STR 9 + +typedef struct { + char optname[15] ; + int32 opttype ; + int32 optreturn ; +} dgpTABLE, *dgpTABLEPTR ; + +extern char *progname ; + +int32 +dgpGetopt(int32 argc, char *argv[], dgpTABLEPTR table, + int32 *NoFiles, char **files[], char **str1, char **str2) ; + +void +dgpFreeFiles(int32 NoFiles, char *files[]) ; + +#endif /* __GETPARAM_H__ */ diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/MAPFILE.H b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/MAPFILE.H new file mode 100644 index 0000000..4c13dcd --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/MAPFILE.H @@ -0,0 +1,99 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1994 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: mapfile.h,v $ +-- Revision : $Revision: 1.3 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __MAPFILE_H__ +#define __MAPFILE_H__ + +#ifdef _PF_LOCAL +#include "ptool.h" +#else +#include +#endif + +/* Error Numbers */ +#define dmpENO_OPEN 0x50001 +#define dmpENO_FORM 0x50002 + +typedef struct dmpMATFILETYPE +{ + char *name ; + dpfFILEPTR file ; + struct dmpMATFILETYPE *next ; +} dmpMATFILE, *dmpMATFILEPTR ; + +typedef struct dmpBLOCKTYPE +{ + char *name ; + int32 ignore ; + struct dmpBLOCKTYPE *next ; +} dmpBLOCK, *dmpBLOCKPTR ; + +typedef struct dmpMAPPINGTYPE +{ + char *from, *to ; + int32 gotMat ; + int32 gotText ; + dptTEXTURE text ; + struct dmpMAPPINGTYPE *next ; +} dmpMAPPING, *dmpMAPPINGPTR ; + +typedef struct +{ + dmpMATFILEPTR materials ; + dmpMAPPINGPTR mappings ; + dmpBLOCKPTR blocks ; +} dmpFILE, *dmpFILEPTR ; + +dmpFILEPTR +dmpCreateFile(void) ; +dmpMATFILEPTR +dmpCreateMatFile(void) ; +int32 +dmpAddMatFile(dmpFILEPTR mp, dmpMATFILEPTR mat) ; +dmpBLOCKPTR +dmpCreateBlock(void) ; +int32 +dmpAddBlock(dmpFILEPTR mp, dmpBLOCKPTR blk) ; +dmpMAPPINGPTR +dmpCreateMapping(void) ; +int32 +dmpAddMapping(dmpFILEPTR mp, dmpMAPPINGPTR map) ; +void +dmpFreeFile(dmpFILEPTR mp) ; +dmpMAPPINGPTR +dmpFindMapping(dmpFILEPTR mp, char *name) ; +dpfMATERIALPTR +dmpFindMaterial(dmpFILEPTR mp, char *name) ; +dpfTEXTUREPTR +dmpFindTexture(dmpFILEPTR mp, char *name) ; +dmpBLOCKPTR +dmpFindBlock(dmpFILEPTR mp, char *name) ; + +int32 +dmpGetMapFile(dmpFILEPTR mp, char *fileName) ; +int32 +dmpSaveFile(char *name, dmpFILEPTR file) ; + + +#endif /* __MAPFILE */ diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/PFPARSER.H b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/PFPARSER.H new file mode 100644 index 0000000..426483b --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/PFPARSER.H @@ -0,0 +1,97 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: pfparser.h,v $ + * REVISION: $Revision: 1.3 $ + * Date: $Date: 95/04/27 23:01:16 $ + * Author: $Author: bill $ + * RCS Ident: $Id: pfparser.h,v 1.3 95/04/27 23:01:16 bill Exp $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#ifndef __PFPARSER_H__ +#define __PFPARSER_H__ + +#include +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +#define dpp_MATCH_CASE 0 +#define dpp_ANY_CASE 1 + +/* On calls which either succeed or fail, dpgSUCCESS (0) or dpgERROR (-1) + * is returned. On calls to get next token however the following + * return values are also used + */ +#define dppEOF -2 +#define dppSTRING -3 +#define dppNUMBER -4 + +typedef struct dppKEYTAB +{ + int32 tok; + char *name; + int32 matchCase; +} dppKEYTAB ; + + +typedef struct dppFILE +{ + int32 lineNo; + int32 errorFlag; + char *fileName; + FILE *file; + char *whites ; + char comment ; + int32 pushedBackToken; + float number; + char *buffer; + int32 bufSize; + int32 bufPos; + dppKEYTAB *keyTab; +} dppFILE, *dppFILEPTR ; + + + +dppFILEPTR +dppOpenFile (char *name, FILE *fp, const char *whites, char comment, + dppKEYTAB *keyTable, int32 bufferSize); +void +dppCloseFile (dppFILEPTR fPtr); +char * +dppTokenToString (dppFILEPTR fptr, const int32 token); +int32 +dppPushToken (dppFILEPTR fptr, const int32 token); +int32 +dppNextToken (dppFILEPTR fptr); +int32 +dppReadToNextChar(dppFILEPTR fPtr, char endChr) ; +char * +dppMatchString (dppFILEPTR fptr); +int32 +dppMatchInt (dppFILEPTR fptr, int32 *num); +int32 +dppMatchFloat (dppFILEPTR fptr, float *num); +int32 +dppMatchCharacter (dppFILEPTR fptr, char c); +void +dppMoveToNextLine(dppFILEPTR fptr) ; + + +#endif /* __PFPARSER_H__ */ + diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DSYS/VSSVER.SCC b/CODE/BT/MUNGA_L4/LIBDPL/DSYS/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..f82ceeac27eee2bb4638de22595037b1a572c4c8 GIT binary patch literal 384 zcmXpJVq{<_<6Ee;`hwt8Uj~KsYN|JnD)=#7WMcpWWgvb0z}K#{f6w;-RWhgm`Hv?T zNx}H4K>qKQjgw(~H6VWqd&@=`UmeId^K4t0HrZ@HNWTV%?lS`NO9L0>!1%^M{x6rp-!Q%jkY61deFVlg1@eV* hYK35YGa!G9Z4F$%IY|Dwgd +#endif + +/* ver change */ +/* 2.01 Initial version for tools library */ +/* 2.02 New line definitions and coping with texture etc */ +/* 2.03 New material stuff */ +/* 2.04 New STRIP_LIST and POINTLIST */ +#define dpt_LIBRARY_MAJOR_VER 2 +#define dpt_LIBRARY_MINOR_VER 04 + +#define dpt_TINY_float32 1.0e-24 + + + +/************************************************************* +* ptmesh Routines used by other dptOols * +*************************************************************/ + +dpfVERTEXPTR +dptCreateVertex(void) ; +dpfVERTEXPTR +dptMeshAddVertex ( dptMESHPTR mesh, dpfVERTEXPTR Fvert ) ; +dpfVERTEXPTR +dptMeshAddNewVertex(dptMESHPTR mesh, dpfPATCHPTR patch, dmVector point, + dmVector norm, dpfRGBA col, dpfTEXT text) ; +dptTRIANGLEPTR +dptMeshAddTriangle(dptMESHPTR mesh, dpfPATCHPTR patch, dpfVERTEXPTR vert1, + dpfVERTEXPTR vert2, dpfVERTEXPTR vert3) ; +void +dptMeshRemoveTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptMeshUnloadGeometry(dptTRIANGLEPTR start, dptMESHPTR mesh, dpfPATCHPTR patch, + int32 usePmesh) ; +void +dptMeshDisconnectTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptMeshConnectTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptAddGeometryPatch(dptMESHPTR mesh, dpfGEOMETRYPTR geom) ; + + +/* reduce a mesh, used in ptbound */ +int32 +dptrReduceMesh(dptMESHPTR mesh, float32 Norm_tol, float32 Edge_tol, + int32 Verbose) ; + +/* defined in ptreduce, used also in ptflip */ +dptTRIANGLEPTR +dptGetTriangleDuplicate(dptTRIANGLEPTR tri) ; + +#endif /* ____PTOOL_H__ */ + + diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DVS/DM.H b/CODE/BT/MUNGA_L4/LIBDPL/DVS/DM.H new file mode 100644 index 0000000..0e94c68 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DVS/DM.H @@ -0,0 +1,29 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * File: $RCSfile: dm.h,v $ + * Revision: $Revision: 1.3 $ + * Date: $Date: 1995/05/18 09:48:43 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: dm.h,v 1.3 1995/05/18 09:48:43 jeff beta $ + * + * FUNCTION: + * + * + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DVS_DM_H +#define _DVS_DM_H +#include +#include +#endif /*_DVS_DM_H */ diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCBODAPP.H b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCBODAPP.H new file mode 100644 index 0000000..97aa8e7 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCBODAPP.H @@ -0,0 +1,47 @@ + +typedef struct +{ + int state; + void *collideEntity; + void *pickEntity; + void *pickRelocateHandle; + void *relocateData; +}VCBodyPartAppInfo; + +typedef struct +{ + VCEntity *entity; + VCAttribute *bodyPart; + VCBody *body; +}VCBodyAppCallbackData; + +typedef struct +{ + VCAttribute *bodyPart; + VCBody *body; +}VCBodyAppRelocateData; + + +#define VC_BODYAPP_COLLIDED 0x00000001 +#define VC_BODYAPP_PICK_PRESSED 0x00000002 + +typedef void (*VCBodyTouchFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyUnTouchFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyPickFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyDropFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyMoveFunc)(VCBodyAppCallbackData *callbackData, void *data); + +typedef struct +{ + void *touchFunc; + void *unTouchFunc; + void *pickFunc; + void *dropFunc; + void *moveFunc; +} VCBodyFuncInfo; + +void *VCBody_AttachInteractionCallbacks(VCBody *body, VCBodyTouchFunc touchFunc, + VCBodyUnTouchFunc unTouchFunc, VCBodyPickFunc pickFunc, + VCBodyDropFunc dropFunc, VCBodyMoveFunc moveFunc, void *data); + +void VCBody_DetachInteractionCallbacks(VCBody *body, void *callbackHandle); diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCERROR.H b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCERROR.H new file mode 100644 index 0000000..0097c68 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCERROR.H @@ -0,0 +1,33 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1994 Division Limited. +-- All Rights Reserved +-- +-- +-- System : dVS 2.1 +-- Module : libvc +-- Object Name : $RCSfile: vcerror.h,v $ +-- Revision : $Revision: 1.1 $ +-- Date : $Date: 95/05/18 10:24:15 $ +-- Author : $Author: john $ +-- +-- Description +-- Vcerror routines. +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __VCERROR_H__ +#define __VCERROR_H__ + +void VC_Warn(char *format, ...); +void VC_Error(char *format, ...); +void VC_Fatal(char *format, ...); + +#endif /* __VCERROR_H__ */ diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCINPDEF.H b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCINPDEF.H new file mode 100644 index 0000000..8a8b0e4 --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCINPDEF.H @@ -0,0 +1,71 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vcinpdef.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:16 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcinpdef.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + + +/* + * define the modifier values + */ +#define VC_INPUT_RELEASE 0x00010000 +#define VC_INPUT_PRESS 0x00020000 +#define VC_MODIFIER_0 0x00100000 +#define VC_MODIFIER_1 0x00200000 +#define VC_MODIFIER_2 0x00400000 +#define VC_MODIFIER_3 0x00800000 +#define VC_MODIFIER_4 0x01000000 +#define VC_MODIFIER_5 0x02000000 +#define VC_MODIFIER_6 0x04000000 +#define VC_MODIFIER_7 0x08000000 + +#define VC_MODIFIER_CTRL VC_MODIFIER_0 +#define VC_MODIFIER_ALT VC_MODIFIER_1 +#define VC_MODIFIER_ESC VC_MODIFIER_2 + +#define VC_INPUT_CODE_MASK 0x0000ffff +#define VC_INPUT_TYPE 0x000f0000 +#define VC_INPUT_MODIFIER_MASK 0x0ff00000 +#define VC_INPUT_ALL_KEYS 0x0000ffff +#define VC_INPUT_SINGLE_KEY 0x00000000 + +#define VC_BUTTON_0 0x0080 +#define VC_BUTTON_1 0x0081 +#define VC_BUTTON_2 0x0082 +#define VC_BUTTON_3 0x0083 +#define VC_BUTTON_4 0x0084 +#define VC_BUTTON_5 0x0085 +#define VC_BUTTON_6 0x0086 +#define VC_BUTTON_7 0x0087 +#define VC_BUTTON_8 0x0088 +#define VC_BUTTON_9 0x0089 +#define VC_BUTTON_10 0x008a +#define VC_BUTTON_11 0x008b +#define VC_BUTTON_12 0x008c +#define VC_BUTTON_13 0x008d +#define VC_BUTTON_14 0x008e +#define VC_BUTTON_15 0x008f + + + + + + + diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCMACROS.H b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCMACROS.H new file mode 100644 index 0000000..701838c --- /dev/null +++ b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VCMACROS.H @@ -0,0 +1,33 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vctools.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:16 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctools.h,v 0.10 1994/10/05 12:51:14 john Exp jon $ + * + * FUNCTION: + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine reable form without prior + * written consent from Division Ltd. + */ + + + +#ifndef _VCMACROS_H_ +#define _VCMACROS_H_ + +#define VC_GetEntityRelocateMode() VCEntity_GetRelocateMode(NULL) +#define VC_SetEntityRelocateMode(m) VCEntity_SetRelocateMode(NULL,m) +#define VCBody_SetVisualResourceBackgroundColor(b,c) VCBody_SetVisualResourceBackgroundColour(b,c) +#define VCBody_SetVisualResourceFogColor(b,c,t,m) VCBody_SetVisualResourceFogColour(b,c,t,m) +#endif diff --git a/CODE/BT/MUNGA_L4/LIBDPL/DVS/VSSVER.SCC b/CODE/BT/MUNGA_L4/LIBDPL/DVS/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..1d5cc48ef720ff87089665c51d4dde42bc618a1f GIT binary patch literal 368 zcmXpJVq{<_<6Ee;`hwt8Uj~KsYN|Jt=Sr`?#Kr&ymOz@<@?~_I3(G#BN(L(+e_ocy z1{mKO$j`BDS_k9X0Qog-&sW3vwm^Q$U;9)T-wwz>@Nrd2T4nG-ka_k%{=Q=QHW=Rl z$j_R;PZ-8`1oGEyp2Q5}I|2E|b)@$NRDN(NRSf0IJU zue41%J3)LlApaF7mjaB>4&={mI;{)ia{&2EYAz+ErC03$spkaplYZ6Bgz>q6e6L4+ zaWFnNkU!h(>}nXF2gujFv<{s@Z1eDj}OSN-u-e1jL#3`Cv0N=3*!R- Dq53%H literal 0 HcmV?d00001 diff --git a/CODE/BT/MUNGA_L4/MSSCCPRJ.SCC b/CODE/BT/MUNGA_L4/MSSCCPRJ.SCC new file mode 100644 index 0000000..68b3698 --- /dev/null +++ b/CODE/BT/MUNGA_L4/MSSCCPRJ.SCC @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[mungal4.mak] +SCC_Aux_Path = "\\AVATAR\Mungass\VSS" +SCC_Project_Name = "$/Tesla_BT/MUNGA_L4", XOCAAAAA diff --git a/CODE/BT/MUNGA_L4/MUNGAL4.HPP b/CODE/BT/MUNGA_L4/MUNGAL4.HPP new file mode 100644 index 0000000..0a00c84 --- /dev/null +++ b/CODE/BT/MUNGA_L4/MUNGAL4.HPP @@ -0,0 +1,28 @@ +#if !defined(MUNGAL4_HPP) +# define MUNGAL4_HPP + +# if !defined(MUNGA_HPP) +# include +# endif + +# define __DPMI32__ +# include + +# if !defined(NO_PRECOMPILED_HEADERS) + +# if !defined(GRAPH2D_HPP) +# include +# endif + +# if !defined(L4HOST_HPP) +# include +# endif + +# if !defined(L4APP_HPP) +# include +# endif + +# endif + +#endif + diff --git a/CODE/BT/MUNGA_L4/NETNUB/ANALYSIS.HPP b/CODE/BT/MUNGA_L4/NETNUB/ANALYSIS.HPP new file mode 100644 index 0000000..fa4d71f --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/ANALYSIS.HPP @@ -0,0 +1,58 @@ +#if !defined(ANALYSIS_HPP) +# define ANALYSIS_HPP + + // + //############################################################################# + // Set one of the 12 outputable bits of the parallel port at 0x378 (usually + // LPT1), taking into account the hardware sense of the bit + //############################################################################# + // + void + Set_Analysis(int bit); + + // + //############################################################################# + // Clear one of the 12 outputable bits of the parallel port at 0x378 (usually + // LPT1, taking into account the hardware sense of the bit. + //############################################################################# + // + void + Clear_Analysis(int bit); + + // + //############################################################################# + // Read the state of one of the 12 outputable bits of the parallel port at + // 0x378 (usually LPT1, taking into account the hardware sense of the bit. + //############################################################################# + // + int + Read_Analysis(int bit); + + // + //############################################################################# + // Clear all of the 12 outputable bits of the parallel port at 0x378. + //############################################################################# + // + + void + Reset_Analysis(void); + + // + //############################################################################# + // Test all of the 12 outputable bits of the parallel port at 0x378. + //############################################################################# + // + void + Test_Analysis(void); + + // + //############################################################################# + // Print the bit numbers of any active bit of the 12 outputable bits of the + // parallel port at 0x378 + //############################################################################# + // + void + Analysis_Status(void); + +#endif + diff --git a/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/BOOTP.H b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/BOOTP.H new file mode 100644 index 0000000..081580a --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/BOOTP.H @@ -0,0 +1,73 @@ + +/* + * Bootstrap Protocol (BOOTP) + * Based on RFC 951. + */ + + +#define BOOTREQUEST 1 /* bootp.bp_op */ +#define BOOTREPLY 2 + +/* + * structure for send and receives + */ +typedef struct bootp { + byte bp_op; /* packet op code / message type. */ + byte bp_htype; /* hardware address type, 1 = 10 mb ethernet */ + byte bp_hlen; /* hardware address len, eg '6' for 10mb eth */ + byte bp_hops; /* client sets to zero, optionally used by + gateways in cross-gateway booting. */ + longword bp_xid; /* transaction ID, a random number */ + word bp_secs; /* filled in by client, seconds elapsed since + client started trying to boot. */ + word bp_spare; + longword bp_ciaddr; /* client IP address filled in by client if known*/ + longword bp_yiaddr; /* 'your' (client) IP address + filled by server if client doesn't know */ + longword bp_siaddr; /* server IP address returned in bootreply */ + longword bp_giaddr; /* gateway IP address, + used in optional cross-gateway booting. */ + byte bp_chaddr[16]; /* client hardware address, filled by client */ + byte bp_sname[64]; /* optional server host name, null terminated*/ + + byte bp_file[128]; /* boot file name, null terminated string + 'generic' name or null in bootrequest, + fully qualified directory-path + name in bootreply. */ + byte bp_vend[ 64]; /* optional vendor-specific area */ +}; + + +extern struct bootp _bootp; +extern word sock_inactive; + +/* + * UDP port numbers, server and client. + */ +#define IPPORT_BOOTPS 67 +#define IPPORT_BOOTPC 68 + + +/******** the following is stolen from NCSA which came from CUTCP *********/ +/* I have not implemented these, but someone may wish to in the future so */ +/* I kept them around. */ +/**************************************************************************/ + +/* + * "vendor" data permitted for Stanford boot clients. + */ +struct vend { + byte v_magic[4]; /* magic number */ + longword v_flags; /* flags/opcodes, etc. */ + byte v_unused[56]; /* currently unused */ +}; + +#define VM_STANFORD "STAN" /* v_magic for Stanford */ +/*#define VM_RFC1048 "\143\202\123\143" /* 94.11.20 */ + +/* v_flags values */ +#define VF_PCBOOT 1 /* an IBMPC or Mac wants environment info */ +#define VF_HELP 2 /* help me, I'm not registered */ +#define TAG_BOOTFILE_SIZE 13 /* tag used by vend fields rfc 1048 */ + + diff --git a/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ELIB.H b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ELIB.H new file mode 100644 index 0000000..b6d3b1a --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ELIB.H @@ -0,0 +1,25 @@ +void outch( char ch ); /* print character to stdio */ +void outs( char far *s); /* print a ASCIIZ string to stdio */ +void outsn( char far *s,int n); /* print a string with len max n */ +void outhex( char ch ); +void outhexes( char far *ch, int n ); +void qmove( void far * src, void far * dest, int len ); +int qcmp( void far *src, void far *dest, int len ); +void _keep( int status, int paragraphs ); +int sem_up( void far * ptr ); +unsigned long set_timeout( unsigned int seconds ); +unsigned long set_ttimeout( unsigned int ticks ); +int chk_timeout( unsigned long timeout ); + +unsigned long intel( unsigned long ); +unsigned short intel16( unsigned short ); +unsigned inchksum( void far *ptr, int len); /* IP checksum */ + +/* + * qmsg.c + */ +void dputch( char x ); +void dmsg( char *s ); +void dhex1int( int x ); +void dhex2int( int x ); +void dhex4int( int x ); diff --git a/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ETHDEV.H b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ETHDEV.H new file mode 100644 index 0000000..f8149f2 --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ETHDEV.H @@ -0,0 +1,16 @@ +/* + * + * Ethernet Interface + */ + +extern byte *_eth_FormatPacket(), *_eth_WaitPacket(); + +typedef struct ether { + byte dest[6]; /* destination ethernet address */ + byte src[6]; /* source ethernet address */ + word type; + byte data[ 1500 ]; +}; + + +#define ETH_MIN 60 /* Minimum Ethernet packet size */ diff --git a/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ICMP.H b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ICMP.H new file mode 100644 index 0000000..01bfdc5 --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/ICMP.H @@ -0,0 +1,101 @@ + +#ifndef _wattcp_icmp_h +#define _wattcp_icmp_h + +//#include +#include + +typedef struct icmp_unused { + byte type; + byte code; + word checksum; + longword unused; + in_Header ip; + byte spares[ 8 ]; +}; + +typedef struct icmp_pointer { + byte type; + byte code; + word checksum; + byte pointer; + byte unused[ 3 ]; + in_Header ip; +}; +typedef struct icmp_ip { + byte type; + byte code; + word checksum; + longword ipaddr; + in_Header ip; +}; +typedef struct icmp_echo { + byte type; + byte code; + word checksum; + word identifier; + word sequence; + longword index; +}; + +typedef struct icmp_timestamp { + byte type; + byte code; + word checksum; + word identifier; + word sequence; + longword original; /* original timestamp */ + longword receive; /* receive timestamp */ + longword transmit; /* transmit timestamp */ +}; + +typedef struct icmp_info { + byte type; + byte code; + word checksum; + word identifier; + word sequence; +}; + +typedef union { + struct icmp_unused unused; + struct icmp_pointer pointer; + struct icmp_ip ip; + struct icmp_echo echo; + struct icmp_timestamp timestamp; + struct icmp_info info; +} icmp_pkt; + +typedef struct _pkt { + in_Header in; + icmp_pkt icmp; + in_Header data; +}; + +#define ICMPTYPE_ECHOREPLY 0 +#define ICMPTYPE_UNREACHABLE 3 +#define ICMPTYPE_TIMEEXCEEDED 11 + +typedef enum ICMP_UnreachableCodes +{ + ICMP_UNREACH_NET = 0, + ICMP_UNREACH_HOST = 1, + ICMP_UNREACH_PROTO = 2, + ICMP_UNREACH_PORT = 3, + ICMP_UNREACH_FRAGNEEDED = 4, + ICMP_UNREACH_SRCROUTEFAILED = 5 +}; + +typedef enum ICMP_TimeExceededCodes +{ + ICMP_EXCEEDED_TTL = 0, + ICMP_EXCEEDED_FRAGREASM = 1 +}; + +/* a user-installed ICMP handler */ +typedef int (*icmp_handler_type)( in_Header *ip ); + +/* install a user ICMP handler, or NULL to disable */ +void set_icmp_handler( icmp_handler_type user_handler ); + +#endif /* ndef _wattcp_icmp_h */ diff --git a/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/STATE.RST b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/STATE.RST new file mode 100644 index 0000000..fa131ce --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/STATE.RST @@ -0,0 +1,13 @@ +[edit-] +screen=80 25 +toggles=1 1 0 1 0 0 +srch= +src= +rpl= +file=c:\tcpip\include\bootp.h 1 23 2 28 +[brief] +file=c:\tcpip\include\bootp.h 1 23 2 28 1 22 78 1 c=0 +file=c:\tcpip\include\wattcp.h 1 1 1 1 +file=c:\tcpip\include\copyrigh.h 1 67 1 67 +[shared-] +pmark=c:\tcpip\include\bootp.h 2 28 diff --git a/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/TCP.H b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/TCP.H new file mode 100644 index 0000000..ef31670 --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/TCP.H @@ -0,0 +1,98 @@ + +/* + * Waterloo TCP + * + * Copyright (c) 1990, 1991, 1992, 1993 Erick Engelke + * + * Portions copyright others, see copyright.h for details. + * + * This library is free software; you can use it or redistribute under + * the terms of the license included in LICENSE.H. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * file LICENSE.H for more details. + * + */ +#ifndef _wattcp_tcp_h +#define _wattcp_tcp_h + +#ifndef WTCP_VER + +#define __WATTCP_USER__ /* Not compiling the kernel itself, hide some stuff */ + +#include + +/* handle some early dumb naming conventions */ +#define dbuginit() dbug_init() + +/* Kernal version (major major minor minor) */ +#define WTCP_VER 0x0102 + +/* + * Typedefs and constants + */ + +struct in_addr { + longword s_addr; +}; + +/* + * BSD-style socket info routines -- bsdname.c + */ +int getpeername( sock_type *s, void *dest, int *len ); +int getsockname( sock_type *s, void *dest, int *len ); +char *getdomainname( char *name, int length ); +char *setdomainname( char *string ); +char *gethostname( char *name, int len ); +char *sethostname( char *name ); +void psocket( sock_type *s ); + +/* + * ICMP-related stuff -- pcicmp.c + */ +/* + * Send an icmp echo request using specified ttl and tos. + * if(icmp_id != NULL) store copy of the id there + */ +int _send_ping( longword host, longword countnum, byte ttl, + byte tos, longword *theid ); +/* backward compatibility */ +#define _ping( h, c ) _send_ping( h, c, 250, 0, NULL ) +longword _chk_ping( longword host , longword *ptr); + +/* + * Daemons -- wattcpd.c + */ +int addwattcpd( void (*p)( void ) ); +int delwattcpd( void (*p)( void ) ); + +/* + * Background net I/O processing -- netback.c + */ +void backgroundon( void ); +void backgroundoff(void); +void backgroundfn( void (*fn)() ); + +/* + * More background processing -- pcintr.c + */ +void wintr_enable( void ); +void wintr_disable( void ); +void wintr_shutdown( void ); +void wintr_init( void ); + +/* + * Socket stats -- pcstat.c + */ +int sock_stats( sock_type *s, word *days, word *inactive, word *cwindow, word *avg, word *sd ); + +/* + * Debug test routine -- test.c + */ +void debugpsocketlen( void ); + +#endif /* WTCP_VER */ + +#endif /* ndef _wattcp_tcp_h */ diff --git a/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/VSSVER.SCC b/CODE/BT/MUNGA_L4/NETNUB/INCLUDE/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..b7fd2f63b261ae8d52ff234a2f229771a193d204 GIT binary patch literal 176 zcmXpJVq{<_<6Ee;`hwt8Uj~KsYN|Io(nul + +abl: + @echo Nothing >nul + +test: + @echo Nothing >nul + +clean: + del $(NETNUB_ROOT)\obj\*.obj + del $(NETNUB_ROOT)\*.exe + +#------------------------------------------------------------------------------ +# Implicit rules +# +LINK_OPTIONS = -Tde -c -L$(LIBRARY_PATH) +BCC = bcc + +$(CFG_FILE): $(NETNUB_ROOT)\makefile.mak $(CONFIG) + copy &&| +-DMSDOS;NETNUB;USE_PROFILE_ANALYSIS;CLEAN_BUILD=1 +-b +-r +-ff +-AT +-k- +-N- +-v- +-3 +-V +-Jg +-x- +-RT- +-O2 +-Ot +-Oc +-Og +-O +-Ol +-Z +-Ob +-Oe +-Oi +-Om +-Op +-Ov +-w +-c +-ml +-I$(INCLUDE_PATH) +-n$(NETNUB_ROOT)\obj +| $(CFG_FILE) + +{$(NETNUB_ROOT)}.cpp{$(NETNUB_ROOT)\obj}.obj: + $(BCC) @$(CFG_FILE) $< >>$(CFG_ROOT)\error.log + +#------------------------------------------------------------------------------ +# Test program +# +NETNUB_OBJS = \ + ?netnub.obj \ + ?analysis.obj \ + ?nopause.obj + +$(NETNUB_ROOT)\netnub.exe:\ + $(NETNUB_OBJS:?=) $(NETNUB_ROOT)\lib\wattcplg.lib + tlink @&&| +$(LINK_OPTIONS) + +$(BC_ROOT)\lib\c0l.obj+ +$(NETNUB_OBJS:?=$(OBJ_PREFIX)) +$<,$* +wattcplg.lib+ +emu.lib+ +mathl.lib+ +cl.lib +| >>$(CFG_ROOT)\error.log + +$(NETNUB_OBJS:?=): $(CFG_FILE) diff --git a/CODE/BT/MUNGA_L4/NETNUB/MSSCCPRJ.SCC b/CODE/BT/MUNGA_L4/NETNUB/MSSCCPRJ.SCC new file mode 100644 index 0000000..5b8ab78 --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/MSSCCPRJ.SCC @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[makefile.mak] +SCC_Aux_Path = "\\AVATAR\Mungass\VSS" +SCC_Project_Name = "$/Tesla_BT/MUNGA_L4/NetNub", FPCAAAAA diff --git a/CODE/BT/MUNGA_L4/NETNUB/NOPAUSE.CPP b/CODE/BT/MUNGA_L4/NETNUB/NOPAUSE.CPP new file mode 100644 index 0000000..54c325d --- /dev/null +++ b/CODE/BT/MUNGA_L4/NETNUB/NOPAUSE.CPP @@ -0,0 +1,72 @@ +/* NOPAUSE.CPP - Disable Pause. + (C) Copyright 1991 + By Thomas Astin CIS: 73407,3427 Prodigy: RNVN08A + All rights reserved. */ + +/* Disable pause by intercepting interrupt 9 and blocking pause scan codes.*/ + +/* NOTE: This program worked fine on the machine upon which it was + developed and tested. Use at your own risk. The author is + not responsible for any damage, system failure, or the like + as a result of executing this code. + + Compiles under Borland C++. Code may require modifications for + use with other compilers. +*/ + + +#include +#include + +/* Protos */ +void interrupt NewInt9(...); +void ExitFunc(void); + +/* exit func in case ^C */ +#pragma exit ExitFunc + +/* Defines */ +#define KbdIn 0x60 +#define KbdCtl 0x61 +#define MaxChkIdx 3 + +/* Globals */ +unsigned char ChkArray[MaxChkIdx] = {0xE1,0x1D,0x45}; +unsigned char ChkIdx=0; +unsigned char CurScan=0; +void interrupt (*OldInt9)(...)=NULL; + +void interrupt NewInt9(...) // int 9 handler +{ + CurScan=inportb(KbdIn); // get scan code + if (CurScan==ChkArray[ChkIdx++]) { // check scan code array + if (ChkIdx>=MaxChkIdx) { // last match? + ChkIdx=0; // get ready for next time + + asm in al,KbdCtl // restore keyboard + asm mov ah,al + asm or al,80h + asm jmp temp1 + temp1: + asm out KbdCtl,al + asm xchg ah,al + asm jmp temp2 + temp2: + asm out KbdCtl,al + asm mov al,20h // Issue EOI + asm out 20h,al + + return; + } + } + else + ChkIdx=0; // start over + + OldInt9(); // call original int 9 +} + +void ExitFunc(void) +{ + if (OldInt9!=NULL) + setvect(9,OldInt9); // restore int 9 +} \ No newline at end of file diff --git a/CODE/BT/MUNGA_L4/NETNUB/VSSVER.SCC b/CODE/BT/MUNGA_L4/NETNUB/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..2f82704811ca3109867f3e6521253ed67ba9d9f6 GIT binary patch literal 144 zcmXpJVq{<_<6Ee;`hwt8Uj~KsYN|J{1^IAaW@7+@53CFf7W(Z1Xm&?IsPzyERgS{!zKjd#{v0wd>**K`0+sgr>7ooVEhCipX=b;6EJ=vkT3Ro Z^>G+K3CLf5Y_M~!{y^H+$YOiihXY4}Dj5QReARh} zO463{9|7?LfqXlgr~@#55RiYXPi_{B9}MLCZI<5%C#H0R$mo8KpZDj8CN{GRyS z +#include +#undef inp +#undef outp + +#define SPKSET outp(0x61,(2 | inp(0x61))) +#define SPKCLR outp(0x61,((~2) & inp(0x61))) + + diff --git a/CODE/BT/MUNGA_L4/VSSVER.SCC b/CODE/BT/MUNGA_L4/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..2ea7bc9815bc62bf41691a53290098ea0d8e0dc8 GIT binary patch literal 1520 zcmXxhdrZw?7zgm5P9+j@LKl~gRK$j4jHr~FOKz}3tdi>(owqTq(ZrW-?s1j-{*baJEswlP+q7WGS?A_z z_^~AN)k{lhc)hlgq=p>79NGUxt{HYJV9mgQjj#f)gs1*|YQ}mM+|d#?QI4Lh73ZsA zPa`l`xcx(Mz_G> zbCc}ok8qG()hxOdKHPHLfi}V$L-ghJC%9?L6%V=%&XY$kr`zF~-SB9^nzrocJ3OD*YeAXu> zmHq*1F1Ll#gYc#U$L7*Q@QLc6{q#>*AN_YJ{R{TaH5{gY!>RF(_Z|V4nr6APZU$d5thT2WaA8rskv4~|Yj-y=n8Y%22S?q^`*zcp>dh<^f)-SHa%3fJXk2^kB3t=eyeC(*i*e;K~I47txk2c z5>}~q&Y|t#{`__edLrzjRA$kW;8#y-P4r~gw>62d|sc4zS*I>IUry z7ah%RqMhJ>n)K)N6u3~A6hu#j7oSN9kh@cgMgM8=yT__1dOEz-A~1n=hR5{oXr@(g zaPo8|Jp+58KU^nY@TxZMB% literal 0 HcmV?d00001 diff --git a/CODE/BT/NEWSTUFF.BLD b/CODE/BT/NEWSTUFF.BLD new file mode 100644 index 0000000..148235d --- /dev/null +++ b/CODE/BT/NEWSTUFF.BLD @@ -0,0 +1,21 @@ +model=apc.mod /id:141 +model=armrmovr.mod /id:142 +model=bulldog.mod /id:143 +model=comtruck.mod /id:123 +model=coolant.mod /id:124 +model=dozer.mod /id:125 +model=harasser.mod /id:126 +model=hummer.mod /id:127 +model=lrmcarry.mod /id:128 +model=mechmovr.mod /id:129 +model=rommel.mod /id:130 +model=semi.mod /id:131 +model=semirig.mod /id:132 +model=srmcarry.mod /id:133 +model=striker.mod /id:134 +model=swiftwnd.mod /id:135 +model=bld03.mod /id:136 +model=bld04.mod /id:137 +model=bld20.mod /id:138 +model=bld24.mod /id:139 +model=bld26.mod /id:140 diff --git a/CODE/BT/OPT.MAK b/CODE/BT/OPT.MAK new file mode 100644 index 0000000..118cf52 --- /dev/null +++ b/CODE/BT/OPT.MAK @@ -0,0 +1,47 @@ +LINK_OPTIONS = -Tpe -ax -L$(LIBRARY_PATH) -m +BCC = bcc32 +TASM_OPTIONS = +MAKE_TEST = 1 + +STARTUP_OBJ = $(STARTUP_ROOT)\c0x32.obj +STARTUP_LIBS = $(STARTUP_ROOT)\dpmi32.lib $(STARTUP_ROOT)\cw32.lib + +LIB_OPTIONS = /P32 + +$(CFG_FILE): opt.mak make.cfg $(BPATH) + copy &&| +-DLBE4;DEBUG_LEVEL=0;DEBUG_STREAM=cout; +-b +-r +-ff +-AT +-k- +-N- +-v- +-5 +-a4 +-V +-Jg +-x- +-RT- +-O2 +-Ot +-Oc +-Og +-O +-Ol +-Z +-Ob +-Oe +-Oi +-Om +-Op +-Ov +-w +-c +-I$(INCLUDE_PATH) +-H +-H=$(HEADER_FILE) +-Hc +-n$(TARGET_DIR) +| $(CFG_FILE) diff --git a/CODE/BT/SETENV.BAT b/CODE/BT/SETENV.BAT new file mode 100644 index 0000000..f0127f3 --- /dev/null +++ b/CODE/BT/SETENV.BAT @@ -0,0 +1,220 @@ +@echo off +echo ************************************************************************ +echo * Setting up the MUNGA environment, see SETENV.bat for usage +echo ************************************************************************ +rem ------------------------------------------------ +rem - setenv.bat performs actions that must occur in +rem - the shell prior to execution of rpl4*.exe +rem ------------------------------------------------ +rem - there are four arguments that must all be specified +rem - 1= t/r where t=thrustmaster, r=rio +rem - 2= s/f where s=slow clock, f=fast clock +rem - 3= s/n where s=sound, n=nosound +rem - 4= p/g/n/r where p=plasma and gauges, g=gauges, n=no gauges, r=review +rem - 5= i/n where i=intercom, n=no intercom +rem ------------------------------------------------ +rem - setenv with no args is RIO, SLOW, SOUND, NONE, NOINTERCOM +rem ------------------------------------------------ +rem + +rem ************************************************************************* +rem * Controls, anything but t or r goes with preset defaults in L4CONTROLS +rem * if they are not set you will get RIO +rem ************************************************************************* +rem +if "%1"=="t" goto THRUSTMASTER +if "%1"=="r" goto RIO +if "%L4CONTROLS%"=="" goto RIO +goto CONTROLSDONE + +:RIO +set L4CONTROLS=RIO,KEYBOARD +echo L4CONTROLS set to %L4CONTROLS% +goto CONTROLSDONE + +:THRUSTMASTER +set L4CONTROLS=THRUSTMASTER,KEYBOARD +echo L4CONTROLS set to %L4CONTROLS% +goto CONTROLSDONE + +:CONTROLSDONE +rem +rem ************************************************************************* +rem * Real time clock, anything but s or f goes with preset defaults in +rem * L4TIMER, if it isn't set you will get slow +rem ************************************************************************* +rem +if "%2"=="s" goto SLOWCLOCK +if "%2"=="f" goto FASTCLOCK +if "%L4TIMER%"=="" goto SLOWCLOCK +goto TIMERDONE + +:FASTCLOCK +set L4TIMER=FAST +echo L4TIMER set to FAST +goto TIMERDONE + +:SLOWCLOCK +set L4TIMER= +echo L4TIMER set to SLOW +goto TIMERDONE + +:TIMERDONE +rem +rem ************************************************************************* +rem * GAUGES/PLASMA anything but p,n or g will get you the preset defaults +rem * in L4GAUGE if that isn't set you will get none. +rem ************************************************************************* +rem +if "%4"=="n" goto NOGAUGE +if "%4"=="g" goto NOPLASMA +if "%4"=="p" goto PLASMA +if "%4"=="r" goto GREVIEW +if "%L4GAUGE%"=="" goto NOGAUGE +goto GAUGEDONE + +:GREVIEW +set L4GAUGE=640x480x8 +set L4PLASMA=com2 +echo L4GAUGE set to %L4GAUGE% +echo L4PLASMA set to %L4PLASMA% +goto GAUGEDONE + +:PLASMA +set L4GAUGE=640x480x16 +set L4PLASMA=com2 +echo L4GAUGE set to %L4GAUGE% +echo L4PLASMA set to %L4PLASMA% +goto GAUGEDONE + +:NOPLASMA +set L4GAUGE=640x480x16 +set L4PLASMA= +echo L4GAUGE set to %L4GAUGE% +echo L4PLASMA set to off +goto GAUGEDONE + +:NOGAUGE +set L4GAUGE= +set L4PLASMA= +echo L4GAUGE set to off +echo L4PLASMA set to off + +:GAUGEDONE +rem +rem ************************************************************************* +rem * INTERCOM anything but i or n will get you the preset defaults +rem * in L4INTERCOM if that isn't set you will get none. +rem ************************************************************************* +rem +if "%5"=="n" goto NOINTERCOM +if "%5"=="i" goto INTERCOM +if "%L4INTERCOM%"=="" goto NOINTERCOM +goto ICOMDONE + +:NOINTERCOM +set L4INTERCOM= +echo L4INTERCOM set to off +goto ICOMDONE + +:INTERCOM +set L4INTERCOM=ON +echo L4INTERCOM set to on + +:ICOMDONE +:AUDIOVIDEO +rem +rem *+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+* +rem from here on down has not been updated yet, except to make sure sound is +rem set right based on L4INTERCOM +rem *+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+* +rem +rem ----------------------------- +rem main video +rem ----------------------------- +if "%VIDEOFORMAT%"=="" set VIDEOFORMAT=svga +set L4DPLCFG=%A4DPLCFG% +if "%L4DPLCFG%"=="" set L4DPLCFG=btdpl.ini +set A4DPLCFG= +if "%L4VIDEO%"=="OFF" goto VIDEODONE +set DPLARG=/tranny~.\vrendmon.btl~/i860~.\vrnostex.mng~/device~0x150~/video~%VIDEOFORMAT%~/pipes~1~/qual~0x14~/system_tex~0~ + +:VIDEODONE +rem ----------------------------- +rem - AWE settings +rem ----------------------------- +if "%3"=="n" goto NOSOUND +if "%3"=="s" goto SOUND +if "%L4SOUND%"=="OFF" goto NOSOUND +if "%L4SOUND%"=="" goto NOSOUND +if "%L4SOUND%"=="ON" goto SOUND +if "%L4SOUND%"=="CAMERA" goto SOUND +goto NOSOUND + +:SOUND +if exist c:\setvol.bat call c:\setvol.bat +if not exist c:\setvol.bat set AWE_MASTER_VOLUME=200 + +set AWE_FRONT=A220 I5 D1 H5 P330 T6 +set AWE_REAR=A240 I7 D3 H6 P300 T6 + +if "%L4INTERCOM%"=="ON" goto AWEINTERCOM + +copy /v audio\ctmix.cfg c:\sb16\ctmix.cfg +set BLASTER=%AWE_FRONT% +c:\sb16\sb16set /p /q +set BLASTER=%AWE_REAR% +c:\sb16\sb16set /p /q + +if "%REVIEW%"=="1" goto SOUNDREVIEW +if "%L4SOUND%"=="CAMERA" goto SOUNDREVIEW +goto SOUNDCOMMON + +:AWEINTERCOM +copy /v audio\icom.cfg c:\sb16\ctmix.cfg +set BLASTER=%AWE_FRONT% +c:\sb16\sb16set /p /q +c:\sb16\sb16set /li:220;0 +set BLASTER=%AWE_REAR% +c:\sb16\sb16set /p /q +goto SOUNDCOMMON + +:SOUNDCOMMON +set BLASTER=%AWE_FRONT% +c:\sb16\sb16set /ma:%AWE_MASTER_VOLUME%;0 /mi:235;0 /ba:255;0 /tr:90;0 +set BLASTER=%AWE_REAR% +c:\sb16\sb16set /ma:%AWE_MASTER_VOLUME%;0 /mi:230;0 /ba:235;0 /tr:110;0 +set BLASTER=%AWE_FRONT% +goto SOUNDDONE + +:SOUNDREVIEW +set BLASTER=%AWE_FRONT% +c:\sb16\sb16set /ma:240;0 /mi:245;0 /ba:90;0 /tr:90;0 +set BLASTER=%AWE_REAR% +c:\sb16\sb16set /ma:240;0 /mi:245;0 /ba:90;0 /tr:90;0 +set BLASTER=%AWE_FRONT% +goto SOUNDDONE + +:NOSOUND +set L4SOUND=OFF +set AWE_FRONT= +set AWE_REAR= + +:SOUNDDONE + +rem +rem ************************************************************************* +rem * Print a summary of all the environmentals we think are important +rem ************************************************************************* +rem +echo ************************************************************************ +echo * Environment is setup as follows +echo * L4CONTROLS = %L4CONTROLS% +echo * L4TIMER = %L4TIMER% +echo * L4SOUND = %L4SOUND% +echo * L4GAUGE = %L4GAUGE% +echo * L4VIDEO = %L4VIDEO% +echo * L4PLASMA = %L4PLASMA% +echo * L4INTERCOM = %L4INTERCOM% +echo ************************************************************************ + diff --git a/CODE/BT/VSSVER.SCC b/CODE/BT/VSSVER.SCC new file mode 100644 index 0000000000000000000000000000000000000000..e6c809ba21c280e9f28f21ac74004e4ffcb2308a GIT binary patch literal 512 zcmX}n&nv@W90%}+EjifO*GlHs*VyL!J!*t-kkwjtSRBM<=zAS5TFKoXU5+5jTRnvL=EJ6_{!7wPS(TcZ_=@16i@m41p3$_*BPFx;753RFdd-$ z3BGZ<{NyCO@h#iPDR^7`k>}?1&u~oVomU4$0kcZE`)H;{X5M85o!t7-E3f4#;O@_#Kc{1Y`hNqhNT3fU!|06p87@AobnOGT{C>R?RmE`Icmy{+cq~#YW1h^`sW#*(7>wyEr4@kxU zaSkMSco`UsjeBJMrZY#e>3p6R5I=gVvu9sZ3mR|KC8&zoWa-!G)1kCO^3nw z|DT=z{~I6pv`($TmZ9`V^Ks^VF$~?;)Vf$ZSlr!gVoI61uh}q^zTY3j(ESN2$WZ!i zR}6}YVwfhXHQEL^mh!7L)-r{7l(MTe)Uw!?a6#>P^g5#XI19+i5`Un5?qHTH*iswo z5)K=N5}@U;-#66!k162-lKLeq$5>+A!hxDZWo!h_V5vn# z`9)R=&WU;ICBST!m!hB|7ZAiJzpI0J2LtC>#i$7RxpTq-g7yIo72!r``qf$6N` z>rYV;adYRqHqcY>EK$fUEiO?=N>#|uQz*$uRVYX-$xtZCS12k4@iU7R3X1a6ixPA7 zc)6g4pGO$J;lExZuNT{4o?5AYy} zP_0T84LUa1+%E3w$&(-dz%Cv~gJ+0CuTWbIMR+mZi;3RWwsk&T6JrHgsj6|L~Jq1cpAnn>xFDOC{8NSjspY zK#8Tx51lsfQ#CcI@`oJ92l?)71Ak&{G^@5Sg$(+NbP~r20Z-%EtPk(~t#Y)BJU~H!mGOa$ z8EG-nc5;tRxp!|on;Xdr$rOvvk?d^;xtnY_0`Mm@F?DdBgB=-11R*(mdhE=2eO`hd zFXRP1(F=Hj=l6Ke=W%U!ZsJFt&6jl?pIUa_w5xM0oz2@N%`_pjl~$mQ($tlLHfN{x zvJE>a9oFntA(_dP^=Tum+nTB8Dz7**XKw@rv(|A@wXON|1bj|**aG`fcR^%g6=W@#E2$zEylqm65-q+gQ&y>-EN5sxrf;D zD1(?x0;>};@w?}6xq3k+qFZ3ujErE&MCe{J0sptSVODTMltf>ja!^Sab63ss#geTY z9vmD{Hc8yuNeAIV`jfn7?WT=o#kPuqk`gPv?8_IrFod)$E&%1g6xm=V!BNrmWf9s?|XD zgS(ir_X(6Uow-bjx!Jp#>Y0+po=<0~6u&L#r^4?L6;k1!6|qbyHeRMov0_(>hRBzj z_S9GL+EUo_GuhO9j+&kHMqNYI13V>(JwJ*B z5Ve{bnOob?#FTvYm1LG2wMH%MiH(*?)J9*OFZ;p9T`Z%bVvP?k2CLMDfV&}BuNJET zl!*6Ypg4H2$*20WAFKlsDN(JZ0*p#sJaSvDT3LrS6F7PqRRYV?OmJmy8#hw+#|%?W z)Cm-!qN-Y!X^O9IsA$^mQ|m>_OjAm*zSHkcC{w^dd>;IFK$%YLwy%`&|~ zWi>+mzJg^F7euC#Y{&PC!$*qPjLv%iQ31$RU$a_U?{7ec?G0)} z^B$H~QB%9UW>;;suK}5B>zjDy)C!_)B%^hH%L(9{r6_cZ!gas_Z!Rm0f+nT#oX?ug+pyB36C|7@i2 zDMu*{yYzmkT|tR+kT_kRT01Kr@U5;=Yj+Wnx^K9e#m|> zppW@>1!)2b1M{ZjBb0mvUd_M^7hPaVWuRyBWusS2$*U+?pig$YDX}@0D7)E|_)nB5 za6=syXyV<4F~7=+gsEuHBn)HT^@x0uB3+0~rO0idL$#%VdH)ndrBM{1M%=gJ;+pp$ zs`d zo(Fo)n3__ov1swC^3ca=LHmx$;$2xJUXgX=_H?*&is|n){O{HLudFI`#6>AfWySQo zoTuL)VnRpknmbpfiZW4us7G%pHB8pSTieznTXj=;iDr!!uP6`CrM40Tl+O#G{h<~I z3pzU8?yyys+}ULJ?odS2Lq{C_ZW|#)v-Y!0{CWrf?OZfkUczfI+7))+R>QI=mk|}Z zg$5rBrg2m}LxHF1Pq8VFfzQ%+jn{zHJP$dC|N} zB;5b|?gVi~eLp_37HdJrc(~?q;l^CA7}{E|-e(wtTA8Dt4Plyui)~`8U%32v7byRN z(A%!G>pRL6_DtZri<^d826p^;X2S+of%Aumc0EJJmaVz*X9l)IH0aJ+Rp8 z9LO)VbeDOr@4gq`eco%kzv#WDyW6{{`+4tm-Mz^3R;gv+bgAWFnm6O%Oz-@Y3rc&G zlULK9&w3XeT;-j5aHDt1$t}onzjxY6U#aEf4m>v@?qRR<i635d;rgX?_K!b5j_6_&+mJ$dS5BEyg#ed z^4v1-b?>h&Ro+Mb_xB*&?!D&yzeD)@2>%q}lio$F>j+brt)G3J5L#pl7u$7;aT$Bd zg;^WxtqXQm!lR%@FP9xy#0D&-%D@72z|H8SB5%$>1;PM(;0p+Md6y2nSgNot2Qew* z)3t#0C`QP5aN~*S8~+?|u>n@vV;OLi_E-lpOM7grYbWbLF(IT|*)m2n=`nm)u{-!1 z`X6Efltv$g-OCI{ETZ^dpgrz`HHY!B>rV%!vwN6&$G{z>J(CCSE$vBWU0+~5 zC_vC{%+RfNK|JkkZ>xbZG+J}tR?JfkVl4CayX^#PZqGAR-41X$yOCuF(@DPFf40xU z)O1RB8|jEtz~&@Nqe;XLtY8BUOqE#}_2>@#xyHModzp9Yz)gr8#7ifLIn;ory2<)Wc`pb z99YjgHJLg!Wx(Z~IgsJa9LV&}8kpmqJ&@(SVjvr%XNh;tz*6trfn}vV_JI|pJ*fjX zmG-0!tn$tSB~S*|;9Eq4s*IsC*o`Qch684Gb+|OVCgq(k48wV)=1RR}i8veH6Ba#nuEO&iH#E z2@rZ`a13G)628n6>L!$I{t)(J<=(;c)uA~LP!#(dNTc$zXx>a_T^@$Nys75KuRuqc zKkmn<8N@(Qv;5#5C$9LFyxO_*J{FUL`qZ>vd-`6}NeT=nN zD5xMZNArvp(I-RyNXZiF!udk^Nw^<>f>pX0h)1UZwkHeAjs`-FM+zj_)I0 ziwUb7pR{6&;gdp%;@BT&F;jd9pUt)-~zd+in@7h}5eauKk zUw3%yvAnI5={0+A>mvF++uKD%lqaJHz%OlHWndbYNzrc7%9a z02J%Wl8Ec{IEo>A7Vls+6wik%mQXb2QrSQ{#uy-$Q1S6aCC0`Vh13LL`48pN^VQF6 z1wLORo3=SntNO4AZ)&LXZ49cYZ#7G;sMy_96=v8UDL#Eu5!^V;(^jJC|~nBATU!ZDWyl0Uq~vO3gbD?rL4@A)y`{U9s; ze$O8jhQCle;O{X0YBRLg{W(Yd;SHzP`@>~Jeyz}ktRLe0yH3w(^wSx9M~X#NX5j?w z2^ZS$yGJ`Ih0)LvtV}m|Zaw`98o>HIQPHzuEAQa2+lD?5yB%S-{nVStaENHQ=5}1*2|T#Fje@&7<4VHmoM29@LA!Ic|GsBqKB-e#?7%wE-0Rawu;6=axal10#;;0#AIF3FMS10v3meSj!f zFPJlCG1XrW^2PS2qu-(VDG zJ;v#=3@1vD|6v>mA% z?jm_)t35Kwd8ntDCziWAtowR`|26nJ2KUQ^fZSoN*N{*~Lea_UvQX5nCWWGp1vA=) zgK0Zb#G8?K?u>32jr=Th&fb!u^=oCL?Uur*XEbsIF^{IaWJh5Ui`Lg?voc);w?pWk z$_MWu8b_;tE|n}`-Buvk4lc3CYaO_;)Y|PvxWa4g{!4uS2FU+fI*IA20FFouz9u1% z#+%Sv6GP$SO$3_~9B=E!=?$?n6q5jF#dyUSW}uHWsX|9HyEafuAs&=`4D)w=xVVdC7=iubE-z*KpSlEE{OLKXm$WUot~&ZDjl45B{7p^OK+k79W0Fo_|ArEAAx`c z_A_=pBGKJyFsnIn?n3g>CQlxVYClm;V7ss@jp%gn)evvTZVlJ_R)P4fG%#02p*>p-8B&)0&AND zi*vYOhPJ^4EjVCwzHo~j=_Epvej>beG;idQ#d&{t@4wY3dDMg%8GCnmhBv5=VoJj~PafCBl4&h zm=o)5?5K(rihQ8SJ`EU(-_=DUyYAHKEGdDxQZH=P_@)koc)ylJSn@-h?nnavWbN*> zbJlZi<(%7c&Mjp9c6TbL07&AjXcnV+Jun5|EAU-}fpQbbVSYR*H1H$Z85=J$oG5-K zG8^W_@S`u>%u6_(O-sz7g;GM~5qr20#b*fz7p!_Z0g-b!p9r53M@)v|I4@8zLx{*t z_gV+$jvXCB9u_;_G(5O`B7%DooGn`?Fgh+RpU6#k0MJ#bj|y;K)2!i(y`pvN?`-RN z_JxwSR{cVZ|OCfcIS+7uDeh+2}#QY>IhSR-Jf@7wvz@m61NXH#`-h}5Z z`UsKuhZ@F=e*_c7{|6Jmf9Ykwzm99ed}bVdkb!i-L1^pxJx98Ca~be{h+?$Sf1#h& zTUoHC^-+Zdw_(9hXaNQC+SlhD4wg{RO2HHgu0hY-XQ#Ln=XZ|h_V~kVE&gzd=!g{R z9?cWiIf$d&=srC@avzmp=}1PQ$8vt@=IUvbLD>{4FS0C=;{4II7UwH#d5f)ihac_T zp%`ML9r|Yw1dM{Yv=?F>aAG8E16_CsOyj%weGR|A@g|KoA&Fi{p~j#WGVFWmrit4A zC0DGwb6shLo&J(-AfJu>7M*_FYs^sSNbG#Bu1jXApwcgb;VQ#MV zsdCH$xN~8W0l@wO0Wqy2s73qcIp@860SB9{Du&`3&)ZDm^U_jm{MHc-)>w$;u&~6kI@b?is>C$C_+MyF01fZNrnT9b(d&?BsTL ziirS%X!=8sWLt6`bMz+>IMQf7UHsNG>Aeday7o-TqK<(_qo$ppF0(WhTW6;taw%!inm4E-4;|pzt+%^Ihb%{ zTogKTTxfncoe6y$4JK=Isie@y`N5Q@sb*+up!PX~@;sycp5ugHdLGd{$HSg?`aLJ8 z!*ZjV=S0{u@O=*gn&%zoA!w=3sHvfkS3BFDLmVE0X-^Zz!k(eX6z3sOB+roM8E_tg zbm{p}^9-5U0ue3GZ}A<3HhZWD52x|)Aw57*J%~l83Bg6dJ!4)k3T|(|FS)}r)Lv-s zD@_n(#B*pneCXX8pd5))tT1KtTCw`BP0_76A-A*f~t|v!`FdEHmcJoSQjs*8Hrj1q)JAuDo*L!tCtqMd{OL&B1ShEX*ME+;tiyM%S$M_D~%DgQ0~VcMq9El|A?pBoPTrU&KUm|ww?*fPu>ae??uc3 zQd^={7gg3**ZG)!QXq;8Tfm>>Z(BrF}s{ddJPq?Z;IG!iU9!cZ?pu8^69bKrI`*C3b%9?y5v5J z2IYD*I8&y{U3>mM@=fnAbkL{@-x|Kp)?aA<=C43-`%GF*EaUe+%%g*gbQ{i2x2u?T zrg$ORQ0QD#O%3PvyLn06&`!5Vm9MH!(MHk$<@R7%A9@(}ry0B)t0<;OP2(xVXkeJ? z3iT{SKD`{+D5UCTxngC3StAp@V%OVdw5!}e23I4L(=L*wd#2YuknK$#2!Mz-gNS|( zzwMYOUqbxXur~OXH>LY!NQ_7E`(u26>PngX?a<7V3hL~WP7ZL_Z#v^MK4iG^s=a}3W zE223jB*h1CVx@8$W$9|7*@USC8LIUbiec)EK0b9=7lrt;;M5#sdU_w!!_XV5)3oFL zNfaP%sr8;ByOtfpV&IK%AxccjBGrz;aOwn-haowoz;YNrp%Wv;ap^rsFNJb-O}5LF z@Pp_n4GEB{985joeDRL#shXOd`4Zw-#2V^J^J^~WE5FS9ftu_O{V^K+Pk-p9sQThr z$U^`j+4;&Ad*p_*eI(xSP;zA9**+3Zc*qu+9{R)TM;xI)-2GUJ^U%H7Ga@#;Vu5(% z+}8lGhWiyYeeZ7wwD4SlHTP`+!!*AB)dAq5DWoTeTeQFd7pd}5=#K>O^aUvI^-h)xU$!o>Ff~{MF81eTI1LngXH5Vg&14j8h_*Q$9 zS=SRpVD0?hV=P@s#pak(c~Uv3OlI^ijXkSe!NfmB$zt@+ir;1UcQv|guW|#sfi1vO zv$C8mXZc9oqvWz&wh(a-DJ$3tmW`)}mCvxxutj)!MENZHEW3}*V=c;!FuGfexJQ+n zV8wL}o*q+fW;eq?EgEfAR^#l}YH-ncN&(x(3NQ_qDQ;H9+}OjrPFcgMVVY)RS&E1G z7|v_4sY)U9vqF~47AR}kcD9zKuq$yKsRo8=cD7Ji$7>`s=>ZcsL|2DXtoStgEFHL_ynVzZRH*n{jY z2KjlHM1=+!@pK3XM0#Vo5iLpce97s-E1~nsw`mZly%BJ<*$`1*OKM9rT0^FjXhAeui@v1RN3rPv^2wf3Zd4v%Irz6vdlkRZsO({D zlkLe$TU1WO zM{NI;=mbh=^tI!WbV0d~OWuq_99*$IUq2d(~#~h z7nD}dXH?tx^-=3QVTo~JwR099#@Y63 z4nDJXaP?UG2}2(e(p~jL?xmzV30+*&XcW!CGRo99OWo#L{IE zqH_AIo;k%@e@?H}lL?J4p7G14InTuHDFRwA=~_m#KKl8i)=xi#;|zK@hlfmhfKsMx z4p|cZ4uK*3e(2Bn*l%sYW6K%J?a%4+Te*GVFsW@c*cf&~(?d((r>O@-z4~6N(4=q^ z3JaOC415=(_eImT8PQK@$zhjCy~XLL2sS^Jm__%K6X>h!F4|XyM)hL7WLS(+FMZkQ zr6KC2GT3F4+Oy9ynnhbFq&o43x1QVgW-z&Dj^jujcD~S( z0pyP0Hxs{qMA}emi=720Lw|VKpF^2Gj7;JID-U#HLXdi_6Skf7HR0V*UcsJiHqadc zy2B=PvsODx-W90aN!Yf7HrObT=w1t~TS0on4%dZNLwB;NruC0*hC8lp?!_ihtS`8t zf$9}jw~--M^h`Ut4ko&=&fVakhhcm_^ji;Oj-8>|Ll(M3=0pwV4lN2g zt-sDWrv&Y2Rof28A+n2USsveR%CYas^V)rpW;tTbawXcV>rD8V)?sg-~q=QO+GcgzY*cPI5w^$Z0x)2*f7R3T43()<)-nBq1i-9u)J8eLJ)-|*%q9B&iv)4jWrrC1&77r+R#j90>YwOC z;3)|;_^4K9*Io^sutu}n$ZBgNzKih9#dkHn9ZFh{TG?(1y{d!`LuY_cNnFUIhcrsN zF>OH2fx%9cshRj;Q8g`$cWt4=w#cu;md*m}Rrs%mXm%%!_dD>V@xB~i!h45(_=FS_Cx8mWx2v%HOKjr2VIw`RXYbqGls%GNL9UDhUE@B|!ti-d9F=P~y7lGHG8es>9M!*0|Hd6NX!%P7A+!A~KG7C~+o z++7c{%{t!c@Dn>l0PG|e4ay8f>G~QBGm;Q*p)>}SIQ@P5?JmTnu>HMav{<%ZXQkXnES*Xj`F%aO%}xfpBd+#Q8086GzF?Z*hQ7yu-`P2m9R@CtJN zuQ7NpNzIoKyd9q)yfviPtk&UOD&ghg`OjkjpM697BjmUEmB@b?q(g^Kkki94_%2CJ za|pi2KSB6*HUhp%9lq<0{v6Hi(TzNH@n zA7a8v`I0y0k~0==LaoYUpCmr`l>I=*$BhO)M){Z~?e)>$%+-!9@A>fCId5pM%V|sV z**tY$Ho;B)TA_V4G(dC3j*}k6Ol#)8SDy&^RC)pt*)q9*_X-EV`=83f0C`0 zb&C3cPpNUT>h+1JxcX+om8giO`l?Wy2z}f)gE?X;v4miJUA#Xze0Z;M8`p4+n(9MT zTz#_vpU4S!h^SD#!A>SEzX90((k5D53 z<~2}o8t}_;A=9dAjik=_%8mL^5Y_j-30_3S)kl4XIQ*C3as(sT#=Fx~TFwj}uZdKpgC2Tk6kwXIT5Dk~r)cR@#M*sN#JnPjX2JW!Q8i9!8oG;*^0a!i1Ilw9tjMVGcG^@SkTbf+^DZ3bLH%yEx!N`0bXFv7pCSM#u7#Q zMd;NitS8@fzK|bvzOV_rnJo28JIbcHbw0?LLOOwy|HAm?^sSo_tKoP{O&L29L8z#$%SsMpZct4Hx{+n5Fm@J zR0cal1tb+aum_z4ffpO$P}$VlC*M) znx5a`!d~L0We2+%WAi8N!Qw2PbzyY>+#$#P= z6Bazu%2{twH}IfuMe1=+Ag=3W6KbH@*1g-dOvbUyRBcro;V+W(3jOf2FK~*p5~s)1 z&tM{)yQHCW4Jbv-dO2c+)ue%Cdkvjl(Q!V;Pp7^Wxecm6IHnNRz&l6_S3G#99>?9_ zq1P|b61I(3;RwXtFj=`DGpqqyN4xRdg5M{-7S@$XW-Dd&57am8uFn$Pv@#23 ze){o)r-2E+v>jvFf(-b``58x#fXF|G9!-G4j!TbZb<`SoyA#}lpGC)f4ca4?!nMvr zIyusgI}fEu(gd#pD~|_l``!-z%6X{Qd8mx9goIZVkRu#7@4hmAaL3@SH}gj{fWnE= zBZ$9=&1g(*+H^3cw!Y0M>*ok4F^yXeziyy^Ja4OO7nl%?e8u#}e2&a3i3O09(+dYo z)?e#m&mpbe`8jKhr|tzn$#wXy#<-C@NzV6reE{h5okt|PKRb~#)}*hAaU@t2E2$*Z ziTY>=RGKg#{NTdtj`dDAMuEVEv6Ye*v=tRZ(mL$qp|7Yttsw7MU{LE5g5(&VFcLmF z9fds`mPkG|QTP`8*|Sls3V>C8GA`14EY@4FHj0~qx=fsk83@-sI<++o8B!Qdk-~86O|YsJ67k7#Bx1cku$ryPF|=(o zw3aK?=~jGJ_p!)z0$RT-#@#~!K2 z>W$`{A4-}syY*NE=dAONKbqQ+23oW-J@|o~lZCl&lJVyTM|i^-tSUNJD3Rp+!h)#h z405N#IZjJzN4nN>W~EadL*1wOmw`!OY3>##TGA%$HoiF=i}vp*mxLgJzzo}?0?)4Et z{XUjJ^Jn$+rQ&KOBVE6->00)@lcn(+j#f19Y{DR06Vs#u@H;7!GHF&PfuE$~onA1H+L|L(iJX#+KgY%1+ha5OZ9g z>V3G&3lrm$oYeeoG0fugr?rc8<08eF!ng%Uxeyru-sP=N4w?YQiznG+W{abR6PmB#O(BkvGRcnM2eInQl_cw{7J;DE^z%=6P3(D;zg z?@?o-%YjLWAOi3NYsH_iRYW7=o$6<(5S%XK{-rrV5%uIFnpdzRuAXa*dNkZr^yk+U ze-l%bX3+xKsvTDSg!(x1NE)V#HWIo;8$sysPpP38ct`H^yi+`QJ*Wptpl6B}IYURX z1gOFZ%R98HAOi4GtDYn8BX#3=Es4j&RT2-$6F~wl5-NMAI!yLpOed}Zaa_#hwL`;g z!_^b111mvO@8WcoPTbq!#>CeBRm68A?qz)6!S{WTkdM4+2Q4^rJQHV-=XmY7R7Zi^ zk{-*!LT}2+Dn!;G@~C2ldB za|}P_jKkdg$`lY;m^xV$ZswM8(yG1(k4wGM==STv53VHx^25KenGtTOEc5j5a@zG}c2( z`X-XR3;~f%L2XqKl5s;tU}tSToQkojdQ`C9*W3snT)t}Xz1sR+4G;K=>Z|GAM|!Ke zVQpQ*w#vG)dUA<^)2#d$$W$&A?Vpd%&xD|f6R@Q~H#xtF$)aaL6!vE!$1LPnv!}ii zn`mxeIF_UKTeyI6KSs1N5s~&dMvGqFCf`^Im`lA$5UFq-B2%X1SGX(TbHiQdtE>;w z{fZ?R9fE(sxmW{m0r%|$(K5^~d3#62CZ8G%)XM}nCBVgw0z?^z6mEY4-=Q>qc_c8j zKDe{7w1HR0O&5*g1ma|IkR^>*a7Zg#cqtZ0yQgJOjKYG zxhx@DcqlC!^~^P=`5vsxZU)mgil`npTfOhW_-rkdZ4pYF7b|U>&)*R6#pnCVI4#0J zqg=b*Ls}QVgz z_g$>Q5mfja?lul6!{PCk5##Xq61_I~bf(&_99vro)%I1s)lD}60dl@Q1?wIzk>q_8 zlueJI>CP7)wmDz)+HiCcZv7YjeE6_St=aoN)(&j1Z7ekzD&iyHfE>JqKQ zk>_=&z!_9eZpWlT2gm;%<~Q7U1Bah~_$MxY#jtzT*?uC3>fB+t=Tc`5yU`g_b|}$c z26Edt5?yqp4GS)T4%4NhsP8j-KW@eAyPehinoKQ!WH{fZsNz}$BQ8{AQ;dL?KLd;ujnU&K1m zGwOWtKHG3_mRd-emFO<0XqFq<<+$?4BS@6aT>WA z*b;BeAMVXpGxeU_`y1Z3z0N1;0?;_TVdI9I$Z%uu;Ug{_FF27>q)skUXB4S(LW34H zD^h;f4z?-!Gwk+ZqhklVYg3e;B7`TsXTR*7^6dA#lb(%wU4k^&eug}`J&(U0r3djM z9(bYYMe6h-bruymmlAoIc06smi|58Ur#HlFNI^6@<0TpeG^v7c7<5i6bA{ebS+7oB zug+MH*8SF^&PRVlgZ5~d1LC{!3^SNAiZey=G z7;lD-9D(lkrF=AI5MSCXhg(H*q4;8cvK1>MW59$9GGjxkEGt}`VG3r4i!ov8Jq>+> zmz!;JoI_>vj+XDBt_gdNpY12vShZp(bh-1^g z^kxo!08xA^yan-Z`NPebIJ0~l(f)A3Y>IEpAlpF7kGkK2D!F)x{9TIQ{`@(=0O~bQ z7SFOm^JMdfn`pSuOIdI(z#p=ayD#5^toT`@lwi2xG1P-*6Q(d|hCRm>bq!x8X>crg z46C6bJBtQ0F`G@fJ2(w+Q7Y^r#7!fEB$kRd%Z`OXqnEPa%_z^J=2E^4EaNyH^Os_2 z^-i>L3CbJ%*YOIX2@*qBerDKnMDr{Odyb;9Vb2dcJx7Y+cT}nQ(I5XydQw%rGWaI1d5PeEUSw~y#p=w2T3-+#_z@8=M4KGZ zrtD}_R~`lDN1JSeAyFJ{O7SuHJaqlwe>3_$&o2gQ`#p5OGoumH z)4AdK&^nvtrH2vmefonDs=Xn`DsDC6ub-eH+=?_FEqZ}Ss^0oeEb`!7BEADCKfH#H zMFqd_m^XR(uzR*eT_QSZndau6vEG3S@ISn1CtoX7o}J{K{N60D{n>TiY44Tb_lw?X z&mQqkeQv&Y+H;-W8Ms;1@?5t!?YY;z)7~G!rAl1Fu!Dh7r@C$ER6Yk4 z+-q3t!ycwC*4(Q=+b!y>;e3ZhodyYH=_VQoP5FZx#4CMn4_4CfGHdFK*yA)z9QP8u z=F*Dnel25)ACt6XumbOvmqbhE!1Xn-CyYTrDec-kxjj>>rC1Azs?)8{Dkjk=jcyVb zN(S#ctMfBVhS9Jj&o>Uc(a@#N7u_x^*+pGRULTO3u4wu)Z!5_c<~Nc;eU36Ig{X1hiogs$&u|mPoKmO$4Pq?%^+~f+KQUcRLr>xG;bs?*|cAdJ5%fOK3v^5sn zGXx0=^Y`aZRai-xck}m%#JtSu%!ZMdDVcXA_R#K;`9Q)q84IE1HjHXEkTQtRc5B%gTw<^QYg-UALe0wZ?PL5odYJfblHGVji6am78CEl(Y$$?qAV)lS>n&VApe;786E zZ8yTfP^ix$o=)Hi+#)oRD1CaiwzV8d_(-xp+<;sA*%A>-L zhx%;M;7~MpeDHAr8YHby%R9`u?|R;ZAzX~gg%v!!6E23dG8ArH77o5e^3O7wd%#Ko zpObb-BO`+r&PEB7aD)W;rxG&qP_cwHDb?+h-+Knxwp;5?L%Z9dAiK5grO zwqbDauRn-JPkoD{NpJPO10o0k0+%vEw4vDtdN~p<$mm2IJ!AqZ?!0{Lycv9%))>aT ziOe#vq2i>9Q4U^j>%rApyw?>hW;qzA2@EX1uE#*b_Vx(LZ<)Xxd^bT(glWNw8&7=z z^l4j9qqo{N;gNTvnRbvo09)&q-qM>PL;@jLfh~bgf&4Uq{MZNIKf`I9$e{~ozr?Ox zytHr>G2==L{C<+H4y=!w1Q0{g0=7jlO~5eMuI zo8CZ^C4=IAvw{#i(ScakqemTDepUo_47hgw7IyG1Z^p^5K)?OB_fRS*4Yo(Wc_nTn^1u+NNxjG0(e00e{EDJ`?J3;K@Gt zSzcD=DbP{eKNIqtaYT;r5+8C|TO8q*QEetl*~m*-BTC8ha*=a1)b9YVun&I3XGJE} z>)iJ`u!UMUDToHoQ2I|q`l;_A303qvB7e_oxcfTmR!4a2kTwk)JgA-x7bMx#RBb)% zM^1yMYn!s1-zhttcX*dA=WwKsOixN|+NAJ?!BER-WtY=i9L?P{ct2hQU5&T|Y=fHy zzs~E+fcu$w_-QuE^A!TpqU> zaig3RVC4e`@uN6B5d00Q)D;NgJhY;1afE(T9QwFeg{>ckUZ~j~C9^*~YWa5SVU6V! zkL2WoN}quPON!>yoCYVcVu*u~%}8gmkuRVyrsil+oMG&&%o)jn&6CFt`kh5H*^cp_ zZ`Yc$cw7=Z3d*?bQ=|`Wi#|pvkj8}iDmV$;2Uj$n`Zh{K1;3*K34R0;ZpUmn^;cAh z6`bS{buXyTaDmOGR)9R97Gf|w#-eWE4~{H#4FpoVdMp0gs5u!{H?p0 zL2|xo!&tS^?mtG^;J`^aQny$jTwH+Be=jA}p4DH=@kLMMtsBl$tJ<20z;5SRHOjo|@+ z%s$&^r`M;F=dEb)^k9zO!qeQY>IR+>jf9w(fpIxRdA`I4gDXODI}{#E4)NbB*B2of z$n*=r6sUgEAO;@_y;l@ESA=%#92D(9sW+KgJrru5!-ysiVFfe07{Ad*EEER^*A5X0 zbwqBW02<56BiAA|)C^K4vy-PkWJiMr2Qy{%R3kgCZ|Dv6p2>q$_xQ_zkINLa6-$zf zmj(iEhT!gu7Xs6vzL6dFnm?f)!&V!-f+u5b<#rKOH3T#*-(?PDm;;$&{e$xRtvfnqr4o%qa|B-a7oE?rHse<4ssQn3ZTW#>*Vh0M>f8!LR?8 z%81Eh5YtKqf6mD!uDnyO=s9~_OgViwHuSI!cAnscx#W%$s%RSgk;S+)nJZ`L!W_4F z)P1X?c&u%{O1dz~ThIckdm8GN)ByN|>3;^F%=4s~3896GrF~$c}i$25R=%aLXWudB)%xy>=*5);es? zeV;>V7-yIjV-y?EMK9&J&qh-#u&9GVh-PJEMX1HaAXW!m!6Mk$KE(O?d_noM#1E-Q z@cwB&73ux?p_U=0PRe(WrT=D2GvHUkW)eE1o+UdJ5G(F z6t0aLAvMqtbh#X}piwcVft#2}q`@K-g24t?7>j}rsRPxAA$R07bE3WF49o{{-|eXm zfDDds^Pt`lHkbuALtq>oT%^ab12-^OFr~oXV)DRY=roRcohPT1_9UIm!M^gzyYO^y zEB4NR;&r??9m2(IY&)~AAog!FgM-1#8l}J3t=@B6+ znXdvDbDYKxzEreY48Eq{QNy#0Edh2QjSXzZDV=-yMz(`AXZoiIi=m5szHpIru`7=~ z0{$WDZDm=;Gk;*Ok>S+^KKlFj^K^P&d>SDCU+lB@BI$aW|HKQh!2-d`Xotd%UG`P= z4YZ|vE7R9nl;;30^|qHPup7gDWiSiaf^Q9;pTO@|@%zvCp1|{ISPBT+&op!*5fXg6 z=A36bpl@26j0a#UwtyQCh__q}1DTt&nfAv~7V-d>V;HW?Z82W~V#h6vMHPrRiDf0qv&m{8aT9LQukC#t{S3V+ef z&6Q+e@a=Z=^fOk3wqM-V`c|^FRzCq->zoVh{*SY#%zlWiRYe)k5&(OZT{yc63ZVVU zx&_KEI~+FKaYaVIn~%_bw~L_fchhP_Dxg`|J*Rs6)3{B*TD?6y4=%ELAHtba+%Ik! zSnO54X&e9%_`+d`#zv;&YuEOt67zlgl3`6ZWLVSLSPBM(aaQ<=Af3}U**u)TM}JW> zh|~&yU9hPJMhwgadjs575v=ox{djS$MRA~^YISvWz}M8o@7b+wT64!8Fj(Ms@gx&{ zN#R5WR%wbg111T$EiDkNQX2y9hG4x~%njgmBUf(IP~1?rXJ0*DM(oL`O zWTJG!ph36RFmmKjlC)0{wjHs;yD4opteL0bHFt5bPq!4lgC7Y+;&ddYBT=N#jUP=k zlwb*=Se%GAswpnrL{r;H&?~7%0?Ah}gHS9kdV@@ob;|`Bk2IVuWM#rrVrC0K5`nB( zrt4{jc?H=lkhL#$kp*2On+H1?wYG}xyDJ8&VlRuvZ}9D0T?hMSZ)Kn<%lxt^R=m7r z8{W>QRM}pUNbk@^c*iMa0eWvX?|6}j;X?*Q>tLl3sIROe<+8l*RvLtmef7`rX4gL} zNE^fxBk2=sQIn{O8-CTv)!Jl2ueNR^e3uXwLr3@q#}UNx7x^FaYeIPu<@--`@-~)h ztjc2WA3(d$uh=oRV(c%PDsV)P#ahhGA|RF0PNYM#xx|7IizB&Q_!hpnM(*OLQDFav^BOQ2sv??eoR`-l5o@1tT2-vRkl ztgvJoL+%N(i=LaI4D{jc_4#Y)!nas^WkjOwg`9R?d&k_FCYT6l-x{A^nwwEGx^Pm9 zy9wb7Mw8bCvWFLh&^YfTg4ItI!7k7^l8R@;i=1>>Y`8Zbds}I8g=Y)hUP^!IC63`m z29M7$c)XqSc;J5>4sWLMp1{*2Foqc4{|d`2tLNzRRSUw3BP(DOpsEZkpu{K7s32B{ zcVTENrB&nAi;?^E>}o)&f|h;Lk+)WFhCSk9~QOXIg%|BiPfWhK!}W{aU$#q#R(w5 zTN$iVsj0p|1`@ljCU(Ua{+zDsXU6yD@g13T_-_6QC*SVNOHye= z|H6&rq5p_Q01ja_Rb~(K>fs`yKZ&;s1=2GWOdoUX{{2r=6c`koBYXq=vz#tmH^uGY zaqPfWhC4n|aPU2OU^$jtE5Rdf15YT#($$Oac6@i2TD!jh=Mvv2Rl2_ezR}~g4*U@D zKgIXg_`ZwNMZd-G@9=vDzc3p(sldp6I-Ql_&M2rU+!#1(<1SyoU)QjEfli(5=uY$& zeY?b6m;(2-OrpCm5h(zqOnRhwSw!~MY9)D6`g}XY$!9DuI==X7=t^1*?Z14hA>kMO z2?tBvr0RCWFA-T*&Yz)ZVHjgtff#KzMZN+qmBmT${2eg26@qoKbR5;Sn6M*^JfTs6 z^;ZpSbEV9I5e3ocRCLi!?$N!VW-1aUQESCSB|T!4Zy_TK(^NWKsy#VY)_I{MZV`bci|*sHf|*z^qJ7b2Ff z3>A@iuLe`G-zpM9e~7AoxLLujacblvsMwT9g!>9@qQmwDz-~oseF^+lR#jnDM)*A? z@GBxNf!|Na|0%{HxPWK@J0{(O${?1DI#&K%2dFfjs%o0Bs33TMD&Q3npANiEzV7y8 ztxG-TJKHjPSC3B?y9}*t?^r%m#|Ig>yQ!xUt;MJSu zL(}^&3m#~`*EUtED!*UoUxd6OA}T+<-mefXVBK=U%OGyp{_g@!@=0A2F7~9(UMJ)e z9=?RH=uc>-3;BdMfGv~qi3nkl{ojR^k8kj6otpoH;MWv<;8W>a!LO-)_N3(3Jb>Fo zE(feSyaC*MPTkup;HBWF2`|;pzA5450h62aKbvt8u=vpY4fyoyv;IxYUlH+X&fj1? zE;)RFeOJz3(I7Op?!Vj5G=GCTE1UTIT_xr(4}XdhD6gOGlhap(7<>D_3#!q-0+}?T z<$W3=;(t*8%I-E@ukq)OYwF+Kfm)R>pO=gN<>60f1`GPk8^C7C4i+KCj7w_%Tv+w_ z%iULDhtk+z&?6GvUue1X{=ySiVJE;J@cGD}0I!GiA*4S>1L(2Y&*jXRirQ!ln%lKk zDvQW;sRbvD=!n6vd#X)MgWa0c%KGvF?}qy z^k(VKT8D57I>jHleX1?OjsB*GbHh!x@WVJeAXdK_16xu5aRVFxk$ogXJ&g7WU!~L9AR0shGq=k`cit3_fbU}M7 z`^-^XV*%L4t_RF=Y1bNlKc~dI!lU=NJitrwi5md07x#=^k4UsX|8@dU+(Oni1cbku zuUdCDRKqP@0I}PBs#?3#XSgXhyt-m|5}a_4Wl$L&p`y(ML)X_N@Z3hy0KD8v2bo96 zf>-Q67RcS3rom-Ygtesmnx6dxJ{b%?7%E?BA3)X7bXMS zu|2dK+d}(bUG>HIPT})kLK~Z3I`|2Ws#_<}A6H$VKVa@t-OyylyrdL*TL7IfGs9lM zU4-N@C~{ziB?B$6tuW&Sr{KaiI-v-Zjv|da%b$YDwGhZy5swUHBKj=mwn3jo(3c=C zzBmC~+(2|iurtZ@NcX?<0rC;Tjl=}ap-5eVfxt?4TIkdWIMJ{CB$mgW;-&gEcZNT& zSJ5sk7JtOMZ z9(MU*CPQaVr4-$Ep-9fYrz46z69FVE2>CF^5g#9dX#bm+<|Be8TD7E!GT9fB-G$rBC z6+Z+h&Vv>2NQ?Od#DUonkd9QGQ_8XC%M3_1&cuMiD&*(zYPa2rYw7XeK`l6g4I6w1 z3*Pt&Y;ahlF?zebIaRYptY54(I6MHvmzU`{`TZTYGX7_&F2m6+zgY4 z$co%(B#9?d%3|aI7eL$RT%^onYlApiVTZ}baKzP@j58loU2vW=4BrqqIzjGx$sUi( z?Q1!+v~(ZDApJwElL?>l!}}W&p{c(q)bP|zf37u?>}!4O_E_WlKW4oYvss$Lz%99{ zjV`Ft1XL_0$ra7*I%36qIRBG6ZY*PIh{udQ?_)vy1ztHX@Bc>pF9!Y>1D6#8FrgxI zF=0l6;7Iujaioh=Bw-YYGd84JwHOO%KtMZXWTz+= zV+0e$SP|1$Tdh`ZBdie_vx1DtQo0b;^>v~?ODOez5GeVj;QzRfu-MH9<0U$Zuk1Tv z?ss0_QTw_421k#6Tya1>$k)Tr5AldZ<+q8fzpi9BKtU@lUP&#gC1#>W-~b5L_qvXQ zn!$6Rp}K^JILefbC}TM$R$?ymf)z}e+gMs5%j%X|a+wg9!sS~R*zMAoOh|aqKO8@F zvIY`+3_mg=QT*IJ0SR%wS-v%fF9vCazE+T?v3#vS>j-?h?xWtu3al*mKQ*q{;eK2q zH*(3U)vw+EJ3Z0dRX-H|tGBdTse5LhD{Z3zC zJIA>y-rtbQhNSxuwO<$_IRnm1+%u5r*2b0o3p={qh>Pki-1Tz?bG>obo6` zE?Y9=L7~^VKG9DUIW~SMl;{b&f0@AgrDEKfW#}?+Wt30dMOuE$I-zznm_?lC4xLH+ z0ld{zWV5ae(U(93z?0}-NwOrzY3u>G5`h(@{PQ=~5Q%7OGirR-E*PWEr(iB>i19@Tcrl=dtYbyC~gsQO~P|4?808lkIZ-)$+}u^(y`&b zR@I95*v82H!hD&pKD1gXVU1-N##e<8mW`cUbA9hdmW961j8tIm$ zSifP2j85XCMJjKQtKB_gUr$RqSMx~KPo#*{6vMVQ!bO&v?B9F)RA#9mhRhFoaI&Qo z;g&kFisPp9>Lj_O147{DitB{n!~koo{rhR@$s*E+$E)vJJ2N)zJxpsdHT?uHBYVz2dNtyh6tcFRfJv1lSyRIQlLjkt$E<=b0gK8tXo^LZlrhfJ<@@;3(6 zdO9Fdv5Qw_y3Ext>ZYa{>WEI$lm-!y#~Xlap&l9__Bnlg_9^5GR2Q!wk`am0V>*7R z>n7q?sj;=`Sp5)HWlTi^oLa)c!yW{u!8Mr(nswb0EE~YWjd$@q#`zseG0`gu)jXBh z?%9tg0Lh}5b{0w_4o6H3Ff=eRk|KH)uyp-ILdG5Mkm7}WHIa@`y#dEbxO3zMCB~hH z(C+7RPZfWOccU9d*K(H)|E~3&`Wzv~O^WTcd3^!5R$|v)xBjT@wMXW{??PJW^=Qtq zaEU$QjHz{r2yFx1^^DvZkxIjSK+(1mFGN0TPDU?ZVbTt=NQ$YX;7@s5xa6H>=mG`r zp$kgn1*G$}Upv1;-aIpkOE{(a7WX~k$N>Wa(8EGgk6TDrLxH#lljC2#3J&9rpn{rV6NIi{0`q@fj2{sn z5@wh&5!smeRR6sIPp1U5-O+<^SD~Z?{ED*@ocwQrRgA-WIA1#&vB4SNQJQ&hZS*So zRh!0l4Ch8t*0yGpnIa&2pft_?U-HA`ms6gcl;GOYv7#_F5JoRMh+YhRc_&M zOX!>ubW*X8Lg}w!qL$~3kTFihIlg7a_r=C=q1e_7mchEDD|R}`QC}R#(uP9kqUzne z-M5?MR=c`fJGa9!ZtkT!SUlUK3b8YqQNmsSm0O2sgW@P=dwI@~v9pP-b>f20fg}6` zgW`8y>p{h9IhZ-l6yWPcENtTTw?sJ6`A!ZiE+u{O{Vf^*u{ka(7borD z9ySW72~yYc3BWmhjCMjuS`22<49B*pR%%ffu0-c>lCc*>fXrb-vaj9hj&7t~&6H@0 z^Mz%RRKs$RXi`$>Tw3s#h1iDNO52ccV;j=ShS&0K$hWZ#iF;OhIejB-=s*fc3j}R3 zVCj4`D&I|gt;4@NQTW$R0Df-!ejd=UfCA9B$2wQg-rQ&>+(XB6k^_s|jqgravgyg*Ln7rop9KVxv5D0v_0a{EGkQRuvX z#gBS(x7egM!Tl-U2MYuPCYOp~>lk^N@5oOg?)dL8RR!xKwicWU$!w~B(PQWQp`%%( z)rq8W)~Q>K5Q`K?rK9sK|*$lotuZS~$TS3!7-E zj)E@0Ld|3c=EA89rbrgJuh(lkc~zKjb(+HEiR!3|3 z*m$E*qT}tO3CyUBczI3VK9K7(s+BkdVZXU}grqa0%~_mN2H}zgzoncgr@`*xG&f!tVBBw=Jf^ zCU(1TWv$z?wY#*Us|WHpb@?v=@1Fb;z7V0zb97(L|Te{sZQR_Z}V9sg^*3Y=>odAtut)RoWe ziMXG0MvB!KGN;7?JO__rEzPK~#Uu=7M~#?}rw&72Koi6G^c2&lQy-bb-%V6fgvO+G z8rO_4YeJ++RFXoPvcUxm@cOr4`+IDM6wE^d^dI3nCI8m(ohq=4@3OH!XBtE#q{h;h zx*q+5sF%gYe9c5QGe_UYV*O8hJ9VPA|`FH_87GZvYy?w z$*#BW59fEiJuB=U)b97goUUM%ei@?9iCtA%xU8${I=X(He}#T+kVBAA*A;91bJ1nX zv9()h1fp+*0U`Ak(>LPOF3$M>^ch~H>wmo|5OpR&R28d$0B9uKQIA;QDh{0m5>=0m2I+3q+^IULz4ztpK;^ z-CFP0AT3pW-R#B<`n4ErV+|fcI0rN(bDLth5RSu&e<;_1m6OZT>>dC(lAawlMB5a0 z_mFr81EEp`OPPd#D;41P=YS2M;46MMazxydQj(F^Evwb8tEi};YRYg<=m%;MZNmPZ z$BQhBP2)wUcE{^W`gkF5Cjfss3$mGVY&csZ2B{5>Zl)2$cmd}@8L#8K4G-%!&wr~A z1f)BXuv;A+&fQ8ecXy#h6eIUUbnxwFYOFE|qdp@sVk?hGY3aKTphzS#-qzE#dcyUM41JDF1*J)OJd2j6&*Z+|etS7Qfu?tMixF!%D0K2B4~{G;`=5xx)|Y)#4Q zN1WOnkH_@!*y7GK9#hN|iI6debaQk?cZknZ9VzmR6EUJfkA>Evift-dqSSg)G2|Sb z2XSj3K%Jmd(N!X1deu0(u(hoFl`UQwLwyR{MJIB;(d5R08VJwmnx}<*&9iZzv4rTX zIgA_hMMWk0qT;)oH=C|AlD>t!7+i5Lf)Y)}{xa;Z!gdpe;uZ``An1tSj-k05$E#4b z2Kz>owW6#8cmR2eFfuRULx-@@mz`+O7;H1J-Gprkw)?TQV~b(?95%|ML8&!f#`YSv zUtlZ6dwkfg!}eipwb&lQ7RI&<+h1aP0oxC-9l`c{Yz3H?K5VnFRbg9-?LKVn*t)QN z8ryT&Uc~kv*nW+z6g_YSwi~c5!nOii9k%OH_W;c&-)wDZ`=NViU_>*(-psBeGFM}j=Q zJ*3rA&eTwdUbn8Xy#;wv5hPcT;DDf^Ie0^)h6sy4cvhsim_63h(x?{s0nRZUDGfw}@ahz6LTAP-W}jqQdo3 z?^8`)*SM*rp;22HW|-Hw&KK_R32#ha1M-mKGp634I)`8zkB0J7cnNCWC_6%ZtG;u6 zgzLAkbG?ri3EtV^d#Gi-7I?I=0X<2z_3;|lsyjPEp=-tKa4%d!({(Yv)6m?~w$8T^ zL0l0ks4;|w)o;WZv~>tt<6AoGZnU>O+}Y7aL(_?XpdIb}xd;rKFsMATE$u#pP16?B zC{vZ%P}4>p{EhVujlQf4CndCUiGdI;=oExMwGD!UG)H2B)x zswq4Lak8NW<3w{u%vaeR=nO>5>x^u~HDhj5LSI|~ojVIwGT6y3R}afh$8=Y70=4Xj zbfPC{E_8H4O}O`8C?T~o?#AZ9R)nn-TRAqwxr|T2=EGKjZ6>yBu+7GH1GahCkeDRy z$F>Mt4YoV6)nco|Mq#V($Mzt$b=WAwbsM&g*uvNz#kK`o7q*?)c42!G+a7G6#P(@y zpT*XPtsmQS*!~9FK5Spc_B^(4VjCcvk}hB!cMFCu(q6x*zNL*Og?1aSFxd~CjgLgI z?AK{}FFX_pJ;uwl-n0akhJ5Bzo=oH}BF46(eZ97_{o(eG&F!+c=le7uG5jQ^WBjJ8 zy9IvZQ@i+Wx{lv6Td!Ph#%~sNHwmz}6jC|FWW;-ptV)JS<5gh_}Ou4XsTGw8R@MoOKn)6?SA?i|R*I?F6= z7rG_!E$VCCFiYe?GuQ~SjD#Ug!`NSwAch?!Vb!NvK=O&s4Pbz%`fSg~XX`#?&%R-9 z79(^{PgfzS;O}#bZlYm>0C4U}7J5NRKA|c41Tt43sR-Qwfl$P;1R}4+RX5W4mY>Fk zFigy@#&aYp5RtD&W5SpQ4!1))wO%=%w>Zr5huGdW5F(Up427sbD%l|K8f2yLeaN z=uXN=9T+~|3Z}Db>(LpJ5>dWjhPQhsTAZZBMy0jMm7dkH!(FG5c;yP*c`|UcD{`lI zKX%N;J0c%Wj30UHX;9E74|GL}y!#Kx8^ixeufsWBNqLHs%icQP32uG7z*R3<_UM6w>PhsSw8R)EQk6nnqM#s9$}ZJ$6zX-~Wc zjo4nr7Qj7A@X24|_`k4y68HQq_TR+TwJhn_or^wO zeEbnq6sJyk`j9wv%hMI&)FV$9;j}xsHJ_>+9XOOIjSaa5dfi>#{VR{UUPMW3Sl)RF zJ=mE1i99V7@A1h~%KL(RWsEzf;lM*3F%Ab9cP&vwgZd`48OT~yMY*4P18>#tIGWt9 zX<+%^gm!I&W$6@3LgRgMCECnKJ0HRkCc(ljrTBl}_5%FBH|$13-H;_B8>zQ@2#Hxv zzUU5@L<1Auv6T~J%g^*U6TXu#I>TP0s0n37#%YfeFKYMhq_oB``8fW+uvax~^|Zn; zBSY0b{_p7ilYt~Yd>3VeF@2NXGvD+cy`{#hdIPU2K3KN&VZ2VX^iloAzeP4tj7+kY z-;PYq{xj%0{Yhly89x5+xM$?-o=WdXo!wO1NU8Czp1|vP13Aa#yg*~Y*RkSW-!(Bw zm#nKRe96w&!sAn4nsYbOpAA|U2G)(}m>W?yybi*}<5%O5-(PI`ez&%FhZcVT#O%kg zy@oA;XzIVl_8V-cupt0_JV`<5vE^Ya#OB3ThHV12$=If2yByn<*ebEj!ZsJ%P1vfi zeHdGHo#P82WWMmX*v2Ex{xt6&9k2ZC+rushtvq!(`}mPH;hVcoUmJO4ci`y!+^yg3x^+!>5El{?Xu+m= z=xpF9-FkTYPZEEXGO*T;rxkf9aeHbz!&Ry>|4jA#zO0XT|Dv3Immd;I5UK*lkf1Ga zD5WYmN6q{LUijPBz)t0A;_k=z;kOD@H(7x{IA{?P_;EFKrZ`qGC>A!Pg3kr z;xwjYYB2zPJ4wW*IpxnmKXqd4xyVK5ZZ6Exf5ts|1>*{e@}15?XL$*idYsO&PG>3p z=$D&UP{7xVonuPMoKCM(T<41t>yrHiA-He{hY!*5Eza%Y+y9+L$Cx%|MgwIJvSL$w z4qc-4{k?9CC-QHW12b`Uvf-h?TQrt5;wKmoL&b)CfByJ2P%o4 zo*k){`75EQfR?&6GS~7^e(gW-%O0hd-5V*`Pq^ZEJysGV@HzVlg^(zIKO>bAnD}^~ z?4k$GR&0MF3K!pQ&eC~$_Lk!4>6^EEdaDm1hg#yY=;?YYd7MhVL?xxs(+jsOjh?=5 z`=Z|J@1UeAa%|hpN#rbCb^?j~PW{RiI7Vp?11Bm2$H?Zc>Lu^aA2C9Ei<(PRL>IJF zTEtPq3F6*zh9^+>tx#mbFkKD1POU-qxHmOe7`~LO4m`#~` zb$kgXwGtE)e*tPrMnhu$S)8`nq|mdWSVe$odHOi%?W6VI7$%1xgWeYBb|XyOpGE6@ptohnAW+t8 zm)E${=1>wRY>qOP;dr)sHrP}jUf&0+3&cfEWkI}(uG%t2&$Ir9@@{)+m z-0?OYg?%x1FI|ou-tqI~hm*;|@As5*0Y`(uGp)bWAJ_JdW3Gg}1Q7GY1@XJ9zs|~t z(Yx?tcqyiwxxZ)%+U>9UEc$B-S!}X|QwBgmuNeWojJ^^}0DaY{`ik6j5a0`TU><0@ zDc(t>IC|E(-LnIrDY<7?&=H>0yR1C= zZFg+xnR^NW_LlSLLxs8KfcX^Zo!I4a8X5;F(a7~e@PMN2ZVWe56Ct^I#-j@C!h_Y$ zbGMSLB%~@5z%Ja`-mnq5i4-R)!|Luqla(W%s0_s0^U#BRYe+9d<}EZI*wcbz;Cxsp zAXirnZyvMC5T^~gtF*-B!Pwc@Z;)d7JIVj~yHo#O`MZyuLQau?|Mqd`Z=Q|)YxJkC z-}FDgvp|~CbUm894oIbDcWKuz9Gw%oesNuRY}YRe!+Bl5xGd~R6n8y(R%J?EbAV!m z&~rNuz6IRG95Xx$V6;v_ERfbWPz2hF(|zK&l#h|J7RTj$j6B{ro`~b#z4QVE3+uYo z7k*ndCpNqz=|+RM<-9;USdmqmTIc!+3g#wZ`-<$kv$jw6?))?KTlAQtbA9yKRU*H2 z^q4z5A@SqrvH9Ve=&>B{&adz-Q^T!^A&?l}t|uH?1SYQzETYwv5i7FqWZ;Z5^4HO2 zXPnJR+zbQwiM7XiP&rI4d@%8e-tLn)t2!L%22p-lHCZpXal1#|4t@N6`t5flRw4On zH%0SUqTlLPx0cr)n`PWeZ@Q|hYQDF7CT>@s36DQM38(ayG1%ivj^iF2;Ks;hUElgG zo);A;ZFTl`(DN+$Cc{f1 zyEfpZIJZk*Zp;EEOc3%MS|b*Dx{g-Fr)Sc75yG5JAyITEiu%Gj^b{7f?92d*2L&q} z(_*=pd&0;8vlwIqO-0FF_d@I5jMtdN@cKPOX;CkyxreY%e>p_;x7IoOtAT+Y!hU^f zN78%oWBQ5+cEevF#HUR*>8nr{y~*~u^mem*fcV@ssEb5Dn?y-1O8PeIVAm5XO=`QH zkbdRB5i8-I`^xS^u@{wj3A!Q)P|GIqmhSW6E#^MNBooun)O~60p>S@{W;x;u(RYi{ zmk;8&5y!15Fr4S3h+b&SM{#abbI|hwI5=0q5(TdK;fngaDxdy%Z73$R$ zLa02@yP`by(zk!=>MdI8`fgKCfj|1@ttD^_X8}H*=Ek{TX^0ydEyE-T^Td zOpS-+*O1~n8W?uNpUn-4EbyV8(q7wpvlcIaWsMg;(mqJI&26I3};S7I==aJ$VJV-ZsGF;H~G`+g1XK^WIt_N^{nKE=<@u}$F3iRc*!5lJ2 zKsZEK{2l;^J`OXnx$+^5CYr5&g#Sdds5@D{AWrRaU)lI-kLRT(-cP+qM`WETE#Bn? zRIN|>YGciC;}sZ`>;!xkobc7wp@?dYz~@54rng6&+HKFx`s~PPZy>8J6?#<-E}J}lOc4tOtQbF8V0ZkEaxz>@^=HN~sO-N;1JZpR31)c#@i})UfQu9t+h1R~03&QwUCWlv#1}(;7JZ_&b_+aGz6GSPI#yk~d!=Vrxhq*+ zo2Bdjfquflo4C{WRXw6ZkB&Af!LZ%>^VlJtN}TJ&kr{i+j82 zQAk}@V+Yij_(AXDB(U+^fw`~jT6xO5|COGVCtmQOK3I!AD~Eelo?%Uk&->)x0Z)7P zf8YDnKRZg#zCB^{kz~bF)6sG=0o{)61h!9LBa_cX*q*}nd2C<7_I;H98vB>9k#6uu z*hm--h^+kz`!U$pqqbi&Z4?P+5L@?v_Y<@6_2|ovy_T}KlASYuIt~a@T2P0H{m4^ zj+?IzA8)3sFPDnud;}*u5Lg2pboAGvs74f_d3w=}C>jd9?m?9j<8i=xgJK*2nt{MR zzAKOz44lFwPUOq0`y8i+=wcWOVbvdrYflZ4mMJ_*mNlW1cEZuv`@$=UG2XAeLfT_> z^Ui_ZWnb!97Dv#G5>{Om#sYEhwTVg5m)*OUCGG*|`Z~6_E;K8r+q_TSfVNOE15c2Q zKkf+}#(CGgYa=c4U4iEY17Fg5wY`sM zP^&uas8f$Dfm-zrYGitpVG5Y!74Wz!t)`8QT+ejxRO@9bZH!1Fi2k zL~L%Z)==OunxP$MMU%NP(XDZaz=i^GT($Jr;i|x}_v44DHQb}$M3}mvE74z&58({NG(x0ty@l!*7YTTvjp4rEq68Grfv|F5Wg;zt3 zbrnrm{KqRq13e3Th)Pu%xn4ek@+4iVJ$AeL947Ob#2Din*NY2yPc(1>Kra%HZau7p zZ;b^Gs1SE+5YxnEJ&#?FORJ+> z`!#4ZVN-~i)u(Iwz|kw_Xg5gOzXC(_4fqz0p>^;u0i2obk+!z0G_AbcQ9iC5Kc`mi za+l}p+G{G4Kko#u2Zwp(<5fv{v3^uuTHy71Jq6|Ex#eREOUlc~loyrj*LA{-=`kU} z)A=hAG^(ldQ}%2E&!5Gvq{>9KFe9}-WwJ{=EYqA5QQAzGwchDD$-?-W&`%9@q0qQz9oEjBm%oF;)ZzA}KFKECqY?)ZW-#snQ*r*ux6 zPr*|dG4;^WN&?R-g3{_UF$M}WSJ>p>EUi5|k1A8o90<(Iz~)X%BjXkA)dT)Be<4%) z*ljPOwV$)SDPH}0?jXIHM#O(k)2%nt(nw0!5*;9sliq^^xkoO+XO~?yb+=rD2uPzrz9S&VDL=JQZr()OY((!*- ze9x=MjgRDXnXX0{(z8pUhaR?CLQ3P=^wBZ~=QMeG~ zQ^Fo+|JBxZ6TghiuAyegSgFCxFRKE({BkxCt1?0;xl)x&HlLD<5w)FzSAh|on~bsL zxd_T2Ae9P3M26`q7Q-7R!*qzQ$YR?X)`{NAKf*^M_@A*J$Z@5?uDuUL@aKe9>`x$F zCIrHfaR*VAzNz}6E=tzG&w0Pe2X>9HzDo_>gU1*iHR%=$0v?HTyDb17IA;saIbRJ6 zhFP*bLXOIFl^wIl;GX1cW6kgPTM0!{LW1_Z04DCq0zi*-^i)wzFeB39K77*SCam zAOp7HfD>J#L|1h{NF=g-2oh}VMvm?FX@GkL9J%o{b^FFi(}?K7S4l>L;1Vtbvn`!_ zatPt}a04+R!-;8#c3ZYzou3&B4AXIfR3EiCYL#*K033lz@?IbSnz+0*tVTzc`cYc^ zG#=Dq^L8B71~hHQ%Uw8I#hN#$P88o(CmXS)eSw5-Vdja5gVkRvLwV`D(O6*k@%+SyO*t~4OD9l8`fRd_-LaxtAVPA3n@Qd z&mw`U(toVwQ@iWgh|iUodXkRw@ULD;DO;&3Y8k04sal^3(#5m;)FJ2*PQB6tO|}Rc z4r0&^joKKpPiKt|2#KVrVdUS$0fq>DuzwSuJ^U$qyxZ<9VDHuRC6TU>#LQ+el_^%B z2z`X6^nF}GV}cZ(5fidCCZ^oUgHAZmFoalj@*qSBkkj2|F|Xq&e8OArMhd#807a2V z@WU+k6wF+`Tuxh0)miUfk&&`Azyl{<2&`O=895Cz^A^m|Ahve1F&-+;^MwO98Tgq` z?ar6K(6!Z>>D5~;@L%t30C`EoqTh*PCAVq}1{|-*P)8gz8v!UqpedqU`u~D4*j;rxTtZ^86$)mNZBtFviOz!9 zP$j);IN|Aiz~S0DocJg7Do5Z3+=(81i@!xGu_~U(oy7|B9Cu-CV=GH!E}H|4CGR(Bm4eT5~3p4_JQkHis`Vj)Zyjc&Be?5rx%haLp zX}Fex2j;?TDJQ-aw8uw-j`$Y@u#A5PEbdPc`q2d-I32)l1%yN+AR5zOB6S2!P(go* zbG!7{r?Z%$OD!{$7zVNQ)67*cTr^ijSgLfBRgxIu4l;x2`>Z}&PtXjaIG=DtDvD_? zF`DIwG)*QFMRQ;2DTM+jw&qObPgb-R=<^ek08~UyY|UGhnBK#cgH?w&O^O{}u}U9h zJnWbV6zw{YSZpeG{U*BgEe%PtKbW6RAZai5mjhAP zo0BjSerjk&z!4ok@tIw3Y1jvxlQ+0rD__wVt`<=}7O4;?3wg%gRVNJP2}gFF=9d8% z7sFl*NoT2g=sI)KSqU-_JdT&Tu)Af$W(p05NWE$$()z;-I$Jgw_9^n*?)odpV*N$6 z2}>Ho0V7CCupSXY5bR;0HUW)Kdm(+Vl;b@k`${){k~UAuWQq{J(T5ZDK6Da=#cALu zo({TH3ch3)aFL901|EaE>9Z*8E0HT5G-@+h8gnnhe;4rzyhAzkm`c9&m^Xb zvzo9-x*0oxWSA%A9b{ZX(i>~N2r-sg>IF%ispbGWKfQ(8vHeHh{nNU(Ip#-v%7ASZ7h} zKY{ap-185(XAo;mGp{r1GWv=226q(Gdc)Z!oAltqEY{nN+E`3Eiu8i$I-M;KMZ%4t zh1yumtJE^<>?yI%9%C7zp45asq|uf(_mDJ+ZW8H<#bQicdNNSd1(@|+2TW;xepVX5 zskLfkHbuPj0`%i}^dAMRxG{yaqi=D%TgU~O&8045`I9QJD}S1jMXya@F`EdPj()+X zgi)d{l4L0*WhAHS_4#zEj08!miA{c*u33Rne5?VK=&JmYe2tm|lF`U-r3&n}??=tnrdHD-@XnpXbP+8%Z)rEw8BM=Z7`}7Cp0M(4?!kKi|$?_U^H3YwS?-!;m0(H zo&h#wwl>7mDzi=<20Ye|qpv-Ow(kMqNw&b;n^cHw+XqqJ_jB2yl1klL1j|eex{y{# z$pwOTlPZ|}(_3B5xHzCAPRm4GwV%Wl5^`W%a(8@B^O3?C^A|};afSn(6Y+qw?Q!}e zQ}?@ZSuTI^u>N|2L>va3s6!SZw>mAT|2ANESO?=GC~c6WX0qT4b&ZSz;a)_>fI0nl z16_9jWOReec@oRuDa$gD^8@MN8X1A9`OgJ*=SO=M^J9uO1`uLVOX%Un_~Z(TOtnxq zy0oHa==dCC#1Inlz#~*k^qtn%sgEK&b0B&`2LcID($#W86lVqlzXzf?dp{wI-pH9= z$W4?#KZTDLonI3!dcF*Adxl;~VZPt&fwJ~QPc^J4hABj8;H{o&cy25IW5@>=fZkbZ zUTCuanlN3N#8Lgn1$O%{n>flJ${Olg7L~SZ1lYB9Zxi4+HG=wLkLeN|3Du>UxTMEw z7I`Y@Zm}dhj9bZ<5FF-24k>I^fzYiOBP&4#5S@>CIu0P3LbZYmSA-SajvvuiSi_V| zQ0H&txm|t8#x(SmTg&s9b0BZk@)zS%48gPs1gPo|2)(Z3&JKhdQ>WTEbyU}}s3Wup z@Qv=$O6bwWl+ci_FVu?Z{4QAFiPMY#&#*AxH8l-@W6CN=kXPfeBvSJ$)}out;Ewu= z?EXH9^1iSnv{-8sV>uu!5;Z8<;z1>uXkkvA8SZuiG2{#FFpCZ{!qEx>wtBe^XB3B*n!n;padpzO% zll%@(q&&t4&y5FPx59Jzp_4C;4}V6K^(+>N%)0-LzQ%3tT@3G{#U+3fG968<`!Fu{ zEOti+OM|`NisNK-r#@Z!s_ng&4B}ld%qA~LPrRzmg&1+J{${{pl7s#baQXFM-m{lN z#yJObUL^K(1E>+^z^3#0627b_(%DR(aDiR;lE?x+KmHCljADZ5!~)eJFu}qMY*>1R z!%7;SYxKxT`vI@Gd=bj~el5|&j)N4Mrnj5^*BT5**SDykehZ@i@TKTL zU!p)i9)Mh`$EhRY9S4VTGtbtd-fz({1m(FIxsz39?qmjWCwYTQz@01sce2E#8JBgs zwMvLF^z%yd{eyW66XV1UtjfxZo_2(t$=tJfT_3)0+Z#HM4#YnmlZ#?r|0MwHGnjDy z8x!uIu>ZFaz!hDj<`+5WTjm!P*qvXoEaun4S|MhO0-&~GtS)HE2u(pg>N$cl5RBGo z#IXrz8ufibPM7FG4rec=)ZW%y0ThL$U?TyDRt>TmA+i?GLm#!pg3gdIL@%BtNRVGK z8N#pAFO?&t^sgXK>T%-WO(qh7K81L22Km*yfgf|?*MNqbgJGSIp#%xi4_yh^L|1#^y*yI5bj_sT>m+>TB!TSXdgTWDrHTA&exFk!^y+{Wl_&Okk z8A-(LC?@jREKv1GT7uCI(-NhUmSEY-1PJS|Fl%RZ`T!KZg+8EjyX{5b#B;WHp5|GO zSJU)OuMM#fU6!e67CcFj2=xxtlqX+M_727AR|=ApsW*%Cif7PaGK5sx2?!ZxIrMTp zFqs$nIK*ZkHkd4?W&<=(*nwMhQLQtsfPa!o(bw{IB00?oNm7goDUg{)uJTLu zRZhv5`{!Y0FTqp~V#VK&(OPF(;c~oKs&0nYLddhT zUeuKU?)x+6X}PH%@fS^qQ@>t>qhNR`&+U4U!5QqF@MFG?{Z_O*o&kiINurDpM095p z;En`zsi0%@J|OVvVn2urphnl%O}4I0&}M?*s=)4eAc@*JA=Gs8*~JGqr<{ju3^sIt%QE>7 z3gSi8L1@mZ4al#4fzmeJ-BpMF;46axuoFJZ%T_xA~v!dLQteK^vg{24-%f} zFh}(T?FnAX+EI5fyq4#7b1bb%BM(ZAw?}!qq~jz_(>puXw?GiYylyBnqnw`ARk}1? z+(XbPBx3mqMr8!tk=iubKx%(qy%gve>?rAgDbV+<-frSbYn#c&g5eD&bv|aV_v55p zH`G_KpP)<^(Oc++&d7oo;(v9$=->4eJwDj|JN%zN*!?zk_YZcT#!l_{Grv*c2^zfED>$F4By8cH3%X!S*q4pXU!%7m<_?wgV8Jlid6SiO?ZDheRI2bB_|8BR(KR z=V?~7TF(&fTh=qq?b2V_*biT-Nu3b&28)m6xe^;em?Z2{=mt~*oux|X7L=ejwLUg3 zzNb!3N_R!gYN4%>jshNOO9_J@*dQ_7hw{J$*p}+ELhYC03cdaE+;00nqgxnfwlI5K z&{SkLX2AB66^&t`uB%2Cn6Or~q%piAyiOEpUOubu3`aIDZExyW$T1xZ{haVcA&h}n zOY^|AWR|3@3}XQ)(uM}c0X-k=nx)*vPhDP)QluiHRU?a^qhfh8zNRY$Q7Yv*E$uC; zICL){PTyW>p*(kh{9Uy~eiX^miV)1lEv$34{95c8IYDy)8H_N%CCQ&SVn=jP35c5* zg`vzP>Q!#zEn9Q&+Q_eE7Nma-xvLIsCTxcniin9w+g1==&`nhkK7nfv=-(-|e#av! z6v~H%ld8ZT)}xR$Z^ZL7y`#6ho5DQzhKv-jC#ZQ}ue&Qc;7%;> z$&C&ob`)H#*=M0DaAw=p|KNy~ogDOpU0vVtogD0nVBd9e&`0O~T_uYt(8~cg?%e)^ zZ@=yo;T;6h1|}y|P4*FcU?H(8dhp9!A;nJ!fmtY5XbS|8K8OlKP`aqX-Mgql>ae|E zTU0SW7Oq$T5BHsafg57ud&(FvdL~pyhunB}%fZ-`ie4c# zNqESJtQwsp#e64X?h0yeuo)i`cn$51ZmDo!S-ovpU1U*DEkJEzlZ&Q1oMyNV_O(3cos2akE{)Po^1@ej%)~e zjzq9M5zITXz0UD03`dT<6wH644BO>F&l_`s1z!LY@P(S7`;BEduETyc_77s;7%X_B zEtvm>PLs@mTBUvjuUa}-QLn=*d2Sb8ZPKw@rNf=0JkhNBxXT$B-B}+B2Pnstt|$gm zr_zz7=LvMv0#sbN^e79abyOzh5xUvIB5|X`Wfo{s83o4@NP??S*RdjqVy*9Si9%WR zyycQxuEspwmczEoJWXWm|3vwz!(vfy{kd2XgfRIIh7njuJcT&UD$M9(2WC*%rP^ap zBqaAoU0~GC^7%M*Ie$r#(OnxD4RUR>CEvuC(OLM>}q+- z|%%fhhE0mMj;n zY^Tp;mNJ`V8YW3b8YMsM5s+S*-bRyFk6=UvG~@eV_%CJhy3n~$NsPdgkwt1Lv>n7J zr`LCo6jPe2m}I8!{x2rH1(51EGC@v9&MorT$a6KL>dC_^S*c$4J9AkGPcxE!65 zBzQ!PX=z`t!y|ca7apC>Vw9F>IV;*48{sQ?ry3yhV426oFpf5jkm3O|nKB95Q#OD` ztj}p!N|HQ-d?9pXEVU(oBgbFCy|Eiu-h{EDU@af}M-(C9h#xx&i&2M-LanR)(>T^( zB+v2P)i^6#x(J#2Gmru?@fbrO!7k>ApaxCN$6OLgE{P@!w!I)gTLoT8Mw?4UypM>I z>-jy2tJ7W-h6jma@gg$I!Hbm8Zqt*tY`DX0l zHWdFT_MZ+q;{Div6O-m8NWA_N6X^)9{W6%RCJ@OpH#}^%Pv*0Bo19uUo~Jjb;IdL- z8kb_JtW4s}Qz^~577|IWD~+S@P$iQvELGijc`A4KE#&$JKd&4<1M$XtWj!d3B*$W{ z`OrNxQ{+&@&vw8&myG#nfw6s)DzGbm%7&j^m}2xdI#YpOGI>1;Eu^+bTFDTX0Mj8+ zdFrJ-695fMg^tp=GMoBOF~sOSNrIQ@Bzu0$&BXhf17dRK;sM6p=x;2xlLz4-!HUp#pb7OG5(&PWcEL5ms{u!JP)g8PvNvlZFpkiXO&zZ^6B7RYHIOl6YE|A_Kx zZs6W$|5I^l*Sb8rSaA8vAnYT&Gn(1Fa2*!apl88e%6=&GBn`O&lfpKNHjp#qwMtyl%P1(@C z6yE@Pj_3!aF7XikKqq$ThfnB|%8b5-Pd*QZKHL%6h%B0d$0xmsF1+N>=NljDG+AGe zD#c{%X0h5$HRyo|V5F~r#k4oo_RS2wjL`eKq~4-)xsr_DSQ?N^RBImn^U%M1`d2{z z3hAH9^G97sr+t5}%R-+=>}@j5fh8z#Bor=!s0IVqG*peW+r8c2gd9`aeX^&ZxBDf$ zqM6>K@G1Ekw*tNDfjP-l4rOp5la2<6+Ukld(ND>hM_Qkq#e486x8}!H?|#tl^ybw~ z(Sd;`*v~bQSWLYHqSKdgk!(m>U9?dxxX35wPCz2C#B|uwq1#OMP$WFqw=j{rn=dS= z-%`5Z@$E2<8bC8XhbAP(E?BswWC8MSiLw_^))aG515GNYfJTcP8jeCl2o%X-BY#5Ho_o7We;au%Q13I6nf=_crX|^5EunRnQA=Heb5C-aqR)5H>ve zXePP|@FGGAdqPI6f8;Z}@Zzk#qKxeGsj`2BK!;$AfFWBdSQZG0$Up(sxACR&6`U`Z zj!mWtmi2-4u&(~GwwCqHVKSMa7Che3-e_@70;+2XEm{Er?VNU?0y=TiYXFz}oVqVQ zd(N%#^hQpw#DuB59PJC=8(Rq#@7EWg3qNz}cTGLPB0i2Cz*)}$%awwZE5p0^8OTPO za=w|@)RX&lDiKe9f5++C%aDojvKkj4Esn))6in*Q1Cx@ zs+PEd&LDm%@O~}mtUTP5Tnqy%Z2R4LRfo6#g3gbD{7=OIzg%($ykT9IG3LzxlTZwDw5{1KGj)h6GVTAj2L@LRk zB(@j^tySjYa%D(Hd%3<3OGtpHh@ck8RaRTud%ecVi^m1?;(cJ1z5~bl1@IGUhRPxg z(NGk=qaXy=NpN1c*492Q@KX z!e@%mEREO`PGK}b6NaU;@8TWW-b*!T=^ao!x%w*sK5xSQ0i3VL9vSP&3oK=5s8Mo! z$l-L}iZLCRYwgkC|{b&UMGiiK*l- z!+W+M)Zsm!*@gEvW-}Y(S0irZc8e^7bY6oo(vxVJO<4^)w3*phu@bo~6io~(q`@m; z-+o?1oLa(U*;&WWB-%&6EzaK4eJdH*XmsqLF&B* z_$x}=4t*YELinV_5Cd;9(V#gk#Ht}6|53t02vH$hcg*2_d|9UhI7krWHCsJ%Pa=9r z6N+QlJZAjtYL-G55FV{gAW1CAcu16gZKn zA>?feVszLa8K>iO9n+skAY_AU>twoOox(B*2qI5yJ(G;MV+TO^59;XuMlDVrSBTI< zu`OY|?}6cd0VKI@h&=Kj^2qPs1rp#B!Q6O1#36qTGT|Sge-ND4Ng%V|VtWf)I`W?F z$v|d>J0tB4Cip4}?84W}bg4&XJtU=yfYB#O50z~-8(N#Z0BD8<+SlFP#0pBX9-@QV zj+XW?3m?-23CoE0c-Ob%ly*B+EH`o6mE@8VWGVe1&X*~Qn20Qfy{ir0^x8uqG_;??F-3sZa|&Bfb4C;(@m2E`Fm7 z!o!mqlF7vNu@jZ2cATY)n{xKcdqA10Xg%sPQpzyHbrwW#)o|xaTsfN4;#H`eyamcw zeO@jl%kNz9lzH(hF$ZU1-c>>Tb|>cQYV6yv-^AiLcRvIx2+^0*|0V4AV-6p~d_4h) zK|Ul0Wsnk>?%7|sQrD3Eb3 zS0}FBQLz_q)RGV_uOe+^is68a-^VkTp(yEwV9rtqc!^+qWE77G3pw$RVD8pqE^e@p z12P_;a&MIQl}_zOJUo#FEPOmgV{1XC7V&PTs5gp<#%xU=(*(n*D==|vgo?}tt18Jv z-&+zW3hw%3pm-qSWv)7=F<+ezEoGp%E0VWkS&`-kY=i@*250C}F{XXh^70^mUh*Vf9R?wY__H{G1%pMxK)uq1 zvgoj5^1vyi?RX3L0gl>lf~uh8Amn+e>U|=5HW{fDvzRhu!(=OZx;;|zjas~bdI9-H z4*a74(C|D-ERCHNvRjVdL&M<1eFq$3NYE=g8jDC#j5_H4JklGsM3E>`0%=Gd5M`hg z{5`#+}GwEOfM-k=%6c=9X}CeJIqj9$|GZwcLUBK-RJ$nsc z-!yF!m#6r`X9 zSMQEm?Jsh*+@ve%)SmpBqrhMB5P~;VJQ8Wq$`K~25lxCTggZLfSiKezYcBDxT?>6& zZAaT<8#+2SHn%h^s;jPeWaB10F&5XB!Y(}UXhY-1@NHyS1p-&n2E~3<7_VO!?yPuZ zlUBs1pnRJu9%<9c_$=Jgh&So2E%WOgYCJc_FPmvDlKo>8O;LB5h7DI6#J4kCl{LE} z{j>F<^{AYwKd1Od4x9NKX|L+vNPBg}H^%toK&cnEXyzjMHf>L#=5V>!Hna%Yc@fTX z);4rR!gpdNBY!NP!eHlKST_ z@ic`r+2C>WUJZ&RM0ho|47r{8*p8cPmeFz!2nM=ztQ-OtsQZt2FOF1l8$Jx^nT z?0D+#FyAdhji=n*tUXUdhWxhb?kD-~V}k8Yxw}hyo<@}8sEeBP^W8G%S<2m?)}E%0 z6D|kb^>hREMr|`yQ7@t<);80dQ;Mi+s)!$X8U@lA1Md<=^qgK>QAE!fMVe33p0*Sz ziUVyfYv#*TAN`3~;NZGvP@w72Vxk9MeV*dmb7ik=b1_YeHz0QT8DMd(WJ~iHn^IbUq z1kRts`97Qv!ifI6DEoPELOg-<-_^O0nCp@wlY+%ZuEg<&al8b_D{;I5#}OPy>s&{A zaQ^Y&q$8ig@n>=Tba2X%FX8y_ar|W*e-pF`qRp|kkE)GsOT8sV4;3Y@bV!saicI-pg$FScMoP6{z zu>TzPsPh;94*Tb^|5k9K*7qh+GxW>zX&QMP@rgVKt!g=E36{Je2lt;aU8nOmQ_hd2 zoX1V)2l<$J2Y#c6*cAO|9Q$NBNJadN@_F*umr`CU%V(#QH_LK=N_m$ouT3fcv@Cy+ z%b}F?TldQVC^#|& z8y<2W!9(sNc*uRE4MjV#eHL3^-9XNf=P=9vrfwkj$d_^OJRJ<+;2<6R8xG<~av&n1 z%?3Y9b;1TYDY2Pih2 zDAf9{&;~G>&9{vtvrSLr@Duo$`3Xfi7=*d$iCn5FO~F#4Cp6!#5jCBv4d89`!ctjN zow6~#2MH}UXajf=4Wdh%%@1tH@gla|$ASFO`{nvXKdsY7wnyDb@3H=%oi~1ay&9Z| zCc>hAAU|GLHvp?3)Bucs4eqg1gOUAXd?bq+Or{#-$r`NG1|XkEt-(BPf$>TlQTu70 z(9eM$lQj?p@;_c<{Pq@5TgStTfSMW5@L%)eGBuNaP-kd2X!H13{gV@sPaUWLF*%ms z-W+=A7_ASLhDl=Tz@4koibpcPGfkz($x1KN2Eazn#NFmfFW_bvudr5nk)}^I;}&rw zDqqf(hcuJ=SG{*Lj_2_h7!Og8(?&n)amBQW5_&e}CwhEZd|n-@Z4xBQ+en^@4%i$L z+&Nox^10oJGTB5cyB^FdaePf}_3J~#>+1T`G#Um{MD(qYA-;CQk zZ!(RP5zGwXXFV}jY~w^I6dZ~oEK-^U&~U++OBH)mlpT(A;eJO`Xv%-CQjHWs(1*w*(x4sKu@sqgr90gePLQ^eaily9Kc!& zq*mgfN{j{{Mk$*qgnYN$(3R2@Fxo3;087+GdqZ~HYvkksoCOFKy7D}%aYLYhcnNxY z(>0C<+T1vmpNAW#+m&M^xmB>^LK+!kVt18jMR7A@fDLbi@{y!xygvEduKf(s%K>hTZoS}xXpGk9 zL-nD?rk2LGb*T$f8XfvkAIw1(H(?I-T}nuRj4;ujr)gHzww9_{Sfo!sINXfPs!8xC z6mD*O)Y3kjzpw4X_s`KjzpeIlG$8o9Y5Z{hzP1nFKS%p~*|rbxvWbGlH^}A2@I#g~ zf687KtmRqE(GSTv*?@4_kQ%lS(!i7j4k5P`2n$K(s3c^lSA7G(Cn1ulK$zqGh#|(( zEX;7f=_)3%iiJm$xGDO?JdHBKm{13)E6L`uTB;y`Ss;xlg*3rHFSw`GZ9Uia!o!ag zYgYo-%)<((v952xtESLHrVeCyrHbsrt50UpgDW)_>29uPk?uH?L=~O55dzJI@b%gR zYca_=QH%@Ytrs2=7pQ|Lp@Y+QJv#T(3PP}c6Wu#oaKMGOyxbzKStP6WgB(G-2B7$0dsMoUqFf7mV%6o9)uoh~ z15>t~vq82dSHxV&+KHIP{;=b&SoKUnB&{B*o(a}8Dc)6hf`>^O+EZHL{=2O6m)Ac@ z(XST}POg70v1@bnSjO4A&x=W`R`p!XY1VNl5|}h0>2(|i^)V#W8FKEYS7%st3{pQ} zEtEp`iKex%u48Qo4zKOB9$GBRXX8Wl4G%Zfw}5PGf&NG51pM>}vcb|LkK!5Y%4&Rg zV+Ya5E!z27q1M`RJU<4QL~g3C)parDdJ!BpJDb`%pa7z(s2d~g>s0Y3fM8V|daNCk z!6xl8qolF%;f^NK=v+TX0P4nv*TUZv$|Tc0VNx$}&l&F`T@k&@fGJQ#%Cgjzq3dyI zWo)$o8vz1V54o^#H95H%(uf&OhjUV)&9!NuP471MDrJszuxOPDlrYHy^D$Bk6GWLt zG-+;pEJQf{$gJ6aJG}4ig`jgCgqkq>VZIjx)4TrdozD^@Cqh)0LJ>VKUJhmS#NgQY z6a=X81q%>yats*ba)hofL~xrjNMXmv=RvxHnb9aH6qE06*fHzm z2NNG9l+h_iD3RcOd?AR9A`ly6Ky2iJ*eC(9;Q_Ic4`QPj#6~HIjRFuGUJx5&L2Q(P z*ns*6lKBfqY!qEcV#A!=1EbXi`)g1aU;xB&XA4+SFxMt8xJ>7EQlpBTuhssrqmb;M zU}yu{dQ%4Lt@n|$$!3-7Jg>2U{$M#0htuGs$ToOmXGfTpxX9!g*B1cltAU5GaKIpuhs^a{+k}1r|u(faTvo9I}82NFahBakD>wh|s(NLH8cawe;N z92^u(ItPS?3h;Kw{XPYm-xm#;pX4WngM*o$q>{}xA^fZ?d>s53P2mTUBO)EV>p?|D zg+xh^7jva=f^_?r!y0iz%9@AhMMZ!Drv`zXweT&c1_>mD^PZ>EgovejYS4$1$k<|< z8>a^SI0+-L8q6q84U$nv_>y8$NGHnV!xR^V-uq=-6CndACU6(MkHfK@8iYEKUx9sW zW%+UtGct=0=8Ev!qIYcWc|wYXdqUT6g-#8U?FQ`n2hJjNjf}){5aQ!G(I@7>FAxvi z#?s^SBo%%dGvig5@*`aY5(UZ>EOLH?Ag{90`&43gejwiwx^8rx+|u(V|4Uu{;N^9x z8#=ZR(pRCy!{QH=icnrn(QS~_7eu#tguK2MxT&mrV4Ig$ElJ!9N#dRhHg;(4Ypt5= zK&_12f+V@U?&%Q1PnXesFuHW&I=#xcLw7*JVhlh(62yXBZ#WO2RuaC3NQP*IuUupo zzMjpZ$0;4ISds4>&RzwIKN}e+^}8j)=vH(*V%AgSGby?cl~;yHbbk`+j;X;|H9|3% zfNRx>@FIe&wA`XeN93khbwyRRZ<8k$s;CV4{x`Ns~=@eCj!Mhm>) z61(_0o2XScp4%S5U#OsxQMBvVq1|lf^Kp^MDs|4gA^kL4vJEQ4w{UP zLL@VjF%bq=$S(|at(0F-fn8~(A-_oFRoKVQY-s_F?G$a_1gP@J^X~fVP1iKX{o;zL z%s;ncQwXZ^g3(;tBzPUgwarlbelCOTBgFwtol2eWc(yE|tR|qRO$*sD zk<=IiSeQoK5Co)|4*F{_YKD}6l>JR$dJwj&w|Y^JOIO;vNxd0!4QUk6u{Y!q&Z?`; z#*a_qibi@$p{ATnA<*)X!vL1%SCFV+7DNR%LwdK6!ed;TRz9!@Z=etHj|`VJGEpyr z7;qx%`|4TFw-cAmhRdk}ccSB!p{hfx)l7XN-Yox{t#FBJ;GZy;E+M;kH`&EQpXy~T zV-&eczIj~S13QJ>Uz>XbCQ&@kWXQgSO zfCKvam+Deu{m-$x{vXOnP5r^G|F8dnum6b_ut1^)orB-w1C24sa$Q0OG8z#qev?jB zz6xw2Z*QrGSj-89)Y%g1nS2_afM!e$#(KU-&@)8+wy;_#xGu2K=zC z?OgH413%sm`XQ}bw|)9SK!{cLAOz_bbs8eYg(3wcjG!Xsf{OSss0d_kya*2TbwdXq zKyYC26E_HU%YX+r*rg{v^2Y-YK7Zlq2}9j!wimF&QcMToU?nWfZ^C@+TWc387!-mD zI+WVsF{%I^mH;~3eGxjO^? zC2Np^fpf|fN70pe?vVk@jVsT#rNTiE7}m;U6CqXHPE7!OCE{rEZ4CxVB9U$ zn=zydTjNoR=;-&HiQ?E`^mQ)@#`zvuH@y1Y!SviyRJZgKqsUNsY!m{(iAcT)a*|rOYF+;@6FgF`$_?$@m6*Q^g}#7 z(+CVVPnBzqHjO=sRDqI9myagP)+4kjZ}rh5wAm43|I0ffJ2RjbDU%JTMB*Y>!26k1x{>QG8XWaBhrD~aERs%uCF zPO|U{>~(&XP2+r&9ILSZ(qJjX-6ipx35x+GP%caSTSj@Wt{qkKjRgvcwZ>w0?7-EP z>r(KsjLzZ}EDC>wMd5pJhgB4QFF&RJLC~vF)DrqR5Wq=wiYO8Pm8g6XPSvrxZjB^@ zs?3DhEuw3{f?84jiA24|Poj(A0JBsMv7R(jy?+U!A*pY?~;o)<_ zU8x|5zT^PDM^b7X441!SFgzPz_*Q^n2EKO_1YSk|?!O3zFM?r$PWX)y@#%vAh7I^@ z_8$}QcdlLd3)(4zJ?TYyR}U?v)1mKz-ephtbcP&u=v|?ic`ysOYX-JO?-x&qZK+5!eb?`#}e`Xr%#frNYW2U%0_8yj}MJgSRjJ0noddHCDFB zU146CO77}Dx6N5VT|?P*K1khb0e!0geFHk+MW|0leDy`>dlCBn$v|JgU-(aBRq6^s zmUoK+yBfi^4;b|AK7VS%G_qagjiQsk8Ng{8>8w&cLW#0b!A+#>wrUrbrVOEeqrT>ga71{NV8pVd2BkmarvK!2qf<&?A zKtdu)r=;uAgxkin(bQuq{n9)HgJbO*YuU2PV5FT0%p5IRYmeapg6e{NCQPpqdc&}2wkt&X~Y4lD0 z!NE{Dq>MLIag;^@q3AZSKJL@F(X5Y~mlD+<`W8ye$3KedFFR9~82YzGD9J(>hj@FW zi-WW!hXU(E5p}t)i+fJj#f{X;!5=y|I38NL@kk&#{yl{8<8&AgO(;~D&`s8HQ_cE7 zs|wR?>Izn2s@17?n$cBcf0RYHjUi;1M`{6&RAHW1{aumL-(4W3qgN^&p(Mn7s!8d; zb7?lybe}#Yxl2Vz|5D>4u&TR2n#eMmzmT&-6N%M!o;8sr7EPp>EhhXX6_RHBHpec0 z%N%c4#8{FL5e6V1Ec|xjj|jin*KnrAaYEu_AV0=&hJLeCaW13bIkOK`mO`IwaNca- zyjy|u3^iwv(A@*{ui+xjV?4-i%NKFpMVu$_0RAg7>;sMSO!!VJfX(=Bu3dZwYCe+& z_#!{INgBWE_J-M8Mvl(ArQ`8z@^cwA%4u=kMA$``FYw2NKDjkJJeRdfIUD?j7~?SF z9V-kemk?IFi~cc^`^ZK7b`igEezuD|-3A@E(ZQb@ev=A!Gk&|lE`Iw{<>!9=N5s$B z*5I2lnbI|>NTpVhrLMp4%nr-hR^exZ?Jjb25T|P7LvT@oDFAvJCya{{%=$k;Y$xr@ zpq~RAGsT}H^&CpSt@xtKP1z?XCNNbGstLUwvZlO;DmNj240S?+BojDF z{!A3v<|jb%SuOHkZ6vpEuJu5qwTo_B1-Ee*-T9TzO+KhPBKN|W*~lKN;ChgW*~J&19*v=@3e}(sNwt*fnCRuu}m%* z%eV(f0lv7gPfj2A#HrO`$|2W*P;`3>+R zO2z-wc`ZN2MACa;h+@KrR{ImihqmoczLJ@P`xC;4C4ap5aI!&&5FAtZ5V`wQl5_#3 z<;Br(V%}QZ+Sb^v=c3n_fa$F*vO)sd+b>38(I^!O?=`|-6Ja*h=vx=J~sf{lsa zL2M^mcdn+RdSXBy2~Oz$81fK5mznvzh<5ufqTTZyx8(z6_xXWByE+BH{<$5YP5@Gi z{FF=Pd}=0gwbTXft#eo3y(oa=MGNZ|y6Io;q9x1kURmp2d)tZ?E^M4tYZUqEpAh!_ zr}tl)nmxCvWT$EPM|CMnv1&TTki@Dw59vwojka9znB<~1BKqaK7pvODY-z-*?-xUv z#z!rChSDrreNQo4*&hT$d4ctTA1LwadxF{6TJ6F!l#-te*N56uFy8q&~F1;*rj|@Ka+R4!|UlySYfpi^up?qjgQJxk%oXPR6b6xg5hkx@?@ryu~!; zg3(6E(Q=YT%fz&1Q8e+^dcInZE`}~8xv&a38e3UvP!T$R%nPQ1;*aJd{%BE}_@n*H z;pl!Jh0#tQgOudZw2}Oo&I5Q*&DO2k+9@R~8yRb8u{|vH20TM$Yk(3lehFBYove z@Fo?$VkOv?Po676vRZoY6TErq9l;wj5V#63gqhKoHh}TFfhJY}!U2p4 zfD{6N6psvG{H}n9NaJS-h4DTBkCG93t8)U65&#dR`-8*ng##W1?*;HEk{>y*{>}<` zV0xP1ht=OGMD&Vnf1}$o(<_q&8Okvp%!H-@CDXM_gm(RAMXH$Y;lL7fN1AJ<80_ae zl!QU&ytDj1Y2l87pgQqlfg2J$S;{0VnVPos`fId36#zn+ZZg56yX;Um>FF6O1e!u5 zOaUNJNxYIo`g7>teERp{Ac9t(C(=cPYeRD84fKeg zKSdEZ-c^)yk+%d<(=Q}3hDrlygH*df#2CZV93#+xf`3?esr)z<+2z;H6@yHz{`ZM~ zTKx`0zu7@CJxrKtp#hjc17#B?%)&8|VAkNO(hFwGb>Txg!7PUflWB>}VZsXGd0&7q zVfhFX_HJk+vmEyQW31AMV9y1nRG6?oe%eTJZ|9XZ$~RyG!Alc-Nae2pA8hki$i|gP zp7X~{A8oi`aK%CiN$O~HQb*kcu!Cr3dWt7&bizgH37dBUXnbT?pKmg(=Xiv(Ve$|F zpjr8@NFXbac|S-X)W8M_q+rVjl>`zQ20ln65bM{?=H4RywJ5QxU%$qY5xS9JnS^q} zI!b2P8n2BJOy6wd5*vKe1*6Es;*DnUt;?>J@Gotmt#@I@{on6M`jpm;d$KA00P|*M zy+ay`E0e*Ja)b_|A*~TzQYwwK>gbMe_lrbYOKi;rz)a#LkmvFsrwnKtr zJ>(MP>bJ9%w;<(Kw`xe9XU!#ZE>mwMV>k1pD`Ri2_#k{k+xvh>Pj(dt3olL+EWCdU z1b@A_{5c5!zC=v-KKl1O{reV(+}CmW{{~B+bp?x$6r=D+IsKbL|1QlOCRf=ckYYg@ zx#RF$$<21-4zrX#mFETE)QCf;AM?EWR1#(MU-86L1$C^hS~>J{CN~>t$!<<=_MRFY zjM0q_E_8x37M7lGLpk6*DB;1CUtp_ljwt-zBs!CG%D{h;yf@*$Id<{ihc4p3N3sj5 z^oNQ6G9tJJHpAXC4Pa}66?Y2c{dhx5GbU8#8zK!Yhj2sR{47u)S#X~RB)DhKIndxA z*>`kgSP5)*3$Wb?pRN4WUI+|NG2xP;NyU2vJtqmL9}9@vay7gj=0f-X)U4ORbGxP7!Io}OxQfX z_YB9V0{8R`hZ2gtrwj*cF4=ANLNgo}#JmY{|KAgaqlDbQ-%Ex=@Ea!cU&(K9iCuof zmrgC{&Fm*}>dtNe$ z(QgxRGYUpC=&gB2BF;1zP30I-AJ^kXP`}=4nn}XIwg~Fp9%)UkA|VlKB8%3!13lFq zvv^P2Tc-7o3+BbA5@A1s{>=))aNyFknL@}wmNx!TOaZNKzzLO&hYe%d+yE-M3uM#a zVbe9O&#PzoP&Tfxl+PvI5R{iN1@WVH%3Gey?QhWLaedW42u`Wb_%})hn_{tZ^?T;A0K>2^U;QZxwhvr^z5kO2=rp#9kyny#ojy3^qr70ePOwYiDG{W z=f4+IIDhmh46C3EIfae+YsrT#tP}0R(^0%BC>pwgRp$|&Mzfp0Wn|mu54SW{JhJg7 zX+fhEabf7;mW>sUw4{bAw>8DD!4#jNH%}>bZWg*Y#M@{wK1!2)r2oTc;CbX^XTg%m zH7J0vtH!Anl250lkZ(Y8EQNyp>YxX%4|#BXunpA<--{)|h9~ZfP#whU1zQrvda&dx z=Jjxc-Syzl49_po#;FNoCJe>Wn5InDfR7@sF)$M>JMm#BOw*99zv6noUMB zP(C90A}F8Kx}7J_9>!Yd+X6Ok1bL70=gLd`hsd|28nTV#WuQQi+xp#D>}WwSZ=bmXth6* z6MZR}@Zy@^9jo;v{l2*ayPdHU(X+{jx7B3=-U(N-+7lamKskH*4Ngx?5w@2@>svN9 zJt{h+i1Sg(BD?mqPi4^~3)1w6uyAOs-{5bo4{vU6p?=x~qY`DE+SC>aHFF2;nE>R7 zE|pzJ_2w=`$9=}=I8JWMlw8aeeY8jmdt05l`RUw&L~E=t`j|%x&+a}M_KAM1si>;) zZ7Rk|tvhyGMdfY2gmdmd)roCIbloE@9=cCPE{nNN`o}oJm#jEOeYjeFq0saNQRMyP zK=gHo==(8R|CFEuAzNMj8-mXMZE74OegO1J;XkS5(NEcnmvLvt-oH@%=iGN7WF5(B zD%g!NtW6n10d76ruZ8DG6F>!sVMOfI!X;MA<8+qA6Ug8%R~YCrI}C!6%C zy9(4vVv3?cs%k4b^J`-o(I+4}{63;PT(L*pu_eB$B^90H_(t%RM6&Q*u@i|xaq9PZ zzdHNmM@e4hi2U8+NO7yfM8e3hbop952*lZ>5GSEt{3N_;1XpaO=cuIFCjR_+7QHtk zP4A^4M@ERLI*EQs6<8mYy?M`yAOZ!F$-8O6cMo`XegjQ>fjTC!Jht^rY;k$j;)$JQ zv7s4Bl+`jlI1&0i(1Js;V0m(J`7S44@<;MsAPyn1a&A&|a;q_Q7tf0o`r4>vsE~FF-&dZr3X9cJW!X0mF{l zQp?7ul==U@^SFz2}~L?|FRZJKyVkU(WuPpx5T#Z}m5w4f>M(FIblQ zZ2lMQE&IJrqwGLEh|w!qeNfp6OTHl(zTbolpEiEwmGvRxhn#rF@1+>VZ(2;_XP6IW zQax)8AINfauF`Q-jGzBdAB|vBgc0mOxz?t$Ila`knd-2dBdxb(wifgS#;J$5B`u6P zIKicT-rK`QXuxUI#-ECKVMG#$E%@pJ->5yr3+6VRrI9;l9Hzq{1K3Eh zp+fBHVQy>pS3s)%EOfZE@mjm4CS<&j6YqF^F^2J)rC>{mAofM)H>^`qOG_(#>ncj| z(F!H8w4$M*woY-DmU?{+Yw8x%)RlR|m@N4)nLaBWTeOioL#D^=1!oF5Igi;y^u6;@ zU-6sF_Vv}{udhGz)~mle{`ZX|yI2k+(291i=}aIS1>S%ynxdf4hT)-wUPloJiogla zn;G!Cqn@A%afN~{@0RWf=;<7{t@~yimm=MX^EGa(#<)uS=BWwcS1XVcZ+|}+Lx0~G zvA2>+xZF8OAQOCI%8v z;MH;J!F%=IhLW>;B6|2n^zd993z6=|`C3D7>+4BXZD@ZZC*JtfQuP*zH(Z zVRY#~^c%w7VT-gx`GQbAxoM_XO3g?3MCp@Wl5 zR&QBX!5N|v{C}8^0jl4g>p99g&nk!y_;%+6{pY5owb1N3zsAU_ zt{J$h%RkW*J}5{38GjRMouL+-PN;vdFPPi6B_X@%bl{48bQKt}XUC&SN_N5N+`gs+ z8}bwOQO4HbFWw6VA0GbtHH!d?3@qO|^7^c;UEfYt#LcEF%ni`7_$d#%cWZF|FqpWG z<|{3|VV0r9d>UUi(l_BO=O_(CcUJ+;q-IZ7!F$15Dd$*M!5hfwK+bV%UQ00TTO^SK z^~IWG{or>kL1kwNt;Dv@7LcdAu}1vDZSVfiV#_Xv+j?T0+rDcBj+JiviDu;e0Ov2d z?YmRm){_%({2Gqmaoe9xbX(sY>$bmJR&059yF2OKr`!qeevh`R-vj$``MA1;wr3 z-l+!1--upnzE#;dk&E_bL%erC#06hLdIsn3xf8lSa3}4$(rwvwoq5@l^i)mlx)Aym zIW=+eiz{pcuXgi=Cb+z&qO5@=)#tO+MO(*eUPecBxNZ1Ln+LFn!O`PtM^0~VGr^J7 zm!0QJ$Lue3`d_r^F6{!PBF}2byIuXQ?Pz=YS8Xr*|9iUnK1yt|`yXbD*1}A1@i8n~ z@~b~o4>PXaTql3u^oJ7seK&3~R4Tzxfx9A9YQb|SZMM^d&(5Pd+6R9cu|B-EE@K}V ztK*AMoihH69XwUfje#Nj%0XAF0yclo^yg06ZG>&lv*%pCe-Jh0n?WKGC8Zcxd?5yU z#NP*Ms;t!=t$VDb8O4YO!E7n28l)G0s=J zEo_z8fa~ufe?N|Ix^24`xvjeoyRA>#OP^&>K zaSie{C=O9=X7Fb;)n*_`>e^O1w}GkAWP+W8Fcvk2zLovi7~Y?h_38E}kEsjWg;!38P@k^P+-2 zgSyFu%Mg82a#z7w;yD7PT=T~)lLl5fMNnw;83kdp()Jd(a{C~92?o4%_-W-De?v<8y8@*OmU>R~W5F9f;a5)^k%NJf@N>OAT{j^EeS zRMl3P=~tE&FTO+Iv<7 zBbN~f#VLF~Ks!qFp#c)ZM@&5rV8KuJe>nfK?tJ) z<}}kI>yXnBCq~~B1N6s=(amNAtfw_h^z(r*Q9B@uW1Y`k7MJxF~yTa(V+3`df{2eJ<~f!KKbkGXVavo1f9r`%I|mnOV?e z?Q9B%aDngFm(^AY118Duv8;IMpJ4;{vGf}+XhR{DtLKrQvh?^*BV{jwP=rz?xYAj| zgFdOCu(Y43fBl-W^83y78_SBf{;^n?Tp6kn0kIIaLBb3m^*%3EFzW$M8%S#sl0Ety z>MgwsVXjlww%VyKgrG4~9l`9`#%>sMvY>t=A!uDHK+ZB+y7 z?D>Yy#>~v=UEqAgHwGrJ@S_R!1MKpoeF?>I&I7j_rV}OV9~M0`j2$6nwALT>b&clv z+;~5-;_Z()=iMJ>%2M_R>j8AKrmxg`U?lZ`vGtk$L(cwMKP^J*HTv6IQBxxnyb>N* zR=n+BaDm#-J}x(SA?S*s{r;DNYA!I?BffD6*o~0gjBG0;R0iBcFu*r$)wb-r3}p|=4hdZnd{Ypc8ko60Ndz4L17%J0`Uc#C}< z7j8>lb)kIX>6w$vvX|mx^KWA z_*_isyvLmm1J_h|9UjuDB0SFDxl`e5*xLCEl>QY;zec6sq0*<^DZA|M5htAP)LmKb zA-i(iX}jjR2cNjjjjg|H<#ywwOhq{hAuPIw{oY{bKoH{RQ1o-kinTlob^|vtucdh=q#W zfFj0^k7L4+-;p7ktAH#NYbI-G9vG#@e(n-YbuwmqN0p@AgI+b|Q zwsa38M33VcF=LGsmN z54i_KB_;x=t{N(kgIk`OvUQEP0e|pH$4p6G5Z?!iN>lGJ?r#Ufb83MD=HXxjGzw zloeVJIav?EXe~nb3{twMLx(gACP2%LUBuymDi;C|JnLe>Lz*Hy&1lfTwMF>i#f1gx zt!BuRF!~kVjRtuV&xqH0a`M2izatGp?VzCsbyk&*?{`cU;LXQKU6k2cn7R63RItVr z9&Z{i4$na4#{ElZ0OiCB&#|;X16KM#ghsTjbha(ZO51z1wJ>Y-!N|ZD+6Wp5@e}j2 zzM-PrAa6i>DCc6dhihywBJ_c(#;Us72#o@AQ5TJEEgT!i$nXYHd+I!mpeT+05JXPA z?TLi{E@A_` z51F$?Rfg()r+r5nGi$x7eGVXCz~ieO8l$j;f{x7RB!6fyZ;=g3UvLmz`HP5wke+fG ze-H$n&wQY;@Vlv<6X10GS_HtHP2?shC<{elv|tAwNU3WWy(#9GcA!Ou$SD{IFdsPd z3HCF@?jFjVS((D`Zbum+Zipm(7-^so8?sZ_tHmEl`cW0+xx7C}p3sr10)mA(fTIQ_ zP*_R$BGN<5{ooXpBU5a_Gw9!nxcU zMxqyqxcQ4Pbvo`hunm#%E|W+Ur2Aj6LjK|^)QykQt1aykJI9BHrvnY&0yNB!?{dPx ztLV=?m(j4ITt>qTwfEya_pbpB>-g8`FO}opoOtmscwmT=BJKY8eB$5FEWH~i?&Y>W zp}3dH(mU>p0q+`-t@FH*?L;8k93b193B|&*lBIhI{kh{Zvb~IK8LB0*=o|$yBylAU zTnzfxfNaqq9pBD0$V)iBof$8_UHeytZ(sNf(7PFt=v}6HjEmfbDBLpKD12aav(#XA zRK|dH;RQQ9vfFuM-)n$XC;@h?`7=!e+K(<{QJnOmcSD2w-X+qO^y}9&D?ixGKn8EH@+18eiP%jVvJo&A zV@j{-`Yom;qZ@jbK}{x&1+UA|-o+JV_r&H%TAa&WhvEk5I)MaBdPxR8v&R|Yx zRGbN18O{D~jKO9P3PVi{%Z&D-MvqK4cCLoNlS6hVsyIqLluu!=GInQDj?mcEuPHbO9hLMg{4kC~DOE4X7a15D6X>KdFtRD#&wr zFHQyNPc;SUfd~rH3Z@|4!ak$xbT3`l<%^^w9Za+b^u!1)0CT`R(LCzGPhgJ+fzc%i z33^GwE>mBypT7Q@^rdY5jay&ZkG%e`Vf}sWv$y_+FR^SH+`zr^abkxE6rD|qy!J{r z`Qb}0cheA2s&85*^##(=p6`G*b>Ib3TLeQbS#p5SW0&e*M$~dLn=M(4w%26LW&Rm$ zOTw&KpiMEyZoZ7DjlIWBaV`m>Ci~R7#)c6263d7;x>rB)rN0L3y!|4Io1(El;pkV& zmc))D6F!yqVw5|XmpO7o*3>|?i86AmU5>{N(`rw z#`==r*o$H@2-(vmA%+K&VdbT<9OMX|)58=m-Ykz|Iq}M)GNbBK_5C5ElxU%Jl^xlT za%4$KjX6AMStGV%H)yeXQTdK6gANcIWmJX7zR{3^uo%WhYlM!Fn_~3#n(2RPZ`}0% zm`~VVcoVlw>ZiS-;fBVWTWs2H$jzhC*fhPd=q1tKFnJ@zBfl=*@x4B3ds%!!LjL5c zD_?W=3T={fA{aTg^YLws zu>ZP9v?n5-vn`f-AhtdsApy`Nx`A{qXk@}fKI3%w3z=_#zqseyyh{#$_njB~MZ<6r z;qpo#fquo)fR>I0aY3jlM7SATS-|5YQ~YlSLh3{frWp-nlP?9xvfzE#6&wX*vDf2b zfUKCG{Gh|H$-a}t|BlyX|QbZ9UI3u*igt9d+ESes}gt86NnSQZ%yz#%IO$T%Q?@$ar zQ2g)k#_BNGzdXFZ_}?bi<-|+RltiD8k%(sTj1^*_y;+3xX4UDx2mW{n2 zQRCAZ<1t@@*tB_w$y^xsG9q|r8I$?qz@}i4qb(!YU3_7e5fjvk^#jluLjO=syzn|e zJmzpTB1rLZ$|$b)pA}x@qO2dE49s2jKFjMwNIYf$xraiCatlQ;Tu(VQM6Ab&mP37L}6hz%D1xH*{zQG$7+%yz{*HC=nb+qnxJR%Ud z|Ii`kd5Ii~W%M3$dF|i#1X6nsIdD=Duzr7CPVejMoyV?t2oE7>Si>L+d^!rjjrP)O zsvZ9d@8HO=_$-U>Skb=n&2_Y6a{E^I~~qI72iW^RVN zq1D1$Vuynq>Of3`?b$fNkNjt_&eZ}4=>3hXc>8;b*59EPO?rPv_TOjjPkp6Ce@@dE zL~^Bxs5LC`a#jhsr!$3TM7&Yqo9_yf6ooaFx0n1IGFZ0vXVw}9XQ6_n!=i`uIM%AozbReuCJT?+B4Q#%7-&X6 z1n#70);umyx(F%-#vLzUu~qKYn-vu|khD|wy%{%z3#8b{)O;896oH%MgJRHpH60c}^HMARvdC;a z;`m{ka=Uu?C*;>4=jaE2YCbT1+c0*e9;WNo!!5nOx5!Hx`SJ*RE-T4CeVgqkv|bs? zpEQ*hq0Py;r#ERI^TLy`kGhk8+J8K)&7Opp&>h1|x`lNUzUe>IL)Kp0vkwBA_vRrW znQ-Xi+QUAc+B-KR6G6xkle{m*XKy+BkUi%}AmJxytkSylEQ=D6sJ{QfTL|-ocxWlU zYk<8zDC~KkhX+Ftu#K!t(!NYQ5vZo{X26AO_Cda)1n&0txqNdN*jUrPCW1(+6cdBJ zWH{WQ!LE&kL~Hg=W5E%V_GQtN6ZTzAhta&?&-vFx!GwKqUZ$)vqEOg#QN%;mW){$o z#T4h!!!w@A^Um%)q*dT7`MF!wUhr{Y&tvSpvI1`2lD$*u%ZvA3ONV)^*D}3h`2#to zicH))gUXEK_kPD?qanomAkhm6duQUlJ3>X3o!2Yfo8hnROU2d`W0A6vDv)ZBwiR1< z?Lc6(lQ{pMV(ZBvNY@oxcO#gZ(lLjYg6Y@I$eDTl4L8o3UACrtZG}g_o;xppe!+rk zuvkpLQ<=UAE;QuPxO~XX#6#a9}j5Q_C#98&^K4r6|h39%lYNG|(0O6?D^9*%}s zZOb2giXaG%mRF_iMdX-pb(?g85Obu(9%6z=^TaypdAaqpAgos z1gXxr5D0oD)ZaJY?IQd84ngMU?eCk@AGGKj_dhmzDX0GN$x1?LalxI%_Wb4Z3vfPv zZt+|@{Yjj^aK-YKh4#{UMMX9wW-ESm4D?63FbyZgj!spHSX{DE1~P=E0it}dC5n7} zxq9aT=7y`cIa-c*lkQ-oX9)|xy!v3yenD-G)Tk}NFT*EZX#0>8Z~JbJp?z0IYF|QW zIaX`*UwKU(Xz~cHmGl)_J6DpIx9^QWfieRT?sYM*5#HV5M2uXK zgb<VsaV%sBbD;=_e5(!2HcF6v5;{jN}%a z^+rXo4uN1VMFkN&92M+C1>xS?RKdRJ6_hK$MXVsrDt!e2;l(3{U88i4VACg|bBQ~l z^B`7&|HiaBi{=fK_E`yiIF#Ob zWV6b>W%6JOWoxT_kYX78XG$NTq3$%{p-oI2jZKKgKwwiMejQ$kuRxJ=emEm-FUE;^ z(@bT5x4zhnk}E1-z+WjX0Ljpmmo*(ZU3rwkXiBK`%fAVAhbVd$U30bH2A|85fMfr>;WMREgHi4#{S@E_%7K$i4j`iMXM^6+Y ztCXMx2sAX>h$6kvo-?uTU5Q<0A*;#h(8WaVjY0&&aX=c^My7`lF9E<{jF&){@kR=} zLE{_m3z6kSiHRULMn;OF(9f2~h;BnKsIGB9C!~LbX7d8XO9_bowhu2QXzm%OTjbRN2 zhlDk_6JZVR!)C@!2x-uakOt2{$MDZ?XXidRSb35Bo*t!;2CpIjLa%#h_c`oo9N|to zG44|jWq|MmSn6ooi40{R+%g!#6Tn_6Gc1Y$0F1*J^ah5qu=#^oF-$xza+HB#BFX?) z?Oi0Vr^7|ugvg-`9OyJGUHm6(A1Rc<5K}0FMYwO=O?rW}jzh@y(G<$SWE?YuSpcAh zdE)a_%TKU%@?wQDaD{R!pqH^Pr6{x!^FG+w_at)0?&h}Y++oF>3zQ1wemaQE`=il?X6-#t)IDI z@sa|XR2|rqW#AQrcCpJwm;n@FYyRX)JAkl<%9g07q1CwtJ1ZZhyh68(gyCx6VqdjN zUO88-((lLxNz#tvl+IL`R}ZBv@>jYOJ7;6}{6hEO&LS*4ce@cm1qP(3&?o-woTC|Y z5AAljQ^4xNBoLuw#$u(*bUVAVu!VoJdqnqCZ1tS(9^O3@2H%7)?cHdz;6{eyYUm+u2d=;IS`LyxXjR76-s;#^p{14oCqG7z!Ma1{{zI959&q&Yuc=0MFSb8~~Ex zV&eeR3RKXg#{mZGEH2*zc~VD9lR8va+Ui)a+;n^=q%s3w4_73i z{j%-1D`y)IxZl8KQJ9gUEaf(i0Guce!I1=w=m^-ESYjg0s8{wHfRYK_1Q_P0XXg_b?r+)e z8=>ZB<>qH@0Ni9{=V$U_JV;qmWd7`=JtJ$eQ><`O6kjwP{8gY|90V6Aq9kCb;9 zRyGpD|<5y9$}Un)W)o3)R$>{bu_ZPCFuKa+;D3&veWHW^T%of z<68KPalvX=xjU~5FZAlMc3Pqz6QPT3&-ayD_(qV)#R|z_0i{t&m&_L zGy8(!NHkmUM4BY2YCc&ap87S0k3)Quf3rh@{TavhhG_%zD27)B|$$g#bng3kSH-sXu>XeZyFcR<2 zpW0q@&5HK?sf9W;Xfe`9DV<-$9DEGJy$i$Mh4a^Oe#Wpipdm_gs*>EeRuexYV>TwR z>v*HdMb}I*2|SxSoTVlKgv%Jg%W#iH@Cx16rit)p$r;FG6$42fc3;rFpApG@5(fyz z+{`NX!`zEbFl>^TfW?92=XjHLlLVPtA&B2=vLM=P4-0QzyE4{-r#bX4ym^65@N zqhAzmJVhhxwASv{U~a>j=)Vrqiq&4~57SaILdrnsv07=Tgl&&RbrTSqHKGMW1yk z7jxE`WMGVbZ6JBQasO%~&xx0x>c<}kEp7ly4w<^tz8}>zMa0yL8^!aa>(=kYC%Uh- zq?eY?ufXHJa&KKjex0w@Tj*_op`iXovGmav7GtKEOlE17Q7ms1rkhy9^N`mw`Fn(~ z8y)^a_p!FlC@y2)(H}Aj2SW7OCOVVp2K2`yHxTkRXbm*g#MRU>h9{y*=5?0YP+aR@ zVEqoGuM-m;03*r#$@FI`{h8tE%Aamgo}`6B3%)s6=}d<7%mrKoHzyZEat7%*B3VLm z2LBR}kd1`|jZ4nbAUPWb={ZTxhL|L0gP9H$YtKd2p$;M)>ZdF{1HDc17=|s3`-w$P zy!hkB=xg?6{9(`p#-Q)}tHB>o09huO(T!wH9;nHx-%yX(7FpboG}l1lm{1AVNt}qp78)WJ~8^Y;rJvcUVKva*~ceey`ZK9mykBmjRrK^fWI1?BgOpT zGz+uR>p)<3&1it_r!-+3f6&#Gz_z7wyENDhR4cY~2CIO>iAw*}jSzD}!Z8>Uj^V^> zO@y_;OepM%FOHQ!8t9yKgN86wSP2XPoikim2@EsQIj&1Y=P)6dw^OJs#)AbWKDa=lT1$T+I&FXI`OEp@ z7X)d#j9-9WA;vLSI2J2LWK8H+{z7#?!piZ}m(l3><%Tf)a>Hf(5@Cj4#xGS$%<|oS z@yi5=ZbIbFl76|2UKr;1+@lvM|6L2Ga%TKOIq~8b_)UzWv(>F9C-UurV($eLIYbae zL?oWg$`TAfN2!64Cu64>iZ?;sJR`u_cmL+e@Hn~ol=3#}#48_JW#Y8x7 z&%B8U79N{L;Xng6{=$Tj*_$^|%v|1G*tq^wBG^e}l*ef;){pni&x*ACF0F?@{xo`;Xfe`9}LUPgT6Id2|#8i>8(Y z*crEe)a|nz;g;*n4#3gP>;P_rv)w$zgIs=5#OBO;opf+yy-qqfDVvfyINHJTsp#NP zvrk0_XVBm?d&h<~o`#BwFLI26?FUaefKgahy!MWn17l!qPnAJB%D#nNU|c*Z1EIhQ zx;JmS#XFR_x=Hf*7frXWKIrk^H~lZLhUN}C1$|0_5A*s#IbVzuBR)28?YFOp+kQ6M z8e{MnlnF|wKT-%w%@c;Drpd)!C6Z2CQD709Dk9XXeSyI(!KRdb@c;L)$A9~DJK|2+ zZ!~N*^EbhQf0~*PX9Wn0E9E*)6v{0~Z?xOa1#D_l`YPSL)}-8W%p7`piGQ<8@eN@^17xZV4P~c2Vu!{+%}>wG z&q({yA-q+-Bdz5}xT4JxeQdKt>q_#%=-)5=F0nm_K4z!;Je4B{jnXm_7P{%#U9AQ0 z!TuMHP``G-|Bj_~Wskq9NAV6T!e`0xz%~rnhTWmDsoe=+J7b z7QAQ4PiOBKr52pF9R{48!C#xNPb=h-l+fn%+|3z{Qvu94HVl(q0X6gRK)QNZElLmO zrwccL0UNBj0d?e(QrUTh(wPIeYXr=-1NMFm4aeJV`>sTH!mcz8{2!XPD=3=_o z09a#Nj(U@G4{S)lDZH@0?BARPN+vfyt1&^nJqtN6z)`EZ^z0plD?H6ePdcl^!c-OZr1J`)F7!#dq z)py-1J0i$TOu8s))0ZSEfss**vH-TZFK!+xc-f-v(05797`xB^+6#cVD??y_!?$iuD)?K< zsEd=Di!Kd#b~s!@>2OQ&m3d4Q=>_S!9MfIJa-Zh#0XL}U*)vfCzCGKIUFtyFH2&q{ zZ`0^cs20r#qn}WzR|5GPxnJs=FhQLzDgo4KLFsOZ7L-mc$Y2yIx$tRkbV!=TW%SFZ zDI>X;`!VDwF}ZsjS#wSzlZRY*;8_T+Z#kJfz>5n=sL-E`i^}p15$pzwa9|Z|m&X>| zHhOW%Q|6mqL_0jB1mB_&fI`o3Z2!k~`Jodm* z!lke_g@rBlfh1mVuMDaBJ`fFm2y;>$f6Ry%e=LoPi$Bx&<2x50e}v%(wmWMBclsg_ zBxnUq<=PMK7zf-Dep|c`aNluB>kMT=1}Oh(>xzD1%gzfnO}jAZ&*yqYu1mG<74V4_HRL^g(oMOkLYJ$RvwYc8tez zXEqQp?!Th-&bXhcQUPVjbt!Ohk;qx6)_g|-<+tWLA^(M3kf{qLPdzA88U?CBfooFGvK!O(m#lzC~PhUVZp0Jzu+WZE|W z34Ori#3&GvE*l}(?*Qeey14ZS7KQN%;nhLlM*&+QXNi2_ANb&h$0Tup3&$6JI z?Y?Kz_T?uQ;*Y(slG>un#5jpi=&rV~Gm8913SN-Pm2e0?Ktagagh;oNg09K8rt^~$ z^IONFa28T#Vdb3z6qZ`Lxe5qxD||gzJ10X+H^Ysk0oRLgeFv`Z#&sR8$qy4bY}FwZH@XB1Iu-EIY5Cnpq+9>r)h<3H?Sr zLY`=a^otZ_o$-e0Voh23{rnM-iO`;+5}`jP{|ETgR%|lHX9dZ{vf`EhkB^GsHJH-* zDS=MNw=aF3`MX8^I<69+Lz)++OLa;IXo;E_UN%P7zj2+nmd^-o|AG2bR=o8`ES4w~ zqE`RyadV_IE@*Y-`Q|Iyk(Rd>&pu1rp0LivyDDV4_K&o z8gIZxpJ0JAZSO3m_91<|hzzCc&Q|G40c zqQKTAmF} zek&+ilw%i0zx2E z6KgSGb-DezcTK2$5zmRYzAy}mg5k8@-A)mh^@&8LMbfpt!J=2RCDia}qBheCNX`m# zu9Ys^%ev)>OFby%NW;TXIU67`KJ;dzJr&xEoOs*2E{67U37WL}j@(AA2LN67%QhmC zjAkdvkjQXm+mM#q=-}qc9G|o{I^ej~0UxjS+z&Qb)pMdXlhYr_KUfHdN|#!Q*VsCRSySJ5e1vv={msmaXSdW zTfZRfQ`wsRFSJ2AE3+%;|`5f(CTF>Ad}1{{Rxi7* z1G0?Ck$MO4A^Io8|2O&vIq~*SbpK}>HrgR0QfT-T-;pw>TphA=j;f2Yau<<9^+j3P zi-^lU(sIO?&LY4gFFkt^xn4(}*K(VBK!bYG9Ju01}WWENTCKJ zA;PPP{g?AO%-)kA<~-~@#|_-Vuod2JwADcI$ zzCt>sMXs%HE7-`AiuK#27N&1~hg}sqvBYaF;_`)1dr>cC#2Yg+`r7bps*=cnjC<-1 z^~bF>cKf8*Y_F6Zdasz2afYRZE8|GeKPyC@&$Mg9;IcjjN7dYAG?t7!bn69h867dc zbR%`Q$=;4-#M}SbQRhO;{eMer{U0s3r;PVS5v-+>X12y`p$C%Mb6eZ@- znr^l|GVauh>||HjF&r=w8ets60-SHLhD91Dv)mmca3_sTUf}049)cW|G*3ZY8b#%8 zygYM2@2T-MR-(AFV;Ej!T53pHZm5v2v7(`z+yT3g-=UEVCZW~@4l-)~EHGS2ToPLn zMWU6!_r^}Z4yS1ZHW{P?smHqqBPq}v(RbMI+k?sa*bc}9VM=LW#2~DNE*N6K`waUr zy)3vphcL0eu$*|;m&xez$UfLLlxx7GT10ttLdR4wPq{`_U6cXKh28@eZ}QefF1i&+ z+IpWWcrF-JpVQV7>P)_#=-Ww!eGp|d#!0QlK&uN`8Q~lH0^}GW=th#~&7#Hw^S zXkM{jMExG?ullh5VmY6M{$dsRto0W-D36)nV>$8m*PR-C0lk4#=g}C<@HJDw7pZzZ zRTVXB1$>pQt@br?bgzWse}>H!3&-YEGsFZX2my-=m_2ux)~zd zqzVM8zQ%gss+G7)t@9E9iW`Ow7jZTNhk$5>7_$OLjxUZ>eeaA zrDQz>$z&tjnHzJkrJ<$t;M%HM@i@d4$}paXkA!F9lZH$qV??0B>d)R+CuJ)YR=!mG z552Hw4FIi&pv}XDEilqo3tm|J6lI;d9?Pw#iwRytJO(w-&cvr#C5+N$Pa033q~}lw z<{AE`vx;{H^Ftu*7#y5Ewpcw~1;^5rYAZQ8K!QNlg%ER;>)>%8*em+{O?~1OeGy+V zmA#@5ujn(pBGd4SGybMC;uU8izG6Om#TmTfjNuitl<=$E%{oti!F%!rUZoPe0E)dA@dcH1hhFer$P0Sp3$`nja3X?Y zJrQ5fOn2x7J?sUna@_umwFNzV-dUAOroy{b`*MUV4RW~Chv${`T7yu6|wsvPD z&4B)Wt~(9;iBr3mxQD>3EVX+Tf@0UgP-EWC-Q!by#2^~0eNq^N1ph-d-#b{ z?!mkM;C7zqb&oi4)}6N7;vRG|**)@Pn%lKI9p__lex-ZJ?yGS=6Zda&C!bu1>!oh& ztvIKVoghyX1etu?3~Rw_I`)L&pF+z=Vyxi zp{$giKTG6a8IoTp^2uya5$AMPDbDB7g(1ILoUfqloi{?tN|vb<%e?za`ZJ?=zZJHD z__KokY{Aezj`TgG!$@x-^%BK?1v4rq?%t&k6Rs$lj3#pm-kgXKQ!HBASZ4Ok!~j}B zjxi18z*-|7lkK8LK})B2OpwLF90awQj2atdai7o*-L%Jr%Xhq06(;!(uH*F%w_spe zYkRs9VKJ1}KE%}GyI28l6bmMeR0sBu2$l}I6tY54nF2mZn47k4CRMy^>+LR@A6suv zr$b=y)^ZmSW?ReC>0q=u3o%sS^ro*COSp-@WjXQEo6#kb8h;A`kYW)WE`3yEC8VGb zoV!|>p)PfP@XCZm(b$7f{fUn_V{`o}C*Jx;-;=1-fBTiD9ZE(SoWV*{SE-oTb_}P! zcTWyy7kF-t&zbWf?~Q8y9IQ2CC>w&WLdmJaMtPPf*V+i1Ly~QzKN`%RgVWr;hyNfH zi-VNTVek`it=oqE{CXT`f+hNKdUlhhZW8n?WmG&q8B|ko!JWnS{N?ita6W%-@mxFo zNu0lM#qyPf_R@JpMK&bHSwa&HSc??#Pw%ZEN~ko0M1T?k@KsQek|JUf8m?htOC&T) z$y~FPq-&LU{fYME!!7Dh8S&O1{LMi1hY*wa3wnFj0}VN1r>|&%41~t=iKgh7A?GSh zQ<$BTjvKx#$w+9&j+N?rWMC}wr}BKWwhZF~`H81-P0jr#{!iq@3(tdMXdwqxPgM;W zf{T{2olZjYDeuVEZg5abhlrL^!>DB%-$eBz&)3#01nYsVgt5sZib~(YM6~9%mU8ptn~%xT>ORU8NV|z&~xX zD|z3x{B6gRbI+avqE%hjfCTVLDNy@$^EQf*Cdv?a|^ zyl<2q>^)@l4(WZ~?sfJaK%nfN#pt5OslA6-h8-ElC}T?RA&2)!&%<=y)qKVg_(k)J z&4K6eh&QF@1Iq1ae&5=A!0v7DIZKz{Zhqe$*t+VDA}&QyfA%d@Ea&xQ&2z>p-kh`_ zImgeMKOR=e`HS1^96!*Y(`mA^~-@#^Dk^T(&M zSNE0NU3#!BalwayUX|&G)qRiQP5wWw@OQ0fzE$x~o|WV~<4OC`LS_`UaN!+kKVEwL z_lf?ll*PV}v`X3g4t@w9I952rLH9a>`KYUn<)PLTOx!!PEs5pcp2&ybB;9>{r%UPn z$_R_4`yKo_F%^HFYXfLOn@#p3#E22Z5di-0Hc&iIVKWKOQu>F$Nd$rF1&6>dD`5bq z326b^$it`jY}#vRMc?jR0a!po$K3_Us=|m48?W9 zruwql#;Uqn!?Og_TE2MJ0Q|lkz_Aw25>p2O$R3kWKSe@4;^uJR@TmSrFs7c?f@A8x z?ZDZBR$n)Gu;UP*7rcRI6-bytlk|`*{fWEpEj@A&ci$s!wE(;h{`RrIr%{ke1qlRf zueSLg#k;l^yg?sq>&ZFVzPgXGMr|)V`rG!^r`@aWWtZ;Kd)wZA^tYZ54m3CW7WY2y z@?}gp?mhbGAg`3k62*SQUUY6T2Z*T|oQ$4#Dw^#qUa=k=S^c!Dypo&4<)`J${xA6;E=G%c{l=2QzSHGY8vG2;|hm(}R z*gMo;WiNgI_ruiH-TAiFZ?xIY?Vq(U=(8<}&dbdtviX{nwr_&dr*Gr9n9&Qk?| zHfqa3`h4yx^;fFz{p^?gAKD%s{QEDoCAO^#Zkx1iVK8vTbEmAo&+w>;9<}t`qlX^- zou_r2r*+}E1q+rhf2XH3@C`hQYM_+=LuEAnVm7Xfcw|_>6mO=U|g7mEb^6#60yg6A(Dlf0A-7u|O*~YZv>?&U0dWjmPGABef zs?m}=z-C)gOF@fa9j7nS6a$fBu|ig-=T_8uffMN-jQ)XP_RuLvN%&;35Hp-d3=#=& zhzrj_nu&Bh5;=6b5os3EY^0lz9u_~iYt(-`zd&)#t=)Dc2a*%Xg_MqzfixB=6DbRy zGs*Vp6~u2sFiCBo9^=#zzg{0F{f+KGQ-~1CNR6iLxt8yqEMH%*ur-j)vZT_|a_@un z6}X3v+gQ;+C%*c6oG7$HSg}In^Ey$Lxv@ZL=@M4!{4(#dvh@{>-@;(a!h*Q^Ib|{X z0a2z| zeCYG?ddYwzB}+y>%E>c7hIg4JScF$5Ck@=PA|IRfczP*E05~i5RfxB(s#q(|iYtBM zY(YbnI4ddx?Z|$3%i6LB#f3QFePMZcb7N>GzEK;Ri?20=7Q}Z$A5~BTUqeXlZDq1W z3o6#gx`6!Szq$4DY^he^+q6Eo%}3-N{pR}C@e`$}qF$UWFPH6IR>u%2^5<8Si@W%) zudKn`38+CsXy($ghVn}Bj69%LRr1R+Pp_W>(&@wsx9x=6Z9j1r_r7GbfhF`#8!QhAe(ManVf^m)29LhDzD`GSK2{>VoGXas4IIe<2-5dJpLXq##l% z$XWU=S)M<4Nx`&vOP28K|C4{0!B~UB0ZKc9SVisAsj0V1E+4UExKiTpBNX}QjAD3&PP#*V?@9W4>fIhxOwZB z{ExIe`sHn{ZR+;+zxm3Jzy0dpJ@&Q7|KAf||He1Jwe#=)q2tMKKh?Qw_tVe(<3D}p zyZ`*Xe|h#_zyEJP_~DO!yyquB{n^idv3KA8=MEe^^!(wj7mmF6@4x(ymwxr~D@T9* zoB#ane;s@Ewb$Qx^R3?ef9alE-&Kz5UlnEn;&!M<d&RoMpi|0!!#V||=bk^hPzV#jQwSy*DJXI+K2 z9FC_v*y~wNvJjp@CoIPxL05L9Vd^q6IIbcFNh`Cq zYF(B0A!E+EhO+v~9mX7ntvii5%n=p|vb6Wq`(S@aVsb5~vA(Rlg49M@4g)h6WGN8S zD3JPBHEv>`&!Q}?8I9#tReAK76NM5=sVipb1?UnAhedi0^$2oEGaw$JoErVoQ&H!k zy@6N_6iZU62bOVl4KGl}5M-plhOVkn$4ReSa0d!RsQvwYK_83jGLbBMxRsjv)fKp( z_M`b$%T)zVp+>ESb)2KH=P(46FsDK$p5NN!XvR}%U*%SuOetAS&fyAs{@z%wI+NwK znet!)hjJTCdH1rsHKsfV%Ufp5W6?V9E$W%gGvRhLZR_u;{{D|My=aYafxtAtRL|-> z_Kp8LQJnV2sJzp~Bu^fC(LHv^)!9heiZxT_*N%)PfQv#_3 zg51Ec@?c;vvzwEFT_`9CwFmF< zsCh&E$1_8&X=C@!>y_>iFdWNsTTk2uM*j|^RY+xS%PtQh4{d@VpdHtbA$ZvxURpqulUS;t#FbDakV{gvs1rmX+ z@;-X8zsaGbwfqB4_kjRVf(2(!eH9n5PsXXgFDdQITX7l8YMFt7YGX zNj=7}scfx&i#kxdMSU9O7Im?9OU>DOcsepp{WI!Py`=IPoa3W(FqQcyD$`13=2xEK zW$0ik(~FEiWo0rnh?TRb2W$y+FqOFp8G-rL(<wz}BE?a7+)+m@rv(cK#G5Z~uYxn%ma> zHcXn&z|?qJvE{@Jq#KZKLb?TM9?}A&+mMzat#qgES_5(P0}w}VhPm=raQ!V@|D!u; z*N<^LjisSFx$-Dl?Z9i#ur|uqt<76DK$8iacB{;6f@ryYA4UXT$@h`>JrxV?l zrw6-Jl#a2acAVIl8~&f5umh$|IHVIYV5&;1+#pK!ZZ*I*z;88#aY3a$<&YWidP6y# zCUI<3E$jC2pl+jMR?veL(7Yzn<_d)BNi0QGD((m7t*eKF)`U{*v{-9Iz`(?)JaS-v zLoQsI60(+XGDpsp4T2PB<|sh5D93b^iKV4w4eK^2DW#sO+O?i4u>5$~Q@g&RVO<3~ zYpkz<`-)VcV$wp?mw79dLFT176j9Tjmk0>jCAF1OwP~aS@Qx)+? zLPllyNz%ZOO|%pDSc}h6E2NgX%sbYBTN8k^M&lN(C43D<<6#9PF48fHpiSlL4ZmN? zXz3r&jda{Vb4%Cy>P7iEptt#MF3PT`!AOZa-GgukwXqDr9U3T+UsJW_86a71&S<_> z2qdCCLW3$EDKGQdu@FbP1-M8DbZWN@Eyjmng-1Fb%ylCHif%9xpj!{!1G*UNg1Xwd zmwGiPSh*Dk_>O6zI}$rMVd#K0Qt>smyzaeEJ;*4pHpfjVzHyHnfyvk+%T2dgd_(>F zt^NbnM~?Wq5eopQ#G8$x=p}^}oopyN)=<<%MSUr1BCyV>KY)m4s3^~ul(YZT?{JAv z!gTYe;Hmg~M&LcO#V1qr_jo6w5Ip7ZLRT9;HbyVxOVjA^l2cz|FHdV}!9&Q#Vz<$Y zg>EML4A?-q8>s@R4(UN8KT%o55 zSWPKnt+^Jk1Fj+u1*si{Jt>@FIrSu-M<>EAQ>o6=UV)V#T$Af?!7&TZD`_qGO~8q3 zTJ^IJ;;MD^%Mt)Qc({b93cTnJoXh-PL;h@>yW0z1E$sOv1kzL$Hh5PeTTN` z-)xIFLx-y|yv}&(S&&dL(}nRGI!%xxcOwrOM3Cg4T84`v`Pm%)94cgZ*-I#hui|C@ zLN7a*&*+wPoMSj`IJi*YDjc80i2oYtO{8~`{)F@~5*Wh7v>!MB4Qe1k9t6^9f75Bj zXZVgs`_4l84n6V+9#LO@?zqEtAc1HV@Oh_^ekot$RQp zy0zdqg2@#04)8K+4R87nu-+kTU9aN3O)WSMGrhEZ1-yF3p zyt=Zdb;lFzq`P$onK-L`0*yVOCWf;r>In6#L|z+N7J7oAyITp3F?4r5oiTKmO=k?< zO`tP|?nVN=@A*3{q>2|)!hrb-`uqibjIMnOTg7 zjIy!pvIiUWY@mPg7eVqM|Dis%emin{0|nKS+BZ*HW&AEf_8YM<6!qk2&ojnG&EHgr zqF$|vtp$BRtH}$}ew?3`d-|b&WBX9qmp{bliwco9!Td$oC!;q_)cQAip=+v_JxM)h zDn>O?cCJ)9U2aF`5~RnGj)K%5=XStCWiWO(rtPY6+jdWKC!AbgY~8)VZQ1>G_wbYd z>K=Xah2nHB~ zO0)NzscH;Ivp%ZT9zFGQG$5z<)NUH^toHmRQJ$EiKhcJw&6^)myojN^sjxkN86MHQ z7i(?~MzdD&PKA`R47b{gmNCL;tbtZ>8E6%fX3nm*U_6%idnl+uSfB617sbH1767fB z%RQa8orz0X6mk+#qTO2$WolGj`w!_{{Wxd8|48ut?|tw}_J?2o08Z0ifvM`Bcd0M> z-?sg^v;7xT=x1n|Qk^S3);m;yuy^+1M7BozhOH{<+1|?psA$<01oKmJS36j~SIbYJ z{Gkifa{+ed$oGHjc<4K9Q20!v`av*3PG4!OPCZc?93o5bHM!~TNz_CE0IB&+D3I_J zU9z3ln8RladwQ^rmM~tGOEvr6@a@y_LidRQ5+y)?p|+kIFK+Cf=LL%AOHr+o&uN#j>_HQQ3P? zC#u5<5E)w!kT?SG4V3MnXJx?!RImcLmC#OvbF77Jo@c`$8y7VoAw}>QP zQreFo4}nwkI(J@!0t)`@nfp9{0EnS1O^142ABxSPM-qr>WxesH*KZ*Ee$71!o1#aZ1a)%qDx|BCvXQPu%0apjDHrKhq}xz#15yXl zFOmA(qu!l>g#34#fOZ~tCq51I_4G%yS^5m*iB2a6avkUJty(NP%9B(>0oZIJIpK-( z-~Y@S6Ie!WgC_bvPI@>~weO5n@<~xLtCGZuths#iBE9AjaWhGf^RzUuX@C3!!Q8=< zc6$q5=`q~V>Di3s8vqx8s6K~JwzrTkszMwv0Cd2>;c%7?tZk}BIj6U`eEc!H`|(Ho z@F6?&(Lr({VTFt@Y;QS@?d5V*)3wT*^POnIRMv#{Ur_meQ5sO`O`>~P_fK)F=h(CT zK6Ni1vjJ2!!hp~f+f>M8#){9u#jA)b9!7Z$Ae{vjXOj<0I9bKfV5kVXuQj(N$fqE& z8%#c}ChDO?q&%8-BkUm_#?ul^d-RVOHCjBnWIsC8VXa@&7z)cVEPg? z@zfXS4p^EU^oA8`GnFVLsVh4XGt8+DR)0c7B=$gmLG8-kN;iM90`L0z2Oko%!6|&3 zErD*(2N}hQhlt?BLsx4LL8>DkB61v$P!W2B9q|Z}rl#*eI3pk7v@;%J^eY~sW2ivB z4+8l;gq6{K&Z3??Krl5mFqg^gL18laIcp@9k{tzkbvPAlq<-1@Me4RHrTYqZM(0&- zd-p;dm*Q9f=BgSl@%-))ox9yby1(xp-Tk54waeljwrdj79q`joLKa2i(b^e5||QbSFRE3MT3Rp%}K0LN~w9&&`F+S?G1Rv=ceX zlDW$kqU)HJkIOg3emz~jDR=9|w<9^aM^asLWZDg?>7;8QdJ{Y1j1H^0p7cpnRtfIt zz?cBnQ%7Sni4!~sYXRNVf3iIuZ`FE(yw=-58S%<%znLWEwV^sOy*)D^Nrhs`TUQ3D zXsP#$wb*YFCU32O&?wVX#8w)}DtWyssQyx}2@x-x-Bs0=)yxDh(qR=cJO82MAne`OeA=|x*qr#@+YL{nMXX(8`xY93h zrR@a|^t!*VIPJ?1pj2BkeHye7N$@g}qW#8?yJ9TvjTwzUqsW<~GIGT5^kGAX5XFIC zTI%3IkT9kypdXSQ2pXTLB-j<3)pCUDf;0r_i(s5)A$hnIGIuH%HM; z>>w*h=PO~tKcR|+Li2SSH{K$N}6WqQ$L+Ka{;UljVZm2R4Q#$MR7N_+Sn03B<# zJ-laj!imuJkj~wOpgv_tKSkP$bO7lv(u+thAst2fEz)a9Zy~*dbQ0;mk^X@6K2k5z zM@Z)&#eaNF$I&BaK745@{0B6r^cLMor%B(AHHVJ%aQk(jL&%AAv=` z*=;#_2iWx|ao!E>+f1Y;q@Mv_cRXpcoI{IQ&!5_d76Z&u4i~(wocca4x(d!>#ww>W zndFCnM1z1n(S?NB(Ad1wcay z?{ZPcF(`pLCbK#Yrs84(5is%zbglT-Y1Ew!V1|Ex(oZm}Iq0&ivDpXx`xCXyV@5!{ zN~_NI@CFSKL*eId`Ro0gG88W%7xm7JK*G=HGsc(wmR`Z2x(sK0>Y@ncomx)!%n+DS z*wd*!ajkfQH$qZBj#DF%FB_(};k5x9cANI*|D+m3!)$wS(=?8R>clwy8ax7x<71&^ z-q6eZ3ojFBWEBcQsIRdGyLd;CZ4h;icTu#;1g1$i5tv!)g#cpF03tKhIW2gL5=htw zH!2DjhLphjX7+D$4>YFA>tlfgsL-q5T^mf+)BK_|55n{5(X{f+xoX2EWt8>$bqT((6xQ2 zzL1yuitl|WkDzZue2miraCD68APo|@8ltV1DxC@(e$IjW?;>|XXD7~|hgM)3Y{Tl2 zp256^ZPLjx5X;@_PS_3GvEARp^?tYYBs2)SVF3U_)wcV6xBcBEuqES~_vzD>iR-VO zxc1tK4=UP5tcmEsP!f*z=Mq^|vymChLj?0wlDLj{e{KxkH_g6Dq@gCG%TNIt=nm7}sZTc~O!CR;8&;VYCeTT@1mtVL#1}n!X{Ez%1s?-5DUPhZ-5}&O;XfnzrxJ&zy zoy9K)FEmnbmuQb>Q7_xWZQdV`Z+t#cdvq)Nf!jlH7o|P0cU-^bL2m`zGmHH*{4(DC z0e=~IY<9p-!;)CKehmwD433Q3ZLf!un7WPSjoUCb!l-)v8p@eU8N3W`d+Shezg}h| zcD$}%vlba07E%QRfdeohq+&MK!0`Np{NgeR>FR?F6O+D)#7cy^Dejpp<&veyj~mFIuXIxqMA4GHwx zfO;VJ^o9ga7i!LQOH9-S!Muwq#-2;>&9m^g2gbH#Y#Rkt#awzGwjp@IJM0Cv!xr|q zM2Fn}88fFU)9tCGB~QHbP51d1)t|dCdY50Qz;GCR`eBg=qHS-HF8v#Y8 zFjWlMmSjY*Euq!dDuNHfM;dvc7(>o2m~VE7Vf1y4@V}645CF6FOkCH*IU8f~m&Ugh zh!0S!G@odIJ%EPRDrux+u$W2v+JQ0qQ*_sU^tkX>$D}80%M`;Wct43#D&ie4KiiK+ zR^SdL${x1u=Os_!lTfP`wOiUc`454Nf!w5G` z^Z1eh*5YN(~%61h_)Vrl#H@}M43*cTaeyH8RDxpAdxNli%1@%YmhQf zmWbF$q7V|F@Ox&71`~z+THcHx3i+{i&-@@0g?xi<8d)@hD1^*biL|GhGSV8lIZYza zZ4z7*$s$Iffw{(Olzs(gfAp>LCDK$bBH0L;bzT^5G`Ko)ObX)Z$p z#F}Gd5KOAZ_rDO<8NT?%E07f`~we~3K;mhJW=3IR*iH`M)q2?z9;5QG=y`3XwA+a zD&5n8omWEQaSzfDk$!^o3#8|eo<}-@^dCsCApIxOt4MDmy^VAN=@iocApHsHe~~^! z`U|8X7Ni8EWTZhz;~)jeMOuaAMN%OV*$a;8ZE#4S&~`6Csz$<&o0HFibNWw6MMfjd zK-%cGyo>Vhe%GDw^hr>29bX0w$WQ_XBb@idOg|sqld+xMCbsimAie01?NoM-;{4!H zSb0+%lJT(cCg-N}-F6CwiFrr79qNOj#zp9l_NxFd3w93D;inS$WxU+aRRhy++fyNe z*9d7rs`0N;wK_n~GBS+p3mocO0ZV?`UKf zodB??C$Q?6B;ge1N-)ia0-ds99SHkWFcgxpAWzDjgCI#816NBXG)eqAwU3ma)L=$m z%ZzyG>pQd-N9BjMXL98vZ2{riJ>7iFsM50!hlA2a_r4Fm$E@wYU4NbTYU`o0} z&Mu8NSgs8-SgwiqRtc;-xY<$bmpbq$$z|ZnGZj0AhGUhUg&w*U>r4T~j}yEU-fiqK z*f&b@U9*-8n) zlUXabBlvEe z1>V!LA(}VqA=p&4co}VvrN6X2HkEIHbtGF9qp$0fyUf0>Q-fAFqzx7;w%AhzDZC$a z=GQ~21Ye3g52}Hfoxz5VPNJ&N=t)-LPR3#r6x_yZ4^^nlm$J&YYP!bNrvdp}rs~(Nma| zh|+QFUYAej7~3$Mob{fg$}jFnzzZ9O(?FGq`L8I(v&I-e75q`>r-S&KVP~n#0kXXPlVv{1mf}U4aDQ&GPVy#pOlkRldR^1k2QwDYn&zr&<&+gRW^+I`&fS@dzoNMx|a81RIp*W>kk(d=n?Ke{{Cy%}ir zv{sgzk*vbwZQ1WF{e#rpKP-#+q}PNZfI_x z!oI*Kyt_>6qnaE1Gby^)KNF-zbidyjhj6>KIx#jLcQ1u1!-`r3^)ug(Tk^@o)2>70 z9M+dtFJW2$a{Ei|9gKldzI4|FsqF|@s_kv;YMPPEx2>DlYy@^!Rwojh%{-7l>1Xf7 z9`zGrNohu31#yBzsFxB|rlD)%PvIZj!1Ar14e$>Yh2ftR;-4)c_$QJ0=eu8)e@0+h zsLDTu(g`5~sTPIfbkbYOIjUCp1q@XR3tbnIg-n&UVHJ(n2o|~-;XhRql z`W|q{StxcZ30z{Mj&dBRoRkDk`um0j;H1dPu1YXd2!?9v&rmg?80s;>P{bnVWvhg9 z*^1tr;JPF{xHzp9hYF~xuo|3pN zq+~#ff+Shs+?o^;gGI!-kJ0W4+Wic>nxBu+>EGee10kd$!$Am+C4G_6k4eMvTwmk` z#pkE!KBDNE5ET7teQ82JiUvu>r(o34AxRSl5J=sp(DYS>rj14MplJdq8V7PV7MUE= zi8{C1=Jxr^Rsi*VWjCtioLCwA@Fu*5NIH^}^iq)Y;vkaV8zAX2kZ-A$q@yWTA`;Zl0ZR4Bs~;DB$0h_RbBzB z-T^Le=`>93kln%np+ighT*#GsqG2n@v15(+)l#_-wFC_6m8;Y%QSd3`4A^u8SkpGQ z@{tWuzvs2guG3Q`$AA}PMoOX|s}L!>Sz^Tks$iHJPNW)!(saLCj}lZvPC5o1s`!~w z#Yv)ypd6|gXTylfHg{f{rjEr_$FZp6Iqb^TlUh}X6dAK;QH?)TRvcg@Vd^}Z>ip9S zO;uVnfYzW9P@$%il$t6wjH``pTbu<-T%$2^7n`pfOA9ju_Mu>(WAbMzFY2K?Dq_ih*rkXNB!@urEzDvsT34y;6?Hi|IY#D0_gXtkKNPcwPo-d2R$)u;}JJ;mptVYZW z*#k+r!U9G?xZJHYeZYxI-L4?BSV5+z-L}tP;b|pok{p=(NLtxA+uX!?_W2BFp7w@M zTK3Zr4t>K0lWj}6`Ry6@Hr}h8gKR?FT7!!0w;GOkzG!*hd+ z{5)Mn6qy`?B5_2Kr@uT!py4u#6f%-P{^o5g#Uk-RYQspO2~u@Q8h@yee+6ax6c_uQ~!36Km1=XH;T%}qD5iEzA3fW+4Hi2rFRI}wW@uc|U6`H1@ zkZ3QAJTIv2C0uVYpv3uV)KRtb`Jp5Zx00X=M3M}JB&x_EGN75DkpP`HriBqX%=DlU zISh}~jfNIE8az(Iu#N+9g9eWZh8e%xOB@WL-xT~#=VACAo?Zh4%>~vlg!-GaiXZ@p z8x*XuwJ4Ex6qeD&Nv7kqb%#V<6!`5VKxYKtxBt)Kw*&rl1HgZz?llE|j89gFElU=;dE2p8nibl6J(7HV<1QVYeM2b11TPkAqekY$)J-`{g= zXY3!B_g;Q1<^a}z>-7}%l9KQut0CE=R;@>pGKc*^B2fdkM=3>N>`~*Wj!#|aIzF08 zV=!dVDg+p%4m;&3E5=HFR6?h?Shgy+*io`tT%|> z>8E7-r}VnY!x%1&SIU%+1GyFjxd|kz{Va0g-2HFKEvBdD4wHqxZ3Kj6Tl^TE@#_9f zn)ER^8wk~xaD5DCdFSV(F@)uxTxcu{Euj$KM>UrU1&p8lpHk@wqJu&Z>5qHL;}A&d z*12yt%KNkH-s1d&`k=?7`o#14;4Dmi3aLH|L)7Q1>6e4mj<}`?Fj4K_DitkNdSX(D zxY&oL3B^d&G}T_$OqLYtb#K1L{y}iBn|!&wUfb(xJ6sb!r*ydEyf6Gp=%o5KD51Kx z+o+=@|3%Fz@XogbIw_u#2v!~EBtt$*gV26> zPfKv3GHQdeD<~HOwaPY()68l1J5)?-^_w}tn1+6HRWPQ{quua+8OrQ`fb=$I!Md67 zeJ9~N8~CnSgI2q=zjng`emtlNQ-4O~tBK>&cz?#u9p`Vu7P5kr2eV& z#|#4CcC*6HTLf;=6L9OFXTQhSIF+=N1`j+qy*sz(eeraevEhC1SYGUD)m&JwZ`kj7 zv*Cl5PdvSzqm5I^V$|>^{68PJ9QCxR&)ZF&PER`wR?(hTI%?XF2QX})?j@BZqKU9P zigs7h?pEynUVRy9{*qLGtY@tKr9L=L_|X^hhWD;noN#^CBX7U{3l-;VedpP;$UZ|D zZ{_20411{L!Smxhhj6|u1kTTIgBUJF%wM`>Sr*@0DEv8If;ahlVZF&P8tKp?G!}13 zN>WI&ib&!)={jxP**qs{=l0b}x~FZA+l|f%-UW`Ezm-OITB48l+7=I|nRl}1eT>E6 zaZ~Phw3X>SM?IgF#qfJuIx7F8$Fi7Y1auuV*2U5Klb6QpjD&9^2^HhfYFM}fj;g+S z0psi>70W~q{>S|HvuA;!2;JWl{(DvsM#lVwuzm7EV0#o{`v+mME&6#e1fG@>frWOI zeqI#9@q4Axr;8%8#OoEB93z_8l8<^vcsgFvd5(G`Js;DrAk(HK{hAMfa3YrBY1{Yh zan8xj4Jd+%y}hFfZ(_#|^S7c=5bMLcRh;HP~LAq7!v&4&3Mnw?gdGPn;c4m zxsBXmJK>wxd%mb#oMecFBVF(5t;Baeqr(&NNr0ji8#z)tcr&vdyE>`N)Hs!fbuC9v z80i*V?mnz{7|{$rAr7z+2i!u$zlU}&VHa6FhByF!^R}*T`FzG_#@~~>va%w1VEPx9 ztRea@Q0b3?F!WC+`menZ^dCd?-w~GnacFJA1hTkf4Z7EFYDtYEBK2@Z9VGIjY+4FX z(V)90UAp2>r-t$k-QP*j+=Ohs>DU6pTC5=Op#Kp3yT z5ExG&jBgK%@pxbyx;UXSE4O$J1`WXax3ySbMut5}I*#NRswm`xZ=l_$p#2n~{Uym8 z`I6qNf63TSDB6cRud4i9?=(^?^G;A&7mIdj^G3ILJQ4i3;D-Lm=7J>Yq;!SeH;GO8++^P*?aZ-e=j9PJ+EUfG<~zj^J(ShMn~fFhKESFBG3WB zHAi3oJ5%3Y-#+~f60R+ud#7%1tv_Aarkj3}3UKoT+>E{uvKeh#m*!xQQJ{=h-|{)N z#R}>IQ>Yovp&dzMa{L~s?`H;J zL*|SyaVBEKK;K6#?^mdaaTGIR?X1j;t$_NRU3ZlNJ*onIi5_4I>vFCyvGXv}B${gQ z`~|N8cNs7MP=zj~3h?T&DnJwUyq{fncR%bF5TF8^lnOu= zBJL9Am&Pfc-V-T1>qd(zF#H!3u3ksdMfl%rbRGu&D8m0QFF5|W`xF7ZfB^8z3j7$8 zarjS6sr!Ba`+|Q8${Y;->jnPlJPiC_Qwvbx2LyoMp}^1D0O4QGN-{NGbz*j15w8Wq ze_=@pvwx)u_~|?h{QnIPp=b;Q4eIiqQkMZ;ghpnH&aR6Lb`j#)z#r2e>5Z(x|3&Bz ztRRe4;J@K9Z0*P&M(*1Lf75vwU+LF`0m0G)08sF82oxys85{+O$+$w89|$Qx0ZIly z0qzT+pj45s!=)HosXY&|*d$@^6Z#u338TM_B`(-`p}FAEi^=(f==xk|p#%2eAY-vX z9UyTCfuyGuBq19d1}lvp=KC*I{Hd(LV@6xutX(luTQm$+HLo#+5VT2VG@{w#rPtVG0y6 z_b-He!)fXHEiaRax>XmPx@^RkmSY0|N$bdJ-7N^tig4bp)c#79;9cYi*}2{FMPI|g*+oQ2p}e1*QHyC2%?&&2rZZ}he9eEb zw1o98S91Bv&exs41r|{aEFo&})gn+P1V^A~!(AIhTV&9odPkJ%ty38l`Ui_TYdFH< z&Jf>vjnGH}B@<}i-6RZW<-N8ZORr>cL=yk@4?v+PRTl3<#MXqMymPl|=D(GEE19%o zzLnMJyhc@HY>7z#gj6Y!VoxFgU~ue7s@hUWpJlf)3HSutl8OOGeu}N5Jroizybk(jQeZzS95srg)p7 zZu7;qx&El~VJyUoI9ub}iq?9ynzMb(g;<4z>S|G*AX%6eFdirW${NCU5wJb0 zdK7oE08adIkgp|Phq};@*JmiCV7C&#bNrLUJkI%@7lh&WHAIoyLQo{0JX}wGNe|bf zgW`7%AS$2+bUdIErTc^>UJ2v@_dDWj21|Tt+~x_OK?Mx*!e2EI2^!10{UUOTmh)j$ z2#%fFeYgQ5@jia-K@33|MyG?G9k;9I5{bB?l4qfw{hQZ~|H%eSy> zPPD=k^z&9UfT|3icT5mle_Khj6%s&(wyTLWX|!8R^tqSlgPy=(33%Bn zjXpm?9PI4HcbI%4w*fVWmwEq-8>gj&kxv8mzh6y0eIvO4h45GX8bMUJO?1W#R8(W- z|KD^_rInz=v=r%@!AL8vzjAsIfffsS#RwEeUX_x(y7_|3t1J7(Lb7~jeVZ|CV2i30fUOD#^mdSXwr1z%xpZ`Q~P@}>%^h#Hji%UK(rMdT?~71S2-Ea z$D;$@rc|3VANE8)`UVpS!hX!o!_e=)fdM{TXV3sr)tIcJARwBV**JiLrVcqfzA=@d z0KbHSe-3~GvQLzj6tdXcom?K$X_(p<5dCinLI1CDbkCg&1RRiYgTmNFYF9;rdwF?W z%<)Z=kpZsRSnr5#IO_UX*JP}Bc2iJAd2h3ac@^w2Y|KMyoHv4LcFheiPzDV$b%8Nv zV7zmrlQivg(&U!V?k?(??t_ZAgij}7z&%dA(O{>OF#cl*rv^Bc%MW%Qh5`e|^L;f6 zgcBY=Q(b1;b12bc?Pz)(0He`WCKwnhL3k} z7RHbA9%V)NM~K$&)n)>x1nb&bTbD*r&`iQA7egOF48;FJp-zjMCE?>`hb$jUH2ir5 zbJ=M6<>hsb#kSNs$2i3^hk_(3(0d=m*vET0cFbcJQ(HcsTLy?C-kHo5*WU3E8c{Q! z`a|QSOOPRh{ChFA6*FF@_T`A;GlC-iM7d;yEkRh#C{#slTOBF5-Se*wT1IMT;|HEz zwAa%+yDg^^V;`oR3vm3Av*h$ny#MsmWe9&_@8@rSjtTyzjJU?~e~F=Xw{5N|&3=O# z%G=d#>8W&H#HK1G1x9ln1<1m|3S$Gc>&QZ3W6{6ZTPw>ymMGw+gO;gdHWk}czX20E zB|9>Ibl7m~9JBqh6XiY%%Z`0`ISM?j-B^w|_TgJ_42@g$Tw#C~D+`nUc z+;)@goeypAoVDG8@k%e##VmN8U2p!oj3cAY>FY{+sHFQl|}_gm7b$ClH+P4`4o-hQ;GW4S1|jECh)3_M6px`8p$S%dAyfn zhZ_^X_DUlmT&j(v7(A^ul5WvR=;$Ym!p?aK3YB(}&@qX(lL?x3(uH=? zg?92C+$h>f7qycvO*^58HE#{$Xw;(RCBNnDM%Lmk-bT7#uF0W}Poh|O|3?Z!+9W(Bb`VgF zfhXslzlCTZWWQX8Ni5u8vyj^ZctIF@z}Mun6#hF70_yaz!tsiWl9HSLi5L%QkY*f@ z!TP8@pSTwqRn(6agsI;(q%%GoLI!-b5t~v!1_EmF zpi;l-LNml7C`tt*d)_x-P1oZRDs~3d#pz)>Lv0V_prU6q6&2(sd8Z6dpXTz8PN$vU zUND^Mdg0?Ah5t?rPSwnCWXhFd|47ka7@gWMJk3@sBH(Ak(;unu+yB?_)8O=7g;M?D zKT@|m06)fOY(z*J*-Wk{ zLDX7x^AAF?1Zbe!ACyWj6qROU@&8VC1cIPIWexyC{Eb4EAK}-Wzv*=K`P=6c#2phu zaK~30Jq>mSARo#SoT$NK1)V=udB_)-k1sEWl74_xcA5-$x#xY`+;`{Mt*pmoc@jF< z6pTYG4-eA^)r1L+q@#03MmN7s?mTC&-{})`@bPu6-?|o-6inr3ldLeCs$qY_=ah!Q z`_q47*jqD&dd)jX#iZ;@G_W#k;lo~5k!J@t>?L~(-Om)rdAvQd^DyoCXGF2MuYqF0 z7TELWPhfxoXDtfJ_NXN5){+b=;{j42DT~5XBH0)7>?TH+5&19KSB4|r2&7YB#N&o_ zK|E+|erKQGdB*ST4n@BN@Bi86w#>7?a1Q-`@@t|W9E5s4I(~@gw*~ZDR?R{Yc(txS z|G=1d1%INwG4lOfZExZ9{{iRbd^P*|gdm9(WHL_|dOqq#dVab>F*f6dGF}jU228JD z!XsL9kS1q^n%5=4d;E5CS@cV?Fcrvcn@t#=2ZT3k=X6r01rE<@a|5-8jUigYSHoxMJf3BM2l%*7LE(*p={0UtquuB^LjfBhkVd#vvwe;8da}rd zHlDDAiGupJs|Z!oAXY|HBkBqF;xAG1Rj{v~CZ2@W)6Y|V9eJv;bj__Q8u@eBGx82N(bkqtWg1;^+BnJuYu#FmE?oGuVJ4VZKt8l0Yw9hEer3Ep=;CL>q? zvy%zEnEs=$nFaI)aiWemk-_lyekdgUzRZz}z+FOM3fJ#>K^Xo1Ysx+a<&b4b08Gv@ zmTuzP3ep1Ur^s5=izE{kmRaHfO`S-;5_5M&z5|?vsma%*UnNi;3C-NKAcuLeP_Y0V z_(IKp@IO$o2m&R#oXdNZF#YOxTt3lhnCvNe)S5Cvw5G2#*5hmY5e6*?uTB#Zp1=Xh zmML6OAes_srB}f&lL4z6k_jUXY-OeA{SA|G@MwiSsU6Qqq(NcA-TRnuccA6-W>0kY zgD~~MZ^EYjeS%wSzh(azG1-{tD!SF9G~v8qKPKcIznpw3m!oZM4lo?aAA*RaqLMbPw7fWxx?;ds^%S1lN$LPOF+S$`o4 zwRf`@D|(y7y{r^JCLeN6p3r4<%W-L*WVobT0=K2 zJ16O!pUg>i80SoN#?F}<`vY33Uhc#V-uM~a-Z;b2DziKGwOYdw*Zz8x&Pmy1ob%1i z?OVGMaJ|2$0c$4irv;WcDKp!D1QYQ}u|&o|>n)+b2VRjM1ssP3HJ*)NXG7(=!BCW~ z^ub7qe0$1DpF~tT9U4{Xe*Q=Fy?@newt6X}FP*F&B7G0)6#7!^YseP!=nUj)74cIT z^zsR@?0}{{-~c9WM8RQn>~PxeFIiYvl8ZsW4zZj`4xqxyS@#zd=i12~FYOo$TE`(~ ziC3B`t0dXBwc8odSk&d6gdHC*w;c7x$G(0jq6plQ*-p@{#I=^A_cHSc zTP&5o-#HFme+1OpPjK9K}VcW7XQmS-L zx4AYNC1)~z^pZ1)tzLRbciON@hp9Ot4b|{QHbPsLH!*&l4$qu`*(L|&V&p2jV8-^bM| zOIId017Uug&3&(lR}WYCU+3%McOF{L?aKnlMBTAg2Ez-oM#R28-^4J5+BRBxTlU|L z2Bs`1dzc!wG~>8C6WJb@14jqGFWKCLtTTRTv&nWi&7{KuEkK0HP#%r@;;4wP*>WW< zV1!(!ShHmgmVsMhHL^wY-pJDJ9%(i1zS?ToeV0|g+Xm@|3^9Zg{#WU*ppW7YW0c^& zgbGPtKvp(e?gP}o!2{1m@>9nU+sHUo2IddgM%d`hVz-yrEgK7n{YflY&L<~1=h(XZ)WET{Yoyes0~RB(`pt0s zlJKiW8Z+D?{^%vNmD&r69k#?95;4g**HKWsCb6^xC5g5YJJ#nYODryNBo-DFKajUt zA`k|5Cw+rJkg$@W5t|8{IZIu$oGvSWr2k^>C(ZmM0n~&dnz+pcdAwi+L3Y9=abh)Q zC|F~)3KsD%&2C!Hmz!q%E6%?>|5B7g$X=LI*Uje}!^mU4iBJssf0yWmCD!>EgHR`blACrX0SGqpW z?jT%NvzcJ5wzR_}3@RmcLfK>Wy*51>g2~!%^*zq-gzv6tT{QI8}G7c+Rq1FMaBw_V4toc-2LKF$) zgzc|3Vm)gz;(;3(WUNM?lSF}T;yT#5%<3vPNzQ27pEjr2URyiQYqI^RZ@%rdzob@K z%%q*k@7cC|C{=PLjVWWM#v*gaukj*V>YHUFARM8zAp{3{n|Bk6oVTOV^R5)?5pK)lm2mllN@C}M zbE3;luG*AshWTET-ZIYEjiV|{Q|b}t2Zsz80Go3ZMSTajV{I-78I4k`IE@}}J>-?^ zU_8cvqA#NUybyr00TUbVv9ppPwn%4qTs_LYBZUg4M6X?dk2AE128+{7!s2jXF){}! zFiLV$2#F60B%&XJD!n$BRxkg-e%JfD+cS|Q`F5N-5ru*_eL(Hk*}#_&Kz)~r0{R$3 z!49FO$BCC6aDAY=BgB2uuHjP6H>^4=!K|w(46qu#h{wP4h1*nq6AQTwmEWK!2z@P} z6ZMl9$o?Tw&OBwQH~>(6jfxnPYqrrDOT&$E?#zUJ5Dyq!xMoKIyS zLcA@o9;#9>)b%|9O4u5R7NdRwFjOm{Mqp8@!f2{Of;%%2W2K}p)u8rH??NW&ApGNe zs8${7?szZSzdsGg>v6PbgMghBsz5aqRisq8ii#^105qc9MR&C>Vped&^fuGV;NS4%HZ`Ex`5gF*Pg`B3o#umye=^wT#~ z{7`lpy}%H@Kmb(3cP&X2t9&W8By3Z$kD%J4#RDyhYE9!?W)EQoEH=L7r$cRx zh>Huy%Y42KH}oh1OPrzJ80#uVR4$Q(<*mk~6(K6Ttn~%pE&STy<=qs6w-A&VB)~LY zvF8>8yK}gGoKC{{h94qt*6a}8tS=cY6e$fOt96!=J-LvqegA$VrU^v zIz^+iR8I?#gf+1lwW5U;Fs)KcDry;Ra&EA7Ataw4@|nXPIg*Zrvm2{B%oxkQq-);jb(A3ol5%CP^* zo(~Q0x@vWZpp+ZrPu&yofaGSG8stNh(NS02dp8Flf<7BVyIHiGi(L!X!s)a0ce~<2 zBY7wWd1`wX=R@J_2p)8N$wXX`7|nRc@ZLIqI;*JOw2Xu26NiTjG;WY_s&tS?C-k zm-~87Z1r!R1Woj?+hX>PL&;WuMbztrV{de2d5^_uT;#Wyp(bM_d<0u>=A9acL%iGx zyTO(|S|!*y+g09+*&F-l^WKPk#9y*c{%l6A>!|U|<#?Wb*GPIKAYSN5#(q)k)|c?StM7~0N1vyI zaNbQV$YzMnxO6+441i!VrV(cM9%KYsXQZC_57)ECcVJhyK;YZcIBesp6 zzr-1}eR($y7Nu>Ed-%BXw4vOWT5c{+z#Eef%RWQTooiFL@fCJb!-*x1OS}n79OEm? z$4So7%$@-JXSR>$3v0>^so8N(0G=`*YHY`E00zFaJ#O3RwE5fP(jGqUxORI+_qLe% zIEuzsS(&q&y=_w9ZGZlPtqLnQc%e~`gGSBkK$K22TTq)N51M*f2t8hWD|!BwzINDX zHbuQo&DA^7)wdeQC;`%62Nz0*jHyzUF;#BZ>UT_9dYgQRg?j(E=kv+~DceT#xbH(a zbsyU5cb-sHZ}1-}GeEQ>!c}Yb8eFyTNA1|bhc{%U;z#@N4fOBRq_!)uK=;j7L(Lv^ z=KIm99m&$4gvs(GI=bBltol>Ot;SRDX6a5fStCxh!gk1wzEf{mvQSE<-P9#FEs>IG zr}l;T3XkXE7F1Op(8wQtw4us_W}_kxrVP~oKU%@8Ov*47qo7re2TSv?B)XCSOZAMP zXdRC^*V<|Z5*`BN5bK5XA1aT69M)Plj)1V$My#XE$I7olCSVO>sS>#@z?)VZTNXrflC(-->~P1KU3 z+?Ip#BBR@K1m@C%%5V&>WJgTZLOcOGmB0gzHr^A2A6NOSlH($(=BtEFAht{A1uc>t@1W9~ zCZWO=3G!hMbAzj{UOv0!>;lk!^KU_Ho%h#7z-9jBaj~+qo2z4)G@{Kz)l3_8^$ba-1H4&Dz(1LqIsmYX#yq zN60X|zy>WZ?@g{ZoB@joow2dJ36f_zIwqrh7;gB(Jq_xW`mO%*;f+O2jYah>pW{Yv zj5vXxs|j*na=^;dc^dD7W`ysYH*j~i;CmL$K4+YP7Ii6R*r>SHNxXV=Fu26uh zhd7a0W^;B2jd(ct3CbNW;10EiAQc5_BCHusGn|Xh8y%NvgFpRcCV!dHKO+$N*?ft2 z_VXr3yllYioB2jey0OXg;kjIB@+NY}t?Qt#IUz}XQZe6+^ISqf0KCHiETZdK0R*G# znJckz)J5oWF2!~YwprM2!d7UFY_nSuP08^vKI6+Sh-*f+(a$opou%Q1B^xnhlyB(0#sg-rK`CU237|s{{%eHJFUi= zeO6c*Rhp~x3yfa{KAs#}Ow9*_px;E5eyV1n5)xxrVR_}>XXH3FWODe>CY_uf7#$Ms zy^(&4$&bibiz)Ussk@T6S?BcPv~o5=a_U?k>VhbzILh)>>b28ruu7w#-16Qlmz%tE z80E|X%6YFsiO!j{wKjGanIbWxc^taT_`n@Bn5f*^h!GA{@(5T#-DB>(dnGd~fL^Jf z(NfTABj{ERx_ui8>ssMnI>~~*+ zWJ(L79?CZWy#zJC45>ylQVn+<@ds$Z+8HP?S`YxHsl`CP6$mc{0h}PfLm_ddwHi#USYzFeilLmHKhA+W$Y6y)NOg3TTg*HtOc#K zO_mnf=1OVKR1kb?V}+roalY&9l+6*Z5a%pgn?m{uyA=aY93L`{1B7uDSHrBx9Y%;P zydc6EjhQRZal6o#ajwHT4Z1tpa31@|I%fKbK#ae?pq?U&-1YME&e%WP5oI_I5b-Jb z&8qlgRq?l1#XlbVI+dZ&a6qo#e+HF2{c}2X7)VhmH^YK3LM}g@Oh>Vg(j0Av z*I9H$PqOngnzBW1+1glclv@y+#8uLWS4cBeBA3crp@POX7PV3s)+a!%;WIDvK6XkW zP03JEov+-}&NgpEA$ZZA+bqVRViG?DX*psMSq}q!d5)^L5iW@gwEz z)5&n6sq|;}fZk2XmiXibglvpq93d2G#t}`NBTfq?OxiU`s@Vu1;i5D!8jk|im?3vblya)Qr zHl<<4x$62{UV~ll)%JZtgPEkgm!b~)1?5SzbkeTLQd=TK>@;jvYed`q&`S!So!TLK zw?YIz4uU=n9fi*vn_PB7;^eYK_}JMZ8NtR8d`&}7=0JiM@>!FDuA$QNSA(GE4MU?R zd`t>G19nmsK2)F@-LSB2kl8tinyqeU8&R`4q6T+*_03Xqb~{m1Ezmb-cQR`FnDZZ0 zY&{s->y9ZS20Q*W?&M>P3iv9qibR?k& zB*AGu-Ek3i@`0_j=nf9_G{{F>??)lVTTVbXgpLTY6$u$^U`%O+5;9CEw7Ii;_xlW3 z4r@f?)JznRU?=%}%m-ESVKSuhYZQ7OxW>yUe!hQMX^66iLXtVXg!CpwN#lHkiR3fj>ef`$K9GI*Fa4`F)}+b^)ahV3}EQ`pYH$T|YsW!SFAb{maq4+f2D=ZOzh>(j*1kqG7Jj7c1& z{lqMeGV5Z+QBv0^epLD7kH+w$#8+P%&yS3+AHDdy*QGuE`_km+fBnX;g0#Qy`K$ky zOE(^PC$06-j>@BpUjF{`H+{F|^Id1Xn}2cp{KJor*z-d5_z$05IM(dk@`!W&(e#Xy z*>m5>PL-ej-d#I?h=u9yxbNU(r^NqgEFKu9i9#R=?FBLB)2~@oS}HV9I-NGe*7Ard z=?2z7S4yMOu+kI!K1FFs_uI?zlh)bSNF&oq)UrY@|mUyLo2I@jp-Jx9PU!5huVAqpyy?VP4nl$(pY8D>`LsL~{9E>L1k<>)t-=wH0 z?hL3n2yt(R(GDhJ^nl1rVd*5JUH&%cZGLB`-+9{aY!|vHV&t31g=KO_)2a@)8s&78 z`&JVoC@GT#g^tz?vl?o~L+o9L5EFE00m_j-Z&hjGM#Se3!B~V2J5L!R#o7izu`!52 zWb=mmn?Bg=gtTJBK!b*}R+SW$7UpdvMDhs@X^67ZTwoMH%%pBKC z7bm2N_YiXg-$nkB>h{1uuvuy{HK&=H(oHSI6^v&L7JlJ z>03=L9mwE7htVj*>3-_{mix#I+6yx%w0w*{WDH3%%|sa>V~7O%{?EM;db|Yu+M4te6z{`2%;T-uBu6BWaD+Bw`i~` z{immV#puzZSjC%z^<{%}Pl_IeiygMOfEGFeu~@WX?{vwCFvT+Lk@6qh!qyTr(nJ^( zp%=s+GxQZU8lF~AQkJ%=FfZ4hw5~uJt%`$Er{n(IRSzVsTNOe^geqGdN^Xo%MM;U% z0ilw#u5{xn$22LfKc`Bu{W&xgXG-Vc$a4e`o5+)vYhR;b?t>U!@`*fYxj>TU%3gF& z$`#;8b7c;Ejmj0^S92xHh%5Xv!7obywZtR1KvGp{k$dS1e+1;wTv!mPUI3{y7ha_c zFjebDrm?w2noDNPHx!=%VKo<4=l8p^S_PmG3W<1K@H38SB)SA_!5CN!Mibw`1#NZO zG*>X$UIW5L*sa9Nf{`Xce-|&q1?|f^>53whVDiws%`vSIEp5kmpkWk*5xW?uQ!iaR zM_>iNfm*7#=bS!CA_cgZnPIr+J}?66>FqBT2L@ zgr5x^QJdTHH*~ z@BdapRLagc@v%<&SUdX|BpW`nkA3D<_L*AN8y>8(?1Np|%wi*id^XD`nl1HBPG56& zYqRADI{<(UBn_LGG;C$k5R%a>A69%L44!HQ9%0hq@Wc-U&t3-4?-)FQ4H6izA;tp| zI1XrPw(M)l0Mf7y-d=W4FI(!}mTKAZH@BsRAhJA9AX$Dz5I@fV#o`~;>;UzvC5R6) zh>tLc-wJ|QOo{`{&?gYx>xm%8ep5`-Z6@k*3{5c&Q(r|%^L!JEc)vpg0@Q#MP@}H^ z)aWZ-t+MRRY(D^gTG=qXmLAD&XGO$fD}y^fAT>zOFrj8m^YO)obBmLkvj?nlm8DwH zJox>@Wk=Y>>GbjDY=#IJV-8ZrH+XIrf?eKnFErEK8K%k*kWwvE#j$WQqhlxOPKsNv zQ;vXCgI}ymj)17ZflrP=!^A-^u$0{ila(`uu$1k?p~E<%7QrtNo)kBQQR{V(mfq3K zG3GBb!_y`BEKc)zF&Ng+A|2lhrp02E43-w;bObFj>5(DQ!VroS_%7BXhU#%%dPuv9 zq?(b|*qX)GQ8nfGt+kHaJ=_|5vNlV1@;Kr^BC>RQMq1J!EYEo4lf15NkX+ZBSHxDy&HnWY|Cun{X2aFz@u9}@cK>>#|9Zij@WHp^ zT1!XE(T3r_Vt}-Uy1qYfoz*dvh^z~=GmLgaz@+`G0BH`ocm`4syksJ7=P;$=1`;K~ z72-EAp!f}g07?T>tLVBg(_sNh=F+qs3)`3*$ zLrSM1L@?&UaQax=yUsFh_3>H0{g|5By*i2XU5xZTM*3bxdX8j1^g}&pwg&6gTKNom zvT(OFTiTn3-v>pABeBkziJHqv#q41oVgvQ@A~-223DozOg=?X$9>} zD>yCpHG}9GBox61^vmVo^FnDMIS6F}a`1Ommgk}KjbU++(DA$r*?Yj4&@Q^P`q5!a z?YOB6vJP7go}Dx-jbx*h!deA%W;$Nh{x+=m#PEu)$WX&^!`WBFuMDb(k5qg3g&}+R z>zbn)CZcb9Kq8&>L;Qv>E7I?5 zpVh-U(O&i)U#J!de!kExQi6eZw^S1aQ8XH1Nmp2-YHonL0Ai=D3fqrh%&o@ub8NqX zJK->bRsIf<)dq2tXB~O+Cot~r#`XfXKVn1q$$#Uw2U-%Qm7E%urQefm9l0mhYB&WS zJ~S!)sYmd;%NliRFMfSi!$(ojoG!9PeKZBX*IV@;AxP#Uh{xxC3~g#Rw5fg2rrsiL zYMntRnHh_bSB4D=nA)neeG;}5-xWCT4AN+!QM5G{wKdFbhkD#t4sR{~w~+y>UK~P$ z#0aIcDMRdAjxt56p6^?Zl8RZ2(U+%{Zpq%~i8zf{ktRi*EQG~gw`GTH`JLPH1KG0A zZTXRGdDU(C33Y8hYI4>#XFuO;*})E~WlJ@6YBj8i5*7X(#>uS0sDFc~Fgpxi;l}b;G4jImyq1kcuOcZ~_V4i9R9?@p z@GIH!E2_#~R+Znes_fHr`Xt^ob%8d4`I^-IBV+-Q3v#9zaSL<`M}H@aX6RbW(@yX< z05>ye!cECaNu1n(dnn9NF(2a|AHPQ_iIY2V54lg3oFu@ms@gETzD2NPn^=qsR4Mw! z2(s&t<==3x{yQ+tM;P$GUA`&KyQq}HU6gOAhHb<#(JfayC-7T32fXD<$2GD6m3F;p zyh9PGChvsp+V2H@LN;`#nIB=}Hoa`XpzS8s_A)%P8dfrb@?sqa{-@6I9DcO;@FZdr0mR*s4Glwl!;8@NrwbkdWW^~|F0dJ?f& zJn@43lu?TD>#aOvBF)qUz|zhgm=s8hdGiXO@*@>|Tuk`5>rYagB&F^z)5}Ma-*+36 zlJ`45@qbVxs886E?f|;l^gvfm03Qg`!W#)6r#L=%K^S}tn8Wrf(O;<|2LS*lDOFU` z)-r*Z5%=L`+b!np2;i>Y-x_C=56H)kbsX#H{p>~ONIsqE1*eHwZgR5gV8!`dtX@|+ zLNWuFx$AQaSk6Msz?`z_D=GRA()>Q(C zjWlr=vq&^WlJr*v5nr13iT>n&#oRbFcr{*upB6khw0MQ&LHP4VQw$*cSRfcsiIU}C zC6KDG6`nRW)Qx@7X%-`9OnPc`n5}CA{gw;^1fP#wGXkEkI4-_@s)8kk$l&QS8*72cJ_}p60wP&%T}oO6BL}mgcTr4O={q zJVA zaNqT*EszJFS)ZYEwGXAJ9K@4$d>e)RF6r2lsV(c*D6y(a2X4kw5qQeG6kTX4>jRzo zW*Cld|U_#TR&j$HDSeR1G1oMEwgsV%{OFYGFV` zIu(^srAdey@X=yk0+B|Uh79nk+wj_))y|@#2Pqbn#EbzEd#tn&K??CyDBfl-LBgGJ zQ~=yVlwW^eZaonwRR zgFbvMqf1Wrb??_XW0Ln9jvcm8R4uac85-oL{TiTFziBw)zTM}}>~&%C6+%WYqN>Ta8r?S=-RVYt>W*{kw0bccT)EE1 zm9gfu9ba~R*o(lc8AmBvUh)o?Qw*iX)K4Aen=l146${H?wx{x2;>*H8)>;j~^$zLHGEPGo7Z(nOp}r}7nkjd2-x59W|r2<3(J1hR`vi z5jal$bVCV(MlyVe8j;^iZb6_I)pUxS?Q;X4*pE+*&?1pA=z3Gfk?75n-!;_JUCWH_ zi|97@NQynl@F5H(qu21J>usIe?sJ#+%Gtf{l|J`fz250^nvuUUcI&q&R{5;nNj{hf z^F@~c>eG2N1Cq_yQe?+E%CKi>i^PUJXl;|QC1Xp;G9Yh?zUB_dj#qGAhph>lH_LEx z0=8?hU61W1Yy%Q0GXQN9c`m}nl$z6BRVdI4H@${nBNy?2KHWxB;XQjSjDZ;vwE zYE0d~-nv7HzvvPNw;nmm&VbD zI^p^i*PnWZz9CKwxY;!)NqvtOmuC16FG!++nbh%T>|~tClABgnYNumEzERFfG6E=8 zkyISpjj11(iO>BUkEGu0QviF4-f(NL>vNq0H#y^Q;KYHWn8EGcEPvuUg=lhT%=0=- zX{Wk)*Wz@tikj4V$2bA3xPB|IO}(>SM*g5a!?Dzl*GCf=v91z4kFP|#9_q!?YPmS$ zuN=F`1;_;!V;{YeE)bVtxSySKFNU5oB}#VIb}_j8YV?{G9A{uFKo99g*$(_7qO}bH ze z%=K>*{+HZyZ2}V z=je9)Y4BN04PJ}S;-TWR;zGB0-m|O7EG}8ik?GPz5eM)oT0TV*!zZQmaAV~-bhayu z2o6qtcSA&~vunN5*P;HK-bbH@KbqnKTy|Va4=?PMm-u9l>%%^|FZryy+*fs%DfKhw zaB5}KNG<&wPoysQZ9p)bFLimBT|E2&imBw*UNlekx_Y|N*@Z`a;!#pC&3k_bT4b!?9nH1`n)c7>o)u{kwRX=O!O`=ZedEaqfn{fNO^YZKOoIE8dLuf zRJD(I)f~fReX7L=fp#+l8so4zslY5MJ%Y{K>rLOxO0N*5Q4DtPSTg9{VZ^tbKiG%B z0;GJ{M;*OTFQi>pN^LP{#Fv4^Zo=;^*iNJ28qkOn;O>H*>Ew-8aMfM$A8dR$5_rF>9romVQY6KV+8_f}G(0=**!IZ+*vpgDAv zKuXVHYBZwKUlw7FHEn;1^P%>a7*dCoM$;%5I9Nju(ScINPt=%?(X`zrpdz|g8>#(3 z5~1Jh1Vb5<{*Q_~j$tQTs4p@ZEJpm8d$7@TEuJhvb|jhQg+AiSYTTL(2S(7)F7=)y zbF6DCy#--c)T7;q9?hIw7cihIL$rtFx@3IDZ86I4Fz!yRFEgj&<_(c<#+$f)$mNT( z$GYeH+zWdT&u6-$HyJN9x@WWfA|smTW@wj4r*da6ri8{Ea4&+3+9z(NzV{82Y)s<) zTkNBWXyM2(b1)8_(%oD}B8PNMF&KC|dZ4GUfq?_T#i)ovUvN(leQ`ci`rbAOZoN#~ z+o%&1`*krIJ%}+i2#T~yqIc1BCY0D>y68*h_X3&g$GX~0_@7B!uI)<#9mu;p&o2wQ zrfkq-t%jNzXxQ`m;RUE+e@c7akXy(UMz#N-f}yr&i1n~7AU>4FsAfnawx=)CvS;0-K>qF7M@P)ybDB)?5|2s0a3(N|3v?NFC-0Kf7IpBtfv**@x?e9334?lq;>LGi=nXvY+; ztjp?IeeO`QgHsdrPK0YQTRcI5jF5-hwrO#fow zZ_uitkYKwznILJS5yRBl6IuYO`ige1d=7f7>clQo;y!5eB~6C6+D#Z02@_* zU!4F>VuhTbXamb3cVX3dSy(kPjkmf!U{c}?bbHmV@g8tat-rL_b*eA*T?(i&b&w=T z{nUQF{C4u2uFvD_lVxYGp-0|tI7BuKD?~uAds#18SYXUr(yJJy@ubXOXE-FMGxO4> zs)P}#?`&|&;~+W2U@sb`jAx0|UIUH{pCo@Ozm2byC6Yx1Av)NPGaMr^bbvmW>BAvR zPw0RF#iw++%;-*Gfv!FzTs0OnJGPO?-(HBdiF9v^%Y; z(OLe?P~IyaPA1=N7dqLpSY%N;St^SQ0C!F6%G zf`QRNRI>@9vN-6*G>O83GG`kAne9sziHdM_A z=H9S!)}*vdvif3DHcd2umjZKE))SWwGF_-d{xdw6Yq#ejp(_E+dI+Uxs1kKBkYg2( zAYgePK}ChRLj|9$A5omQL4$9cJ&FeN6m9b|6^Qzts#%+8~&VoF=+que7VxM2)EOul% z?9%0FIa&Gkk`0!PtMW=IohD)3F^&E?3+P{|ljcn2VZ^ zP&*FE2&GiOIw1hPf(2erX8~T%50!UdrWIi2ktlwU~8XXq|JqG^0cUynaF)Nmb4Ev71R=uLQ$<{1+tWDZLnU1LVZuJKv5 z`nD_J!n@WQ!_s`sLprouvubrUOOe;>KKSy)OzD~`YjoQ$apPV*1s`9{A?pa5F+qVB*4VZ$5Z@b#AetDfS*muBXGHr)2=!q&pp-SRV;TrZl1VA-_e;-E$_S;nN%Kq! z3YR(^i6yo~Xfq{z&8%ICFaZMgwkd%7Y6SbF(8+9^%*m>SH82Za$>mZl`ce9%K}vyh z*6)Xmmu5@p%2(JgL9f(6CoPr&e8_Jj<51Awt{4eltu^9nwGk5X3fJOs5SEyMrE`<} z?o@g-1i%}ia0upNof`F9!)SU(OxvZ_D8+4&SVP}X+!ochNVWJbVMPI*z?dz~p}W*S z)Q&U-_NSB5B;F!Lf$~G|oMMfo4-pL#$!Qt*&~&L5Um@th$nf}I%0UGusa5EY3;0CVhgz0}N~Q38iSL_#G0I9G~ZhlHy6$=awRVK+RV`r$g1y)~VP_?57a~ z`r>m|D@y`8C#L1B&!gTrhraq?4)1z-w~ML9#0yyaLNtCEE8=CxxlTpNhteIx(;XAi z9Z8fG>niU|Ma}mwPk@r|P0^ftFGrVxb6i5wX)zq2lbC=cUn$q=EG8Xp%7}M9qXgl! zSs{_{hDKYRMDpvF!os{YxrK>Ea3drZ6ek8l4p95io}j1kDIs({M=;}0cAh)L(J9vF z00`u38UltV1H+f77-obGiQ@7BQJj$Om_jH{fmaEr<12tNB%8h0(-|LK5jwwt9O4Kq zol#3C6N2s@5Y<0cQH?YrHLC`P>h(DRR5SjCcCO`LoUR`tb_3Zh2gWW|ctYD(lycZq zwJYyk4ooMgm<9xSjy%T9L9DE#uVjHuY~l+Rt2yLq#b~pae&g7v6H5)zc=Nkp9}Gc} zW1B{28!@zxl26XBb}9I?MR^j<2z!%S!>_KxP4 zgGhk{U-DtsVgJ_J4SU(Aj4q1_;UP$^ZVn8uy_E4%GZ3c*TUemdBQSpdDlE+eG6FQC zcA@;S_JKP#YTE~$54C*^#&$JRIzNd*4-cdr!OiF#;yMe2q*9Dt6zE55cLHsEOzpj< z=MdQ#kW~^U5WRdX_C>^CGncClcCdsythXZth8hAMueOS0V0bPttV$Nf@8~_W{EpL& zL*(~^gODaEyq^}ma%kN2YXymD1>@CL0JzR=0!M_Xxt-~9@reFs>JTCrEWJo%cO~RT zPf^^_poW7|C&CQe!=gbJZTlju{3t4O~~yh%`} zK~R!@;?SEQzeAl7i9U8MNc07f`GpW-U&Bn-YL626}J@8Sz_sI;1NP-J_tg0o44GYy7TV(AK?Et1gZ ze;+6~vzJf+S5Hk8P_TldfN-h)k-QM|B~*X1I3MbWhn58n7rk^5#r6W(F#*cV4SU`8HWo*nu)>bEBNH`Z@(&T_BA}i5Zzw(i=R>W} zB-JW8;Cj4|ULl#Sc)K&V@FsE@NipJVA%$6?f=F~m>uE^aMo5)s8Ga-^kc1lZzz=OS zd?6LHY(V`&Dr)Hhf)FUEn8jKs;qpL7zj7WnkNc}93;WtKCAw?!GbolQ?k56nF|2rj z@jv~=A-YvLPLm)H*?oqF+tPdLFK-}QTq3-QVsT06<8D30Ow6dI02FkU<5*N6PJ+xS zXDO0?tudb(Dcf;d1fGmbKC$f1cBr=q#>3<|??s5%z)f5JMSIxZ-em8Ci-tV3?48^~ zgBN}yUrGylT{;VH?f(W3djop`p3j#m$&{#SpX{0JI(84)btX%QfyHuBkiwVX_bP12 zDp-?&HuEU9ModJDCF#r-Sq9YoBry4ZSLMU=TE;afOd!Sz-K?PK$qQ>GFEl9aYlSX2 z1K8d%NVi2+@@XlQSr7k_!%xx`N_$61!`X$>>xH37cag?E&ZF;{EnKy;EB7ss_Kuh0 z`CDhGFTI~;Y3S|?yjV%)Cy`-(gfxsjFav4CBwd=ccN}tvF}S7&-r%%Jx)svicqI9v zOW(v5KzlzGr)x5pt<^EB&Uv-PP&V{Yusb4M*@C?LookjctN%^X;Edrs`x!=L+!HXG ztmPas8m93=Z8pRZMJ&A`+4lS8Omr4X10_F;z+4!o1Gf3R;?*n#nRpZrXmJ(*0hW1% z#6%74g#htU%3K1as|pH0#h?oUZZ3WoEx!fQX&6Z-nv=i;3RV$L%UV#7yXIzkKk!MC zV#j3=Ko@Juv+TL6$Q?#0+~C+KJV?@L5>xL258s(VG&1lqPFZ$eDP8CGo{cP5a9T$019_a@>WiF(R3+{A7THUjr3>q z@h7@chlnT4u3IYwyDOBCm@Nl0;o8PrK_x zjVR}1Dc8YxBp^c$btEXxT$_lhxVL8EDjk~KTQliUlG!ijIsZX<2#G7yV-roimf2Hk zh@QyziQYnag58x*A@GX9+q_m%?e{p&r}VO#YXRptuHB%$#&23F>eGIl0)gPR396Mz z-bzc|aOVv=Cg#5Z4YjnQ?j?UN-rW8Q3k$%Cy<)Z606p0~^XZ-+2Hmse;0l}*zE2E{ zZ@MKkzB#h9G4drWXpl*WxDB5RF2WK|D!PMEABYK8?6^(ksNcIY`v&vhc%uuP}IC&jj4IZI)1mw8oxWV^;bl zn1MduIv&|6;!iz*bKJkjh3zrxs69Wjjy_d`vR~l*57=I}j@jd}4&T#bo$%4cS^DP^ ztufEdvJU$w4aXMi_>Xe%yV^QIs=kLbfNOyx{Qv*uk0coh0R)7JO@n3PQ{PC~xvsTUbV}K`!d+CP6yQSl9w;Ne}@^Yv)Z_zZ@?j0fSfBQ5_T%=%g%imEu2XWTb=!|B;ti`BNEd zS1h4u91=^^Mk2L%Ej+jIFM|Tzh*y$-%$?H_$0@R2zZ>C8cYsuwt00_f89xTw5u1CGr;R2kv1cgPfi(ZOcC>1?NO}_NdXU`E()**JcKimOCtCF61xMDHGr@% zuNY%;92Bq0rJ|f1CoN`=QFYMj9BObS2aK4d`WIAV^!d!noNYQ}K(7ktO0PFT^oQtu zlYL9E?B94zD4xsGi!6l{Mu~y#yA*b)=ve5*F2;Mwsg(~eFb<$U5W@1iX-7xxRS;x| zX5lAPvT{o;{V)ZwosQ7gYOb;(8q&^`FwII|a}|cPOCYlD#74c|T1?}_G)#ow>DyfR ztwIRi6Zn0~8c|bCUY9AvKQ}SrAZSU*Mo7l16EPVkkA4dait#InnVc|9DU1;CC%~S> z@y4dZG5d=+AFBNY15Lm~9?JLtg{A%!)~>dq&|1x*Ac%f0g@yGcM}UT2fbdz333$Ra zjI0@y7*+{lZ4fE5FiBcXxNE?wl+gu1WJ9s8Hu7yDv)JmOK=Y(Z{LCl409Dr4E287_) zXIzSwjegKQ(EdfvsNB0LrgozVyMN#h{+SyhF2Wbi)o&s#m{3l}BVJdLFi-w(@T;#>z}aIPm|q#a)zs_&sF z4UCVVIp~1qVEO#{{*tPiriKcwa@D=1ixyG;ksi)RL>wc^Ktut)iT!Ps!PUk*gogxb zur%-k+$G^2qIHwn#eeDd^!;Y6{#x5(C*OzflMnyBZT^>CXLwQRpFWfJcJN*3E&p*9 zy2c<9T>WHy>Yz~U9{MvEe>w``(`QtBma%2#p*U4LOROaZe!<3oawFkPt_;in5A=`0 zaHy-N)yCQvoN7pL_resDuq`fcdHV>IahLP!QMouANaAhg?x z5!V=zY$qWuFrX}gkAfLuk@Zj*cw1`Y3Dcd`4q`MIz?QaBCPKf!+h(TVmk{GOMw!({ z8A5(L?zG7fNS@Y!fk(FsaKk&8%t^FIp~)pjIldN1)EY7c1N2E6d}uQ9=tJk$Kny5d zCd43!INkxXI4L78!ZTSUA%Hw0t2$U$Ny^7r{KI(`5r6Qmi&>~oXePI`F`ImP8EswRQ=SeCV^xn(b!@h6! z!gOW1_qDL^n@7}l{l&H?A5R6ps7gGwG~$LAvyr10Lnu5U;%j(jY4;5A3@WAueGqbx zc_-@9GZA0ruTqq~GYEBmH9JhfBtHW#*T>8Z@^AqMOsPL;E>kBH?PL2kEIGDxKK?51 z-DdkN=Wg(1b4P_QL#-)dF}_Hz*L>oWN3wgvuG|mS9>V$0wpYSej9YvM_Nwfgi0rvP z43CG?zaoEkm9184@AUna|^Bv4v^%RrL&JCSk=(Jx{D^Mxw89&k6c1= zOO>ukKxYea7U68dxeezooO^Kgz!OO-&ha>>;GBiC0OtcZ8*y&L`FWh}IDZ5$C1Y@+ zoWyHASZWwDItOgQwEs4(t$2v`-xtOHOG)kA`|lLmf4>xC|0PH}WZ!?=0bd-50EF+O zw)Y$R=T%g3?3q|Ai_>50`Hk<4z-6od`E$przy9mK@)gVX|H2Rjll+RI4D1aE1Tc1G zWF(4R<(LxF_&&hC6h(^xacxvmNkbse*aUE;jK+0-u(2^vr@@LMP*HVPmEuKSu~xN^ zO%arorHwUOpb#_(7hYUn6|ChXvDxP;X;PptuYTQJWmG|3aE*A+QfyQ8Ynv#%YG56l zkJ$wv*OCB41yoYV&y$iwf86vZnf`d_PYV4p<*fw-ndOHbpnNH~jUXkx7zklKWK-@V zBeM2erF0f^`w-7H*h%g4DBHK+&*tw;C+zJ`ufDp!-}k-FQwLh$EJev8u&*DmaqR`m zmG8i-ixNyqQhLF`7QE-sf#*qa%w+uEw;F8s=fObbx37MH5_}1WLB?Id39D}(keAf9 z{Q0mWU%6w(4v94Krra@0IV7#Ye1 z`a#P#@c}D_lZ$srA&HHQ;dGNS64Sn@vA%L{RaGNGhej-ublej&U#yC`5aW%BR5IZC zY&tgs6N^<5F#8tJlv_pYL>@98MllrtchiJ20L}LOeCHo=)na7hK?VLH888D5!(bXH z2uaX8()=ncBph9rfu(RYSPZuS4u29bRk&JxIM7%ZsLi?M#wxhgm{;Fei=~`HVM_jf zBp6L#nVKM1@+Rp+7H`rTAK<(2vqq4DhDYdki1eBZ9G%tfr21m@{keC{i{v>pmDqkfbOmFdzx!8@6Bpg@V#mQ+7{!nc#FYxysqD8( z5?ON}qPU76uo@ccS2k9x$5;CFMfF2Np}X7&)_ zj4`=$Ph3Xfq{Y`N>ohB&Jp}fq>FOf`iysjI>cty8h zBxsIgAgAcC05<`H&Lf2C>*>Tzd_DLfSQ-itIl=81(4Hyr+QS}QdH(VH8xn2LP)5Yo z9#Yt`4T)p0Lqhw9s4x!*@AopDsKjU}BO=^v$PdOJ633v2#8@BD&$q3Q=0y32Lm3Tg zeKbc72CGNLnNRW7M|0%*XbuDtT;Y>1Xnnvv3e6{0faWD`C`}OyaKNIlxq30ycXQ-= zXoipD#N>}d83AiOG!I-42Ag9*?IVW3SP!T$%^-6j58(90G7-h2Glv zhJYS3j~4iwHg-o3VWN~s)Y|Ur=3GiQ_r{h;?&A{^Xgf5vYW6Hnac=8^7zprD5D9^q z0!+$_g~DkK6*bUuYh#s}`Jn-^tL z9=>mE&*hbr`2=N%zAmriVx$n+{!Q8rq~j`K{2ja@oY9Z^N|%hfYYScXA2yV}f5Y2d z|5&ODJD!;cI^WwrmTJ*ImcDDrGldQ}j~*aG_cOqQ;Kaa?Sj&7zcZ)5bd^Mox8j-bs zJEtAp%VnCitDz**m5CGlHHz~NL8r587SaVc??JkR*w-0`90oPA4zde$l{lcYLPUu} z(uytU1wvGC4x~6}eFMD>)G>hN{Z1qkUElYab1FW*HHEz6;Zrq@K>eas4A#)h5-VQR zfZEkwOw|U&5}a%)RR;f*ZTG^Hz_U|}c+AlCkd%6KwPntXJ2X#dzbllhK(<9eT9Vb? zLI}BpDoFMBxQ`98@Yvh2zVtf@Z-ArwKcU>CcY(-iCT6_-oSHBOTiq|b72m795YRu4CzD*Vo?Uu!z$g# zceP^b1y6Yfe*o6z z{2#bPFayaNH0Ax^B!SL?4|1qJ%*Ir11pjU;uD<{!m9OLXTTyr|eTEL2-{?UE_T~l8 z`=LxMQHR=ir&=<$KklyHh(Ia z`SUzm?ch}R3glyUhMoPYu5MH2WND}7q-gKk(jKH;n>&MlFu-A1o|sf+t;zW8mT%w# zmWaQs=W9qqei-#a0MFTqZ!_(t`c2{abFK_t-LHmIA)0$0S+qXr>sRuZeoKX~3{F9T z%Q*W6%{AxFU=j%!6+H17+Y?!uQNQQ)Wax49C&M}^wNz}gW#P2dN~u*IRnSIIL#ZxX zmSSrpg0%Zn;(fNwn|Z1%wBxHy2S|Lto?(R{6c9ublzLijdmxzJ@~Gp=V5**a&~ar* zafVZM&$bkO;?}f&rQc~Y#uCO{xg2*ZcuR}FBEtP>RNCvVh>l+>= z=SCEi1gnSj;-X7fce1eLf@>hp$`Y)V-AsE$;54+ZHUaa(S^Bw zEc$`Jl`w~9D5GUtKY~SL4i>X$;x@)MSmt~a3>s^`CC;IN8{zX|)K8pa{YVy#p^ZS` zJ<=8`3J8p|7L9F0toB5$pTs#fLm3g<`jIRfb4aj$>>Q7%*4T!`)*8$&WBo`5j zq4IQMJgA|JkZt`KEF5!)z`{v%h@UoLuBZ~+s9B}l9{gS9{Vy+2Xg^`ye*3_oq!yO0T9SZbrJ>O@bK5yOT+!T;h4eN!;6&jZ13;;NGlK1JWDuc405#>bf5j0B)B%R^wa; zJo|@GpZTL7E;D%*5O*|+=SKWn7Vm=@?IHdxC7Kc(`LX86$K~BTVUye&3|smX)u?@f z96=(i?6X|T_`J5Ah3hN1O`^U?BwAlz3&RYp+y-oQGU1nn;}_ z8rO7B?+f+!Yb(N;@`hk6Ez~^XB0T>TKQJ!%W7O?~wjcctPoKMDE2JA>t{av}VR$pF zs76MNutzG7Dm$iwRs;Y;Xu6JEK=1juhO#H-uu3c>_|kI19j*#>uq3F0CB=tmygvuD z)oU6^f8!M)u?IT@8Rzj1^c~Xi{I3`~o&?Ph_!(4N`Mly{73U4Yw8ou`?DKh3x=~37 zLkRkia1@&4tb;Fz44B>;Q^=g_4Fl}3b9|0(J&ibn)x?wy5?uNJ-I^YWR^=spB zBX{m3ZDju=llmXYG{(DZ8GO}*4lDZgdYMaq)T2M*)hp8J>lGPK?YL3tT0piOi|J1Z z>@&I^q^oK&?SQW%N5`keIn<7|boE8JKALaWcddoa04Zay{>2W3t+bJ~Tniu;%7>yD=>yW{M=G(4 zV4}o|sLGh7fQ5zijm5C^tqt7w&}#TVRni#dNTu14`Cuk%#^ZDC`zZWNRlIt@`LBwAXg9?U~5KH|gKLQ!xgeAkA30=~*pl7SzV3_H`g;WBvTq}PrD z1JU#f={cxmr%z>;pM6 zM0hG$bOq0Z)0dhO3u>!u#cvO~v73`+7n{vud^a7~ZjP&OPfqA;MWY(}LssbQ+{U!f z*-x!?w>;*!UAuhsO#;DTyejBh{eUg0!E;q>L1xaW)i;{CY)7HxlBLipm~>&RdubXJ zcYliw4$`R`wenS9rlCG3&FO(g+|4Zx=kueW6|F~`tw#|}m)=bJXy%)jTDLX9V#X)N z0hye-Y68lM{TK!r_{L~UAD2S?O~Kkhxd}91S6#tXf@l06^ZUH8EukCG6aw~2m>?i+ zhj9y%U->Q%9;0`?fn`IJ9Hc-$;(~zq>n4i~;S_U%_%4-|_#!>hjz@&8%1}DJ zo{}Kjdx(?s@dW&T9LAkgMGB(f3`{;&R^7UV+^qP%$3NoPveqqcA`e*bHl44E#5c+g zZRtWjfHd^aTDNrL`p_0a9Z(B=oMr$osM1_3TK$``O7jbNtER0Xt7rfFHctpL7D@vrn|+ zd1KNnHT0YF0Cj>ZvM;X-Z2LO3jK zyg9sLb-yk;jo(dL`}TCiHJ0Tq5gFn^eakacY13Rv?d2#lbk#p zO+f@-LI{`~_@U2*>VB<%6mYXtjFqS3|3HoZ09@?Di%Q1{|LBfWNT2bK*{%A=NZWL3 zpCC$aoHw^bxv^kbfx=h$_bo0iD#%xEsuX;41$=WsqcT4)QXc?YF}9}qrxW9~zypA! z%`Kcidap0CaDG#WJH9xe6$ljp5&`%t8fz*ZBGlj9K&33u*kG~$mfu^#COC%R&s5}B z$akiwKlMfXHzeUh2)}8po+sB7b2@z1D#r2+uN#D@X7wE=WYj4d#yIf`nr{{$2;T_k z-14|Xuo2X@LWgwNv`|ao(Z|Ga=A5z*K2c*=lcIv7V+^FbSs*P-uv{zgy9OxwHZ0RG z!iwW-5m8~8zrX`#;ch{03pO7)#&(di&VQAp@$DKLc|~>VH65%Qz3I z0jW045OkcOLnOwoK?-f5EuoScP+c?7^U8+_&uBNC-_no*dkK2NW9C$>Pnq+XjY(}q z$H1^TymeeY7y_FS*?Z0%!Qc4LL+h`QTQma7FD=dKm(qXNfG@my`2p4N5Mof`=f^a+ zIS!nWyP0x5_!C}dWNo1=@TZkdq-r-%hLvtODSvMY?MTb#GDsFOc!!TR^|ASeJ!h*k*Q_q3uG}Z6Y2yA?3gd z#uRn0!J}nD0e_zhhJft*RQl`-P8J|I3uV9+*^Un3iX3FR8eDtO3KOvJa*W{qV7djc zF}z@EqYBhea^9N3SI9GbtHQ;}JHQa-qq6;F@(J=5dk=8Xt3wBSLw|5K-ibfj?exbP zPUb3vrx_L$;VWse^Xp+<^d(xETVB^vmiVEK2we{se$fH!*kVVS(v2e8*zRg=YGHE_@NR9r1y^9Zy<{EFOl~rNa>xx$Y7*&0>(+t`u)kz zmiwLLW9>u}87nj z4o$Uz0Pjv99(E;hDp74QavEvabi}jn@F+>e^ra{WAcThH{8_49JDhMB)bQS8YMZM? z{1RP47&a`;VP$Mxl=_sFJiIzSX0ZJ`_N9+DU%nkgyqRW!zy4iVV=ElkHNhHGS+ z7eLB)5OEK!xYR9gOOk&*C@EHIYmyr#(ObM4${1ma!nqcs8fW*=EYc6{E?;5Mx~)5? zmaX3*wJIWS`tVCEY=cTP1rQnf5rd-NFBt~p<*6$jnDSWcoaEbZI<9X4S~VZL=^9|u zYyE21W^nYMM*iOet@~tG=l+3zbAQspayZ`5{c?O#Mue zY`8$|>;IUx;uiL$IBCAb!oD6;n2Sc7GSaS#W`@ONe~ptovBji}+F)?Snj+a^#=Ns* z-6NO_PfRDlVcMEWJgg{IJe!CcO4@cFm0XW(RyZHM*#13`fs#8VsNuYzoFPQX5mtVc zRElyvMZGQ(`eJXZ_bHmsLQ%@vrHQUDg>tZlULI_UV9pe;#yna@&+eob zin)153ohYdmL{UIX&_cf)0=^v)+@TWx})+QI22=|E{Boq1c+GF_5d0V*TaphyS zi`b(Z+`1?CC&536l=iQnE?qn5tKx&GVKRR-_$_@7=M%vxmW+)`NX9md_bcKCS2%nB zLQ+rD_v7!TPJ+$GH5C+Z$9j!bmcG9CH%?;Zo?w99cl72DnQ*wS*LkhTD6_#8i8iu6jP zA3=I8(k)2;6Sl!`fTA6M5G%m#&`dfdLhSelN|WlCT`7#3BM+jdh|Nm|s)qfDOs{-8 zF^br2Lj3p?@i=7+maBB zHhNH`FO(kKX=3-DZIC1Aq_4P3#f+!rE62(9yLV(BvhE_}- zM1d@(Ldj?an)&4#aUrO)Md(iPTCPetWFwV;!={~iB})#k)RMqT z&?H=VBr;iJ8RRUX;3S9=8Bk%Sy_N(~s-fLnNtjhcPBTFpqLb;>CRsg+G9^8YxDn*~ z^Ez9(nkMPhgD`KD6WYsSK78AjC2f5&v9lRU0H!U_c4W5iCNe3fbN_Zafu2ieLyNsR zuWxxZ=-#xC_;AEJK0|-{h`ZM50^>Mb3YM_0z|C8dz6=`8dL~~scoD|B!KLpHPleiV za8l0O+m<t)Xq{6DzTS^8(FG@6Oot)- z^TwSNJd4Q_NHWeGRDkTC(es=V3lL<2tSgiU3ezD{*hPK8i$^caD$)xl82}UauM^j0 zhmx{Th+swQtf}~m7^>_EfFI*OyJ!r>6%C%a@is6N=7ulSlMl`RybCOVekfhP0mswb zhj5Q5A@U^hd+MZkzgR!sdPntnN7Uqko63<`mAe*fLaqDm+*_kB`9hXi!yffV6v(KjnBc zwv_F-{txiHe~WGBeWd$v;+bdDz~{aaI?vdK;F;P`I40w8njbjj-r{a2yfA8SVR^Y& zZ@i&k)<7RrW+W<4{nr>fitvwO(GU+PaX>8~qiJ>okvTz03!IUY*9b5M7_;iGI#jf- zG63AtVBJOVR-|asYzEVJK+r-Ns4y})jQ zSIBn;GsS!xSe)cge$=3-e`zLWSQ%^o+^n!^-qn~@w}AV0E0C8vK}R3}JA$CNy4K)# zJ!px)#ti!#Tq9hSp*>;E5Q}0U{Gztzp*0mXmVXwRPShuaH^yv;;<$?_I`eC53&25p zw5YxYUJr1ACs>x1>ZUYQ=uN^jK9yJOcJ~A;@bF)Id`^ z9`UD1cf3?z`@#O^$8H);R|6$9Vt!YXEf3Gq$*wcy1q1K`CiiNcGrzYKWs z*`dM<=FySH<1he@i5PMY!9;-4033+cLnG6^+yocLVt@;vT-Qf|49Pw#g7>7WC<|+0G#tyB0R@Tn{00zJ@XLaITQXrR0JX#Z@An}UKk+_iLwyU z7!cXeYLP`IMN=I-9I>blXopK;{;-8c5Hmgkfg^ECOwXr zq{k6`Hs8sHgYUz7!C{oAdxwcE$)Hf=Z>}EA?<`~GSM3uBZ}z(kaHWLB%9};>v{OA) z1n! zbI(^&cekoU{2YxYeh?H@;6JGyHQ+LR5wX(#7TS7yfCv4=KccG}zbE}8l=e9$RY7&d zk({L{XF%$30)LM3HFjlrK!(j%L>4JK#z>+GF{y-)Aoezj7)=-!Dq$yShKq1=5#a=b zrpryjX}dy%rlMF=DKb`8852CCqv|sUaiQ!7(J6G&;Xr66>un;B{thIqIBwJk88-^} z3n-$Y5HKk);7S8xh4@W~*M%+~M#>6w?`<5=iU>$m$zoELS~^Vzx1yHOVS@}JgZ>V{ zr@$X#?tuW0DWoyM>AD1=<0B?6g@9{lu`sDg#5d>cFuWvC!*Jf_h= zehYfEJ!m36N8#Tad=isC&kH^h(#(v2G&y>q8xjGCR?i1#02m66ipYw>M>lx~CdLMQ zJi9w4`^ocma@Qg<4V-BJfx#|*o*fi*j5#LLh*^Twh$%(0_MEE`C9xVY5ijCu^w4UA z_8}%c*6W2%dX8UIzowz0F(4U^05*tUB(oCbkUwtD`e+~37Q1h;GWgla;n3LZh{FvN zu3ZTc8+458nrgHfvf-D3e_MS+&0hcsljoZU)4r$Tj;p`ZbvXR)aeZEb8db$*yVd_-({Vt`z)qh_;TJKi}-PK zpR?{8GZa31eVCycP>Gp{8M=~`NTu&;o^y)e)v;q0rvOd1@sSK3`}o|F==eN8i1AsL z==ju;Sy&1Ot~<|AT?3#o#b6=F7%G!^dchp7Hwp8BqVWcgHD1)uF&V5g_)hjgAT)Zx zn-a@;)5LO)7z2HcUT{Q=mU^&APsX4dqXrj72CEh3KZ7VGWpE6B1Wp2bKUi_rL0$Yw zsEVI&fW^R@e~F$aeOs1KG&D#Lnlk5>1oxl{bF{CE-h*PqQ@2*=ngnLR;9{3gGzJ}Z zd{y?v$xL_=NZVY&-1;VzGT3QADcOOBb$Lr5M5(lK-t^6nPwBzMyeGR@dQXqX6U#6uzJp0Z;kIYt7n9Zs9N zrqb>KoJZ~+2F5rTZnEePdZXW2VMkG*zZ-hmD%U zoS4)-2;#=_9_$2no0Exmf^?ctgv|4V0{kd)=f2pqQftR zfavay>Hg#xenJIAH*g7PYq3ZqYBrGIWw0U}91tJmbF+kjbCkzE~ zPXglZ0pbogHnc#y=Mag2Xe8_<@-XJJ-0aNxd`qJ9`M&?3=JREk&l$!Vv*xoDP8vR2 z5ultl%MCKzW7Mq9e#@HIOvy_vlBk(&?q`_VaE;rM2_QJ@($vN*#iHetChU2neb&@A z=CkC^oAWs*(fJGsG*$~ykqhJQ*>?2gok)`RPJ`qP15@F0usb1p zXqNix3kE^`vQF?$`aHO3Fo_z-A)Bmpjlk+14LjB=zzw?{w#LQ&^sZ0))4GDBDzM0o z($I?tr}EH+JkCWdQ#pfEM(jvs$D~M3S*OZ6|FeMr&A<4%25w@RVe_46vdrR!mKTgQ z?3d>y<+0;|lt;0PNXm0S_964c&Ve8Lc+YnaZO>1`o<90f5PA)(y73@X1imyJn`&HIWT=!!1TV|dF`%{79x_)MiQ0m! zl}sihywV~!(_Dk)Q#qoOq3ph1WfXKF2UdC z1msb}4u2zrQx^O+MU~$+VK6IcZHNTI(gQR~aKl&e~4SN-4j%ipJO--6`_7{kyTz} zLEb-?GHk0FP9_~zJF#o>q)bRW!GOe(%B?g z>L6c1`6KmUdTW#0@ZHzf`dI1$NwDg@txZli??_ukQ=R#VWqQ85$hQZPs`PxDzHGiz zFLobvrJMYGasfzg949ECER#B}gL4iz?SQ1s)o~v*pDRpXS@dR_AEXm%m)~+a(eb!J zHRi{IQS-yHMw1eA7>rqS=AYt>Q7nHGCU1e&(pl}<)H1X<1Bz)DVQQVkQ(iaop?_ad zR}Y7Nh*VbjFzm*(`tl&$fM5)5a+U2@U=^H0m9`5V8Y!D;3O*zn4FyQy@d72X@RkY2 z{$!P4ecK>Mve)6~%kHTdJl)77k#4I7(k2hQM;e_f) zYd&1tn(`yTkmhgvlr`bf<#$XA6#9;xC6kd`z*ce@q$7R=;RxXUa(%3?zX?7~Yw)Lf z!B6SyhxzNMgZ=Ar{}kT2grc&^ix=(V0ExUuLpz!L9HNnyPALni4Ubu@_P)WWKbdmz z8Z;ExFQd*{>M!p8lJS-|rHx$pF}?+Sq06KA?fTBpk+%8gfsZigw-&eA0!HxlJn=%- zm9~mUYEDziiZcN{YUATZ7l=OKAoAp}8QS{U1?ey?G}UR#^wJD?HSEjXaHg5#f4ea` z;KVdJr?ZD*Ik6KniZMn{FLSEP)A1-=b{#6{ML|XXx4Xh)^n%{K$CB=U`IiW{@HZcR zRMuMBtM3i%?T6iASI(=sA2rWL)B=>yOHcatj8^yAOZLIhmwpg8eS5~J`}T-eoYmjY zpPT#9+E*ezdq&+)W|P0m4fX|ZF#3NqxNlxd#T=ich$yUd@rrRx#I$iu{CPvmov!<&(Ij1;v>8yoX)~alihIhAEYf~=5_6GdG*d|veg^%4 z48eh*R~JJc-jaYC`-xp1PcSKAdAy|$A0OYC7H97mlLz03h%v}Ow_#ndvZ0|8fbwbp zRnQdhNr>=hc~mRAB}9YC=`b|Z;qn|CH0$?y_0jsLoNc9NmHwtwnA+V1ilnpQ>q>~(QD_o&a&_qyS#_$ zmax3%&)=V7Itui_nvF((TGP?$QlZLW>r$~{4|A8&IGP99Lsi#RRU;yyz}Pv0tISE% z9;$v2b9PPwbJj-~Qo}=y50iNb8!K&x%Vft@5r|VYMN=%VuePssIa!;`$!eLRSiO5t zACo)J?fW8y;i3%&YuZ89c6W6H0U>_Ck+#}88Al#8JhGw0U zEpyvuW`?Ku_EG$A%N8QXeb`|hG-MS|9o-!NCs z%!IfPAoa`3=LfJ%f|bw`$p@cDqaZr5Fr>k=72>fEB78PbGYun_?I2VgrusMCVS1l# z*8=Fbzi6&SfmLN8GlCu+Q`~(Q@<7%ZzFNY!63g17fWkD@6g+%Q50{ zr*8w7Wgdb*E`cdjwSRP%2EC|_SoR&8VKnlTe+>LgXDID01{k3l*$+Dyp=*PE!ev0A z5);cfj@Vcz1Y$_@mF`c&SN#9Kwmg;$+zyL-T$m;UIOJbqG%oquEGr zcok~XFH|=xU04r7!3!feRIOa=B`FvB5`+1L&a?JY$sx4ur?(`!pMHF4KW$dXy~m~f z)Fyk4SoVN@U8^O*_-4;k|k$v zLP}$}wm+E9p1`M|PT}hnQ66C-f zbsN0P`0~2R6iKI2d$b{dppjZVD_DrYjTF|*a2vIz;^9C;g(ie|L8(HsUHJPSDA%Lt zT+-hZ9)c%4@f?JH+Rfc`kE8VD1)3^x12TfcKsVc6E@0t6j3}rv06f9~6T%NkpKp(X zm^_;|Ac^qDzRemgM0Tj}2H)lY=V$viKfo7v`ZgEi0*~WE5TE-t&!_V5>K`DB;6cxL zN|&bJt-h7}@4nDANcr}3hWhT@c!d!*d8)QJ)cG+*M*i#<@dQOq&gglKuRg6U3w5j7 zn4Wz|9#p@fe~{l_;OW_qRPO1Z>xFm1NvPX4WveRh{3GsgZSx?oKt$rcRFvw7E)}9u zkg10{5gsMo7urtg4-TqtgJ*Hz8#+qqkw7|3} zT7|wpx3?*ETT%bk^o6;-jie`loZR6d?^U&@?CAKDIFHh8wuQr)!rj?LLY@D$`#H{VMrI$Lqfi9ox9K zPxWM|;l&hgtS{(kxhE;BKRNtKde63WJ^A*cvm4TUd-mz$eR~?uhNsYH^UnJAypNz| z##`uO|~+9z^}Po+H^GYuMG2)1SZa(U0_GYACgo zd2Zyu27I@iPB7R=vGk6XTqQWM<&z!SsFqK@6TE(#-?901Eve<>j^JcOkDH*M4yThI z3RsI6G(`Ojy7TFgFlJrrM7(moEMRkm6~Xt!SfVnSfd5MAX~RCT$jGMQ(v-?G!&Go~Z6sAl%7&Rv#2s z()t%e7l>{*|4Kg;p0G{bjM!RJPy#n{gC0mF4nmQsz$2y=^)-bmqkv~h`!NLfa|t(> zrKAnBEv==eL(6XIN!7--^i0=gwe+aLWqNAv;`HD{sQd~&)wd@l^iir-!V#n}g;KYr z`1brVbUIaY!A0pED0CYYx>^4@<{L*Sf8)K-iH&>DsyVN2Ta@Ft>LV>vJUfbC=KJnt zi20YqSz9_EN2tj>9y}4}8#Cfm2*5*eYDsPRhr_92-zW=pz8X5_qiEe+4$TX79u6H# zrVO4=%);f>@_^>0uwlMEGkQpCtREi1kuQXnWud+$8?V)>LVX1rM`@3Rx*d%(Lfvz< zSv^H48tN|8W`(*v+U-4aIa#dDU#Q&^>UL?3p>DTU+H(W4_Ygm+N2e=d8}w|VE67@u zp0#uZKle({8oC-mSCw>?MOS5Xg>6UaxsR^kX-(-Vz?G=r45=F#>g?2ed!{2l=M?T> zS*Dz#FDTC7<=l`^U&VR=yz0k&luQqOJa_%r(8q-v(?z4v&~F30ApY{;p3S6Z$Lu}f zG9M4p<7q>F{1f8w{F#umg_}D-A9Ve#S6+%f~R^QNA z(X_HoGQ2T{yF5l#qVlq}CWRhfqWQp3WH5tgrCtTnZxZ4F7`p%9^`dnVdY!-s9y94a z%aWfMQ-W9a7^3bifGi}vI&?eYjLB64(WYc@N=v7sumTVf$MQX-(1?g*(A9OZVSsoh zDw>!fgSH$KciaFqvlWB)TWcFH$xyM6SHk{@=bGbnvAm!>JQ#LlZzZO zmIL`i#8&YA8`l{sG(i5Yz~E0b3z{QumB7#!m_u*5rX~=^L!bMBhPaDzz%ACPT_`$W z5ZxVF(6zpfyzO6douZu64AoK`M2FL1o6k~3&OV=W5`{mx7kxfg4%d91U{2GOfjVnC z3$-Re{TQl?avt+7OyE0h6Brx5-S4OYscg!!9{b#tj=2DTq{kol8+F0?@};RuGNQz$ zu6_PiR@Bx;?Vp^L==@z6fBv3NVtjs{@IaxiC3RgpT+`Z=Vj{>9r0C^=+Q6DXod(qg zDB%s1j2g7O5V??C7Cp%ZH|Sn?%>>Q|#FjnnO4|YxRNJ6)R6J0jpl2!X#emqC!OikC zKYY*)24esDqDWI8!&VP&fOLx^b|(z@_CNWWfWF84I7G(Tl=oI4jZh z@M&{Dh)+)?ru8oY?Erm#seis*kWW$I*ut@;CUv<9m}3~1kwKJUfFNt__#}0icFAU}pF z8u3ZVq%2A^Qf&C7&w=4=s0}uW0cL#;nKLuN5#D2tuokT!Y3d|is3PNVIp!aX`r|;Q z$#@Ep=Z`PEGiJOrbrGsyVopc{+tM+3F|%6tk&kh8XA$f zK@x(#*5sWux7o8ly)jD}s4P7|e-RNeQ=zixgSz4kP+PnWlG|dxucO{SrfV%+Tz>&B z-gf(;EVeF|#v(xpL+LqI900ra;!Kn!lE*mg+KbrQa8GD2UT3?WO@(*dG{A>vCaEhT zPE8W&YGAe1)~AzBP4Uw2Sd?`OjrvLUmRK}opWmePUK(( z)QY&l49Ip#urI5Q(wC)JjNe!d5Xj6$Q$H`Gv`qMOFs=RDr>VCZ+ui z=u1POuFAH*$(%&@x6hgTTgI^LZ^OC=SxD4phf4d#-ChO~!IMD*vu-uQMd!uR*o$y+ zF8iA|4^vfdn|-aO!8d0CV`x)dc2DZV?R!|Nv zuzxz-d9Jw>+?}+pfmT8h8Q@?jD>)e;<}W9>J0>5|JB{pMz(((gjH(2&VV4=-ed=JK zMLg7U01|2~^hXrNDc4pogLR0(pQ2GoGc4d}cwrcz$tCr;EJ+6YNs=Vg0C64Pv}oNd zbntd~$#9G^WhI7-pFFw+oX2r~v0yC~%|g-m5|tgarf7eZ8xY8S~u4H+_?95(i{6}dmCp!n6hYHK;g}WW6KGznN)`U2h>=R>JTgo7IFuAaR=>JOl#Onb*P5)$aw$UbHGf_10v2_oG08Nkm_#NOxam|6 zF9DYh-nHOH9=^$-Py17{$w;Rc{1nPR!*BL@`jWK;rVUYZQO6}~3wwuLvbGoswQC43R{I6jDaq z0=kaKZl=-*VZ2@}6tV9Bxiye(VDF}HAgL5(`XcjmOd^~$GZyPs;HbVx*6KyaPX)vF zLRqJlBMA$1#DlBqu#oa8z=*-y1V#*ee;B!i(Axoz0i4yLta{=xh>F?ll#Lz{^n6pz zXXJ8a`6Xr;G6D(G^F`)rMcYwViY1LWTpq=SOfHP03q1q|T14D3QDd=Mup~<4k}w>> zMsdpYG5S1rZg2CL>|Q@Pk0@Hg>jlco;c=7(&Qs*h{>2i%A(+e%O6DV!jcB;24a9y;XKU!_JuHs5t?>UejE)&4&mR6T-YY$NteV|Vlv&q zOHBKV@TA+zj=SLsRB}U1_qnHq_uO=Jmh_&RgiG?CdnUqr?mc)^J+u(!X@?3 z&>aoyAR1NoJF><2FON zSnVnXA7~l;k*@%6VNb%iB)TU_2tzNoj`-SO!2iG> zZqh0=LtTRR6OoZ91k5(~llZz|*>U!hSOyk`>aD?>6}2K?_&C~cio&9(rvw(24#<-(*)9tvEz?otzm5{y`IyJDS-awEsa=Sc6R-*b^ZnEXfaxYwDJ>*aCY5?c`F+jPF7J%5lhE~e=NdslQeJN58(Lt*@7D(lrfQz(c8OOOa zPKwX#FY6k+zbpV^mjJ|43&qJwC?y1t|9o1-$wb>=vq{iZ)`%|94Hw&0mYbAhgb)E^ zM8jk#$qYupLc$wkx-k%VsJ@~R8hy=51Z!p` z{4m112NRnS55|b1lb%pC~9he^9!~5hXZ8kYSs_nSxU5J%gtMjl2)8XMXtb`Cc>twmO7{LR@pPAHYPbQ zkzW4M_ffSrUbKn|i8jVBRM|qMrr~o}M>6f=wDYS}Ty%*|EhuJN=Y#5RU!vjx0y1(# zkK$iQf0N{Rfc!(S3B2JDfn`sz%P$yEo+3bSTsVVly0xvK-wZnf@3^6LUd7br9)aLY z{imquiX-@oZ4o8i)uGw29G5yst5czpTGagul%xv60V5oM#Ba|w#702bT-(mQb8Rra2M-KQ}qRquFYGbFC{se=ovB$S>RL`pmWevrOdIw zt-Gm{gSl-5?-m(_Jhv}@SG#_jJqIsSv70G|OA8rh2$c*_P0(|5z!>UWWU-0uZ#?%iGHAA9_ph<)>I#JoA|AGP~k(Cq)|AN_2yf6R$7{F=53TYQ-j{8QBB7w=tk&+C`7t@K*+Nr=*+(aeUK!{WQH~z&@SL^iK24nK)X_GoL15Y z5&M$e9z*8TKb@Gx&3j1(kM*b{l4E_*sb^7RB{roT3)MQWSL?wj%f`dk5+T8zgF)bi z?62C?uJe?y39KP5iRC~oiIFl&!$_>Y5*!u49vx*MttJ7mo^D-@Mnxd|*31aj2q)|_fVpiK zyc!#lXH1SC(p|&G&eRM?1xQrRv;=_Wz|RaMMwU^z0WY!?3ZtL2m?h+V82>m1;Ow%Mkg>YWROD z>fVS>!sZ^KAZl*pHr>u6{O&yC-Gtpm#4?KG5}r`kK{LE=6=qg_jV}gFm&G(oQpyJf*hl$k8k$BA{ zehQQ#0T_n!iTe+}6BG5@G%fA3Fy4;t9djq;CpZ#sVG_{Y2lJHh8_ zkZ!^6Um^W6e)srCJoj(7KIWhB+;RVSr9BMoPZxmQON-3Dn@k&xK7zIs5RcjW)x8UI zUjOhm;SBuogF(sQ-0k)q2mSr_>O-8xA%<P( z4xu_BxZY}@r9<*uUp8eMIs z`%faj1Lq4kzfHM6r2DVX)e*Yijr=}LB^OQrxZ`+z(s9xaIG%;nG@LUj2T~aKaeV9e zBAg|Zvy5^c{PRkx*q1z52nkB6#zInspe{pWJV;6$!(cmDhJ-mm@5I!l**i=!q;V`! z12N^Xy_16E3~TTi^daPnkW|@go=7O3gw4+J#i5I}NHKXFWMjfy8$APnPbhvuR?(3! zf#%(Xy+jDu$bUS|kOrGRAE#G7ofxlaJ7`NoC(?!CkEI{#5-1zGZUX^>eG4*zD za&Tf^?%^glI`_7^4;8wASoDKMTnP4h_zo0w$l_z#CXLrm=k8mZdb=;^zWcu1ea)xz zpJcx>R|H>&{ueozph(fJFwMIcj{`9z@81RskNJ1OhtLG+K9K#XG>M!<`FEE0v>Ahu zR-R8ICZ_8YlNU$5Ubm7tcIRi84Rk$tens-u;Zh_wIU^R2!jgF!{0JpJiw5+*@W&~d zoF_&{cr>I57Ui9d+^$<@mZp3KWL!ZnO!;K=U=pKr)BGgnJv8x57e9u!hv}Uy72erK zcFZE{@|n>rb9#Y5UFb?20u{iL!a-;btHCh~9d?zh45xCWcBiPeqk;@ z646^vBHa#raiYm|kL#WT5PE34nVk95wbmiDEFjhxx?(yhGo%TP2vjU;vjTJKLi}q0 z9T@s{WL0c{inj&7?D4(C3b`dw__f5`6aIgIUv0w$zf8`s1;5zX(linn91M%#W!qqw z^eE>yw@G$qb{;4O4ico!91h(AWKftsKOmcZ36QM}Sa5^Zb;Kb}`7Qynh+aWLK-ggh zWTc-RY-p@q+b9rP*3T9hw)_#!}=KnqX@iAqm9$ zQF)HGR9n9`Ag)B*rA$MRBcX_?1{4DqG9e4O+6SW3Y?UzsF+?FnP-o&VO8xOjj0rcn z61aICMp88>H_F@5D)uW6nEOh0A;^}BX2g+5G!Kl%7qk=}{)_mDnJ8mvd{h&k~X z3?3vkI~qZ!IpU!k@;Hj|Q51o&)3XN8keMU8SL~`PTT_&l z)5=H|A#A@E@{O#heX-%@n-|`7Z*j@od-Ds*%Y!x07{;cOjgnI%KQ263MVD?s>Gt27 zxU{gQ1nMmSn&rUs40H%*h)saSv8-7M(GzS=x^F@8(1G-w_<@Rmv6GyE3<`WCRb*pp zIVwc$`hJ@x03b9%%4Lx7Y@zYd>O)YUB?ZTkLa0T)qaI6LAhjf8i;N+9g?|&A(gG5) zDf7G1yOh4)R3(I4C=pM@+cDms(lrm#%QBoT0Hs?1YM=6t?)ZC%gucb9h3Ory`bTy_ z&`5U4JPy=O>qyRu1fO>BMWqOQ(ZRe8z7l`t;DZo^IH36}YJ*TuM4}MJB8sv#lRzy?Yn|LR^v6YiC`zkC zO)Uq#@-VBy+4In3&g1Ee(3B38BfYh9+>qrsFR)JJ(YkM6N)R`6psSlo?4m!bC$-I= z>MFt?$!OIn$v{kCqoOE%C3IlYe%pLyI^R#ulvNnwxs<;ji75aW<)8}D*`CS^ky3(&b&?z{m4TRp>du5MWe#Aj;a*FM zl3c0PtbscU1zQ)qCvd7RK|JNN=9pW)B`5NjTjM)jNd*aqFbVWIT$dLw4Fn#ps=!F& zdU1W7whC8G4Pg6g)fhq_n&&C6XyOVjLS45b)T6_VfWLUYmeM1UhILW}zYrPiaEQw= z0NV1%$50PAx;0*gmllx)S zZEDmEyMbmECRAw&Uyz%nvD;4EbVTKx1Lwhszk8x)j8NzIi{MdZKNqHI71^#0?V)rahpG983bW8gC7eW($1Gd1R=TypKCcKbb3y+dQW&feuJYA6{gc`4;6YR;|BuGE9w2| zVUO-l&py&$n64M5`}VZpo|1cH?QdIGz@mzzmWCD(YEPacin=#P8V6Bsx=!IuPy0*z$mBefZJpb*4ZwECjF^jJ?@9^hcEb@auH39v507Xu6a0Oeu`wG z^Yi}mubn3*L_0rzK zpkv-fc?9N8TG+Oo-htrBX$$Z6?MYRCxutXCe~O!~g(_47JuT~!oR6pA;*_EW9r^m{ zz3-`Qb2ei4@qIVXq4pW;@+uTT74Ah9ur?8Fn(rG!M~l&MpMGfXF;|g9KY12aNF%j7dFMnB+WI=$ag! ziYq0ISlRxh>?3CjlYD#VY@wdWJ+iSIIa^n_F!gCuz5>7j8!|Mm5I@7w@jN!@Gl*OK zIlp7~H~i`eH&JZtSY*niDVO6P|B1qyXuqZPP*tH-&;sH8*2qY7zr|MS6uaz!D0?Uq zYa&F}X~&h&Fe7h~#GfWno)6_rJZiQrXAxsogxdgrayYR8&RtWq<{4X>HpF&HkHmfK zlx39hJTlr}q52)eRTs`~oV3n*ah}B4hw}_h5dTUl&e1q0;k+8>G@P?=-iGrIoO5wf z6z;olF2;$4rj+8OXx+3hY&It6{Clz_Nc8mLlARt1&9 z#u}vQx>FC98I?fE7nK&om%)&Vp z=XE%tya9bk!G{%$4JWHc5>FPa4PHb=_$|S?4Cezlp}fekURL3^7H0!a4d*(X>v4iz z1MaP}Yb(wtaBjy*jNE5%eie%^60_xMGkv0c26kO0eZr}Vr)Lk9W@W5)w98m|nI@(i zO{1D?@QHH5A1gIze33C+U=6AxWMSZ)5Xqu7)>SqqJmZ7bB4)6+Fy%js+_)wgFqWjnQT zD53IYa49Zb;&M?5K@|k1cM7ZbUDR6LHC3HIwZz=}c2RS8Qn@{2=ysoesDo+fJtV>4 zWDgrqyH+bU+8Q+4YSqur8C$KFQwQ@@rLEAA8QHg8{!&gS*W$+@vz4|LYPig|r&Ba- zG3;Z+tI9%sYGa{qPrht_E-q#JXRKD$vr8lE!72Lep(JV`I$Q~R7UXYJH+KeiZaVNh z(#x?)?I-IH#`g*`^u@HRZ+SI%eQWSc=xlCdT3b=!seK>``WK(cdG-5vLyyMg_9usvaZO(luhJa%v=uq_{?@6!q4%}97VJHyW&>q$W*=&EeO^6` zdbE}jb?{?J9ekMm@ASecx$iV3^M}GW=f2YntUY{vXoJV;`x2RFg(o9V-X4vTbUPKd z9X__+5-6+DCuFPSMUbvgf8l!1rv7cH+T$KLhU>Wp?a&J*F(w0q!BLPYkeY%?gg%r` zf+ue4UWUAv$@enB8#l-*wO1e=1sQw`VOd_L!9qgq<12~Xw1ucw!qYxHL^C8fDs_1P^;;F=D&!4L0D(< zrZs2M0VF~jlpUMEVh8&v9UO|WkW^j?pPP^Qle$^~o4 zHhzBv?nV!OPx(E^Jy2(dr3Nf8)Z6JDH|{^a*=^t<2t zTl~IJ;(YHYAzz4)p}5W{k0)Usu}=d@v$Rh#`1s5@D-QhNLiHqcfG5-r(sfW$|1quk24`1m1G9H+e!0cS+{vv#{T0Br|fAJ|^-a0BD&Ig49 zv8mV(=oKbZ=W0>9{W5|d3^udDJ5ZGU-G9WY-^G^{*R;cdaZJV-jix^J7+q&D3WZ!_ zU{BEV;MWj8slI6?@Y{fi-x?W-;*k4k=wlG_T-Y|VF~{Mna@9S2~rHDBfDn3DE^j=0lKNz48NP8ivLoRMh%wGX2I zuIIU9^`94vaw`SOq5R&GKx1QlBYJjZB)>eOAA!@v>Rx11_ZCt2S^-HTyDO)2TfV!x zwcsQ!RQ#Tz3`Vt@p$DF#Mq|2x~nCo9;tV6VW~cG7KQ^Q(rC)gaBM`o1S=bKmz0okjTLraz|6 zIJSo%?Z!#GcjHM9?s}<6swhWKETl^({dFfjNz4r%TVh73)q3GbJmoU9&BrPo=>SV( zL33Y=!B_wVn9Xp=IsoM-{*zqk1b&$RB-4rVpQ;8iCg+AeLIPn2JZ26pifPpKfN{*G z8whhwZOwNvxJhDgBcO&5@);h(~95`F<$2oBf*OA=4Mcp%+?B?MIH zNrowO!7#vpwfcttfQfQXa-e7gU+3{u75L8yT zmiFNnv%d7>YA8U0yn?3ASw%sn7pYVDO`nGgtc4=<6$G6~^j1TliHUqN<_<}t!zf}J z=I}Cf-GjESqw26feeg33^o8NCOeZ>jy)h(qiD7@{T;=+7pnCtWz3+f;tGwDjb}V_v zL$(t;%WvYu&i07yIPs8IVmls5oH#qOEX%gAY$=jF!VFMmLI{-61WFUio?(>{$}E(! zN(ZGB{)G<;g%0S~meN97{?9q@l`JRWYy0bhuitHPbfv4Sd+&SRGoJID^BU<#hFo}% zU&UJolZ_mmK;bC9lQ6L*=KT7}=T@7}t&V)M8a&y@*985yO=GWiJ(hoN%I?RHXwU9r z-dz*1`^n&b@LzdPO->QOh%Pwdmx5DHl%&pXObFFRV+`RD#S zk+sYJZDCKqM$~Yc>|1E#MN~#3*cqI%+KPYX63wKZgR!=Nb2KpE>304iVhUw~LgM!M z9X{0=$p9U9S08i?cvXvOF;SM)W?ShDtoFEf4tRXtK9{3zT`k(C4iC9j$F`9v+U2(g z0z1_Uaa-_R_`E%QUT?s6b3#2)EJD8?eC|^L%l-H~w#VN!)PqU@l``c6?BkcY4nZv{ zyBPx+?e_E*xT4SdmQS>E+FWWN_xL-pbXL!C_>h+DcV$7m3 zhRz*s_4KB@u$LNIU^TSdz{gt_k;xKd;f7Unytus){B#3eFx=8K`xHqajlcK*oV`P| zg?5vN2#wXKaVF7S7gy8%#gb6#BA(rJ3LS~F^?_nD?CN%UCP%EI$($Zp;kNf4n9xaz z(yZKE5`BR&wa^!MbP4aiVlJm>$VmOD1CtwRkp}x zQ`hbCK!aEzy*}0>=<4_3;>k2C_!)E;w~r2TzYphcrdZZ!UEZ!9w{jOFBZ<4U4Fx>* z!Ma4s3h9s{mAL6P(IGemD%Y)g>6~CEJ}gO$#Vm(hH*Yah{1}1i6{yH#&u6FJ8{?5CG#O8W;7Ta^(wpdXAw-;M{cff zq;KcLby5G(^F4f|`Ss1;$DihFKo3}V-+Oe*%8=PWq{$fZK|lBRR?kMjmyY4ag4H{k8^^{bg?h|*uvs8mz}&Vsq? z9PH`tN=T#`7_pu~?v)tGO|FM1!Y*_Vd2M~7M1G&Pl%k_iOM*nG`ceAxxCMOM2G_vv z{9VRuQqUnrbMo;*sMp`koRtiQx?zP1)pN6_N1!2mNHRmZU~chTfazNL3e@6~OCWvF zXxcV8JcGmN>PxQh z3Dz*)zkVC8Jk&*gT$fIxX{q79V2q1f94ragMBP_*Wb^BV{AUjT0reT}^7Vj+wSCu; zV78%wzN7E;h-xP9;u$*p-oYD9*_0@t1M60QW;f zMZ$)9q+|cVsa2E_&+nj-z8g|^#oSafQ4G8aasF~E9*F>43%{}F(&{9NhQ4+N?7rS% zb!V#|59j~3zvT%mr$#>9awSyzIrHS3BQ*6?eo?gXgifNGt1)&haMIV=yWGyxBezoy z=39>@ZvQT!jM6dtdb)Y`{vid3A?7MD)bP0qSr{6GhUiz1OnM#XH7rJ3*)q;VksH>t*gn!sOKbsE&w@)>+Le4&h#rnQ)5vw~iuENs`~!e!VzJ>%ER zd$J=Jk%U>Sy}EhJ1D|hs%cXCWQ2pI>@sP3>A54=w~Tb zs5@gwT>e_mpiR&ISclsQrG$v9C!RBPu{`kN=s%iR%Fo+2%+Wy4?J0RQ731uY%#^B4 z{}ztLNDkNsU0zkSXah!r_eXqKQ$+o25l%1unIQ)3zxj6#I#BNIE=r?GIPXALz%%0L zDo;Xngc(Hxu0i+rE36dH@#NA{c%9zDQ>$`lY82FU@1*JsngO2^n)jDAvndJdjo9ky zI@Wc&(C8W3t95;IGe@YdN1G=?Z{i$WMY!7M>HVOskW#S^2M3iZ-tMQ@tf07{E-p~z z?H7v&7+ms<#U@-@yxdpgJXEGd#r6z#_uzI0)oUHs;ycpxiWikpzO7%!en_7~li9|1 zWM-?&fhdI*OvgyLyvJ=&mAAbRv-oe>_FIZ@_&E^iq2SjRbX~jbD@SOB%ae8MI%=UU zk3}Qc_qg5a^$E;9)S4YOUY%en#QsE{HTXa4Zn(WWP1URs@Wvo+Ce1vPEU=+IyjCsd z8XTVjTixwh>GpKl-RlQO@XRL0O~$;9?$P6aL*gzR73~+%QJ&-j*pn69U`y1Q$ybO+ zi0?Yo+9jtzQiA;o{#-sCGHkZ>?euyA_gZTy!DM4%b5z}I_$4UXNeB7e7E4zn%cx$rBR`DL#6jUwpjUiRa>% z*vAtIc`y}Tr`gd52S81;fa@767R1r#Q>Wz4gG9s(4Ehm`I@RFZN=6t!B=>rqz9kho zlxT)e(Y-@`T=ixIVg$Fx<5L#vTM<0#*;9jzxDVCMB2%)}4kzwtPb~|YQ2aKSCSSK} z_~_4L`r0{MLrBz@lCz=oNhkBf^bRr?%F8D)3aSJdU`KDZ*2X27cgIx}_Tt9zsVh{%mcX zgeb#|2nCUCV*5pr&<_}oLUmrpq0i#n<0$+GjVf8*8y zyvW*uTHO^dKJ@dmsOrzr2-_I&@5E!sBoj-d`cvF?92P5z0O6{-F5ZQG$h0qjIqpZgfP}4Ktfp!48&-lJNlJ#r!BnhHHmfZ30PH|+Df1M-HM16a4Zw)*1;=rJ#2lOb53TW|rrB8vzwnRfts4=8iX zHkMe>%^Tcob&xH?iJ8|;UKwP>r@UZ#V6dYInd z@jNiTd+EbfhhL>PEOniu%WnYtI{Td^XVDke67~LI;U|_b|3CO_bOd0r8rTnCJG3tD z7Bv=v5uwOhKq5hfghvkqu_>y9vgO&}SWJ1F?fR% z;uuD=YV{YYt^_YWi-rbZk$E}ki+m&^3^6yJ28?$4IxjIqeDb zrwQq4eH!*zT}QGKC?{lP4B3#tb9m*HEJQBH{mk{u6d++5N5XHYlV(o=(g+E3`dOE4 z%FTmBaBSO)TUBLwMfem?NY)Wl{fjo^(@7Gka%dwW51$!&54Rmz%2t-;P6Hkd<@bto zp^TvCtlDjeV5FqLwXe3FQuJ%LejNkl)eEdz4c1MMl#CeiVfLMBcM}T4v|KDvhdaI+ z)MpMlP?bk?-8mO-wNMGIJ3@H=JLpyd>GmKzL-pLZA1WsG zX57CSs5`RN^D~MCP2xNe5{HgSEBRNUIWR&6%ANTOwitNKEP7T9gf^AD@Z+y?(`h0< zbFoY6?uG4miqid%RR9N-F#hlo;0(B)D_%gUh-}b$T6qg;c)u>>L(dL zauqFE1Gn;8e~wR0tfAGV)gR%tS@1^pwbcofjk^qLawM)_uU$;p6w^1<>m0Vb z)ttJlNWL?HsRSnW1xo9zlpshjj#szV&5R@y3yvyl*$yd+#_U3(T3z1i!(I&XVST)N zLfgraG$kl2$5{{R@6SPBIYQTTynfc=2kF#HSECSU4|0L(Zn|+Pp7Ag7UlnyeYxzw& z>wlgw1Bjig(U5_cR2tTLKHVD14IX0y68PF7D57N@rdE~~s0#!V7no|{NldkJkrfLE zOs%oK_bf{&Mm>p#3g(CIG%=gA5qflke z;xa&R4}8c0sFgWs*o%Rfhz_}JL5q=xc6#XIC@bERd4HRT=`8OToJ?7U7{VAeXF6rXB5$bKA{iwY<49N>zHpR`2d62X_UgG@q#_r#!O!w{8*;ENzZb`jxA}oC z)<=N?*V)Bcl%=Ej9-4E3+z6uH4AltdaC3K#FfY+yVcUFAIX_=j$Zya6wgZ^ zyAeAtHn+Pekx+W=X8Zm|^CHTM0S-Obd%}SCrM5cC80&}1u_mN9u|1yB#$mwF4o=Lh zv1JXlt`GHY9*+^rhnRU%%DuJ|*|xt)SUb2OWaH>wngZAlfDfH!>87*svW5zG%wKj% ztgwGr0G^nT3U$J<4T}W3S|3iBO=%RfgEc+UG8abW7!i`sIb3DlfRnHXHo&f(`e5=~ zyw5(eySvM+_RK-p796`m^@9bd(H>)S7^WL~;E#*ypn;tfR zoy6zRBUY$hExD3&gPajKTrm?K37(4EhqUoe>hgf^L~ARm2AbEi-5vCd01Z@oTX$eD z4&rL`m&oq40wd6+^MCu}#65mqw&|8Gxzy^RhTV8^GGYOS+XtzGqbn*qgAmMJlf-tM zllr0&0|h6b+Hg8@Z?H)Nu0h125MgoXIUhGTjOE1}SbOU5jYnXRojytIv&Ur%40wU- z)=rE?^ombe12`t9)~(FsB~z`PjPcuu43&U5>K6MEF}A z{Uf$g?xIn6=LXAYPtl2x7tBqpnCX4XT1+NLGc=cd$Q@W(`cZ8wGh8^LmW=Y9ttQSq z3$#D%Rjb=h6yHuFOw7+d=s^wL@zeTTZa<_e7o4{CwVU6@)%RRF=iwRncd+Q3a>A6mEQw4_rtbgOejtkcBtf`n&pEfddmj3e$dGpRYV>A+!UY zr#2XBt0^Dn=a|s}G(hb#6+<6r4-U%XkvR54p!u08fOxJuAuWU1Vh$jO&re#9u|7Hy z*Nl$VsViWgS+Df6N>abd<%SR9IcuMSeb;V}EM}{vb$4L_ynXf;y8T|5pN!%&@eNtm zG!z>KfIzUFxUM)4(id$TK^9}6OXnQfvv3Aj=fNXfUD1xK^n&rK?y3GG&Vx_U7oy9v zf-}|P`zOJJJ|>v}Uy*qtNBfEyItx|97**R)0Fy(eousH@boR;XOm1CEQ-PXrz^Uf8 z_CtRGVU;lA@>cX`#U3s&XmEIzfgCe9e2lQ3X2BCDCVyUWcHy4+Q%BhoKqQd!Resw~ z)o=-JVtvo|I^eb0z8+PDvtx|pY2v{)#BX7nj$dQI{mR7CFuoW+9zKyrrL#?;i?=Yl=0G94-NSFq+%p&hZX=;Wg(B&o3y$=s?1}%|aUOUAmZK zPJ9Ppyo#^jmLX9{0;@^Yzl9dqF)-vV$X6R{BJjjw*cZfwtJ52+fcCPhU7)_yekpr` zV{96Bv4ai2HHTDMCZT4+uGV%w&F8_daS4SwX#YNTKTlg;4K4c84x+23P$!+Dh&JNt z;r}xW+=3NC&ILQbeV6f?+nS|`kda4KGza!eZ9NON*>*%D-z{cU}Et?10&utgooo!s!!`;+hWBFbhMoUAt?WiMkIW|J= z_lU!XInECdf0*Vi;T?2w5P-i99bc1K{|f*MxDrm22l!-1-AFl93bTM z^Sa=jmU+OqjrTFV*?Z)okN}L8na3E%*K;xvMUWk0Q?#@ds&l6N9+#dO#1g`>e8loD z*Ev%%G3sC<_4qlIn3f%_F?&BJh1Gp|WsptgaykYBKDQu2z$4j`+8lBD}b-V5Vq&IRp*SEL4p9&8ik=qOck&u*L(kiLya>XVog2#gbd74zA#(%{i~Z zpkHA1nb?alRxVdtw%mu^f8KTzIctIWHeG%-(SxU;;;tk+a~^(f$9c4N6aHoQ;5jqH z|AVSBB8q1@q#uot7MoTfo-$gj`|K`12LVCWKfo=w8{rgOY^NjO>=s$E;F;B~Uadt1 zld~BUT}KVknmwp4ij#Ozd)Lq_7sy)3dTa~S$|)b>Vp2kEe)4+yN|!pj_*~!$K=}|#I@LW@uSF2c0)`CeQ5V7< z-_F}=C+iF+SVn?m|G91(rK072mrz5xL+L!7&ExE|x~Yv9yKUGo4#gskP=89C5VA zH=sNfPv9FN51ZffRGoTTfJ2IePQb`-VVhQm{XTTlP!4W@a)1|=|F+D=o1C- zlj5#H+`;0;T#5r<#WAMqb#&+Us;OWtaodPnO|JO_GRIzpTWzaN!uU-Ii^A6V><*~6qu7FoIl|ox;1IYR_6veh z%BbUhG%bopJQrf-^Jh?vj1jsv)xnVbo41?Jc))gf@ihy-OmngxKZR*P7WH2j()TOC z1w2<@TPytr9*q=#8QgEaO(uiAX#!I)3KLm%$E{<_0GAJJUw2{wA~42K1bcViorJiH z_u0ZD6Mu7BB5=8>K@@*H+d~68HM47I;*{VKcxd92hmG&#Ic-8s$5<17(9dEJ#=dZ2P`@l71^y5 zn9rn_95L7#h=+Z>4uOlH6}T8dUPBAmySr^(7yb+Qgig%pX*aB6fZ6mq9uHM&1f^pv z%`@aWu&JI*X+hc2#7UN)Ay?woZ4@yrd=(L{m|;ofPbGKpmokJG7F7GubezZ`rv3}G zAq&C(TpsyLPn-!*fPe_!8YA!x=J+lE{h92)VcxO-^$k-zWnkQ8K0OaMr%9u`oR?8i zb7tV_inpxiDWfo)?`2rU6)1SWu#~1C-W&TcobKf=j?|T4yqKE$bNSb0q>%0NxKFcA z0{52b+-?OeKPM2SmO!qks&jAS>o zIE0iaoc2FtPoNpd-3IW(>ebxEkOV}e%;;5}Ww&Av66rO_ySKs{NQptscK{fp@~>)- zq!=D;47U2Pd21LS%J8sxvTWIsDf|uH9sVs_BP8!XW4q)^&$aXl&D?Sa?sv-5=q^`( z!GlQsv|HxhTqG@YY1r|rIH~^!)amg_{V(HPT&V|iIWF$Zwynm+l zOBR3nSf0PjiAJeTDUukU=}(9J=+L0WIZ(~(fOOb>ejOjgB36@XPjzo>GcGi?X9zAk z*xKs!w8ycZ5|Snu=R}E2X3}5qRDu@G=FKSueO;I zp&eX<$6&l*@bN9$%NlBsNrBI#^HKxND0RdWJVq5oL-b)p)R7hke3MX}lCC+HTwxG} z5VapHJpPM9d`>QKK4?e|H`ZK5mz~;#f*&VcShisyf7eFYMg4Rq_+LEdCq!(ZZ0TYP zcY4o+e8lJy4F){@r9$z|uC0E6}qjDUPy^LgjCklW3M&%Dj1U~g<<%`Va$46fEe$^Wh6a_y{ z&8kgcrXbU8N(kL98b zPX4OH72m|ZnJ1rHJy;XX_`cUYTA+@sC}6o@H{9bGZD;_TsPiaZRov>vsE6=9&6tHp z4|OHeN)KnqTN412u_+EaarqpJ{3~O3Jhi`fTjReqtLK^hUu&Xrbbl%S-g%4bo_P5u zWZOrl5z=;z6rv^1-_@=N&BW)Z03pc6TB~@l#-z_IgW^%^dpu84bCM^kHiRykMADrRUglp z!#oeeVK_2xg|I#}3E;K)jS=7lvFPbx2)Yl$ug#xDlTalhr5;GwN&3(AZi%9lF^>d- z5USW<^iSNFAP>yoc@^Xf(F=DknPc~#t<|_IGiUwW>bdGaA;tlujg|!6r`1@&83ukK zSP>BHf_wpr@Qz>>Onq<)YJun&2w_8AJM=Huu0Rj%r`N5anAo6NQitjkBvK@|P`$FE zQ21q#=`f%}u%#p`;*z7^{40dxAzE zo3Qtr%|+0XQBF^fIwKCG5!eNcVBmB({?YK{gq^WG>wTPN%p$XD@Ip;5&&q*Mh}v9Z zfY26#9f2J#*9m#8@Ee%j0nMP?i|rWo@cHkD?O{m3;kvW9ol=?m$=GdI$z>6g5FA;q z=y|FHA97|vLpPER1Sdt~OQ;^#F5{AlM=@3yRXj0uYSsV4uR*gLqpZg`3ZtS#L~?D-0gXV0vMDmvWZC0#nud`+J_HSJnr%4bZu* zpMd`XxXca`s@I|(zS}WLWqfyP!61oBukG~u_euc`e+9970 zNrYM~`~@^o{K82#+j_PuczaxvnC!S_j-5Sw$ zdv10VP0R_RPUCS4qe{gve)|?I=5rZ)aRNZ9ZY%v}q z53Q+ofX>nMtSR4%l*C-HQA!g*miFemj^K2BbrpMicOW4a+&funVUq1y}8J#%Xr zd%=AVftaHl72jYxfEg;KHoaA^3NnKR1Wp{X##)7F4SXKfvx}=M$P90jjsAl*NFeex zaUghh!%{pCME-`O%{67an;U`NL$^uY?u54Gi1>}Y;nFsixpDo$f^G;?LN!_UFM%sK z!)Jc$#1%@e;k3)>oC4z14`^RRd+(t(3(fNPAEfJ#z&iIKdnfQ8Z$0s>O}vqLHzH zqdwXI=8zXdBL5lJy^2v=W9~n{ea6Vb^Yqej%%2`hNr*?@PK_3 za1k6@Mi;c0n1xHO7Tdp#ANtH}?`)#icU?1doUP-w@#vA#P^#gXKR8u=BBgWAu#eeFz zsduw%=)%vgj21*tW8OfJbur{PB{!C`kN1h|;@oY=|HOSLw*orgIA`-8&NVYmti8q} z)jh8sk)kdFuq-(_LL*KFCJ?4)M~a((B57`kS6x?pegtK)g@dQdQ9BA)WSqkjSh09Z z5AlKW2cfS_OgdFRshcBmrTK6Dn;Pn*dzz2ik!j=@z6aYe2wu;sjj)@j`{5o0!v50z z2gauzjBFL0h_)ffDA$Sz5^`eODf*Z60#K5Z;=VY-OWI=p&ZkM;RdheyLSLY7(t_D{ zj+U+Np8g0mq4kS}taSPA4V(geKAiu_%@8#IlP$a?e)gJSMfkUdVW(7d@@1m^r6G*^ zL&{C!C-y;Uyq#J?*@CchqW_(=Su_#agcJVZ&0Jq7aRu$P(_s6uh)cw?*0GWU=Bu}Wc1fmMtK_JfRX+gux1A%=t$s)TuUT={MM z417GTcZLrwT1?Y~QOfsNP&5P|67s>0=-lEjuziBYk!n5BIPi>73F@|0=2HS|N9G+p zQ9n{s0C^fS{UHE6Kz-PouARA#R4m@rT#Wk{ZN*a!_k$R-W6~J+f%$Mr8%>dC4(sjETAon~fdclH9|3N} z)FIVf{UOd`X10)9HPvFB_7H=9Ji}g;G@id+nD&1)=Np4Gww=u{EsApY+`Q~G_$Kmk20E>BgPEJMjpxHOT)jsc} ze;emyeHrM6+kk%<8Ns~Kb9IczEw$Ph&6o2M7=^*u!?3E?7OuybL9=yfNvJ47so6M9 z&DxVmfCxqG#gix%BQMSW)YT>XfdjDhhe~zX-L4azhK?564%;y>GkEHsQL&9Rv3QN{ z#%i$IfLOAal!DV?*00^$YNsOJMcj_-cf*qoRuPHc0P%LKj>ZbiY3Oi+NqTxCFKUB* z+o;TI-MtO53a1SRxeQ59?eW;5undlFH1+$A?VzLlleanx@ZTxi0%F&>bo**LNE_xe zriT#3)=!t?MG^HJiIe!xjXE_Q`r-aYbW5Ph$jx|iQXj;05OvQ4$P4ZtDo&Kbi)l^p z;}BIHHQU1+xj(9QN#sT;b_-dec>242@2+&3XE+k~X(7KwYv46sOzPvRRI%mys z*5Hs=dw}?U20~^;dkkW(ahIJO?!D1X9abw4+tOMj>=^wQ?Ot&h`ISj z$7gmVdhCart*gJ#6-3Iv?oUXiII|lW1BXhV2t9(a-ppBg1LTHnwcR~9G@zpc%vKI!4NVb3 zjF7f}kLht3!*n;5!pTJ)5M(^pVnfN)nAB&g7p;ujlhZ+&S)3y-ROG1c^Fkk6(8jgm%-+ z^rjj#nTv+Z_SpN?>$Mq>Llb)i>iUK<_7RNKVvovdT+aKFYaBtRux~cjVBaiiK}~Bt zL1T5&(FOU&6WWsC8^u}CRRnVdlcjEB3B`^>rX=ftgcdyE@b0eRJ**~h$Cw9t9_1j_QBq&ITVjfI%7}#|L?WN?WEawG`~{dH{XDu0dO9uHQcYBq4x2mh)eXo1(P^mOO?L*!dA!z=K=C z!^+D(w3x6+1pC~Yz0nRu>~hp_fq=*b`ZRN?uu6#MxDp*hfypz9?~P~41E&`WBz1ax zFUJ)E@vGCp}Pyc;;nNQnQ3O_<&?tSJIhi1s8=&PqIE|}_qVNO zFu;(0g9F~}bhy9)l-!<ZOqh+2UZjY|hfR#Zm=(3I?haxg4TsF|5-g=*ir z{gH@^4J9ge5p_>PE}8F^P(O$uYC7uB9U$-k{*G-Xt-Ep$E%U&jR#QGv9=L!jnFIjT zhAsxee^%@L^e{S}>h`Y+QxY4`A#Mk$&X0)Z2oSrWZV)UMz@(JVRD>g?H>lA91a{ts zhM~zZFyev)Y)eFkIkS}fs}mEEaMs+Ck?wmE=RixFZN32v`;4RwGzHd!XR=7o$r)J0 znLe$@w@$B|Gjlzv#SCjusJ^nGIRc{sK?pjjVFAd>k_m`m*eC3E^+JI%-v<@s(D1r~ zoG~iM11lAD{Jy6u3o^pKp?l{&)#(V7Vo~MUjTC3E`k?I$8U1m5Uo2Lk`2$aHiU7cZ z>?OLls=VzFe@3(qocva2HnO?JWLXJ9Z*YT2*p9l;%*Aw$Sq50mnE<{rOFC1(Hk)g4 zi`jG}JGJcV6FIrt=`d+y77bcP4HWT>AcI+Kg9=jN5Ln#EX*% zJz&5B+6|4>jBG{=>L(-zWaxhH&R?6_u*wHypb>bBb_!~kOi>ZLjJvTIjbYT=NtfVs zI19&jJlcPI@!dNHAAtYA;;xS z4Ux>-Wv(X*_|cbj05JNh85qV)%<`kEIE~sGP0!&fPr-FVc%EQ@~{8Q{0b_uaPAXUw+sKwf-$&6dhv4sUJw8>FaSUT*GJ9fnaHjH?0C5e0%Vr9 zZEAkTci1+Fsg9d8i%~k6uO+I!&;!4Zu^jHs@Nw}zc+^6wQEyp)t!FY<`kYd|4yX=n zy_;En=T&beS-mINR51v~abzL9nh>o9SwTkfj;6y%wKw`zC`V%@xExXxs(#+m!#%d3 zEp*?wF(TJEiTV2;@MrkjlKY=eId?w*eZTj%t+>?79-Vp)(I~ai)mJupZ?JScg(qCQ zq^LMQqyXR}ji6OBoIy1=3c;gT1r~r0qL4rks~}wfL&Oel5{tl5tO9yAYTqt8r5xBy zkTkB+Q-CmJ^R*rQE#QiYA=s4$eIfUT$8Gih1yeVAtw4-Ylq*E(+UX z&qFPmSVgcj0`~9z>pg;|@6gvM@34g)|HbqZ-K^{%yy4(epncZR#niKC{}0bzwrR~L z;5G@GZ4K6WUTI#1Rd+PZZutGW_LsZof^)MzuAQF|qiTPOOMpf;Ygn%=-pXj4Hu*-o zXgp_W00VwuR3d{E2oEDJC2h(B9&03s9vz4lR)PUApfO>n+YFsP_x~lJ&#GaH!i$zbZ1q z{w@>4=PX?a7zH*i*tN5vJdvV+6fi;^Q&~e(^=o%+Wjs2Y!=nU%rmm{`G0qajNaNep zHI#*!=JAiKDvQy*$O_a4Yc7Z+^o47e)bm=jr{}vxEowg(%#GRk#E52Qdj}Skwn4S7FcKgyIdjD<71UQ8c{7 zX3^};t}eDjx9b;j>#kUzY=^1J(z83bD>eOEX!F znOUSp*Io#%Zp0Sq_09KUPjkl$RK@m3{`FcNkN0ofHnj0V091Xp10#O71&Q6$axc9i zdoQSaJ10L8H9Bfn6|ry;x%;nP@}(y}8Zmkd_y0gIFLizLm-$oMs0MMKOIf441O-`} zF{u+NbE0)bTCNxz;HM_nQp|BR^@&+UfpXZ;G-g#I0x!?i=j!RL~WF)G^n6S2;Av~g1zwec9IXie=@6WRhYdtpMj zh|0O3JX7fwzrUpATak^;P~sv4=~_#^a5K4@d)LApun;0ULctNL0Xs#!4H@wQnra# z{Zy}*8}RiQ!@*b4DOYpckLNC`-*+Ib41M_wr(W$ze}9B+79()>wB2f(9wGT%hqz51b>YE>mmQr z(u~^WG{rQ`YZaJRwPLVzj~`@W)wZ^iupg?i=00FRvZVFv6YXeh`uQ8yzxIkZ!R23a z%Z^KSHF3i)x{vzLxxzwhpUWZl*!JetW<87EcM|PQi`)!8jIp;f#*G;|tg691zpr)uu(jNW=9vKz#|{xa#1|!V+8) z+j@o#B1^x5^FXt}FVSHePS@k8n1fs+x;0_>MRh~vcNtk=Vz^pd{XqmH1;ILDw-gF9 z3Ly!6^?Ln$WRWrJLj~VtlHQ>AwC#dypk7S6x8$uk7kikur1&|5^$4?2v@%7`;C_dy=`X~k5{;Oq z6|dS&U&6~R7vYbCZh&-hWpAk6uVw(D1IX8-=72djI;u*e8*wODuN?lbk1HjU_=2+g zP)a?#E9CQJsh5LO|AZsQ<1n_d60ZrxwG^FTWfK9hVB)Ui<2laYY7e!>`mS{Ufy*un zUC5%$?0X2u)~NGMJ4zZ>aCc|vpE)BK7awQlvhUW>9tGdc#GM?}f(xnX!T4#7bp{$2F1Xik#cV+x z39~>4RqBT8`FGi=-_F`_S{hPmrUkiC2()l6W?=Y5{N6nfcYl05y*T=wvA$j6}@4xeC zKbk*gQQ!;DqqGsZo ziTvwEzTZgqBO3?i*G_;0E=Mgyd@M)o(%u7@LYzLtvN7C)o0W!B1BhHppce=Yq>59;meKO=?_8M3Rgh9Zn|2w(Ug5Z(~C76vP5S_rQsiZXn`G#_3C8 zee&szZQ78w+qE47zvIFU;DGEbKNpps0D-X8TDtc~qqBE6`c=t-AE;sm8<@K@nvfml z*}%WA>f?Cv5VN#`P){Zd<29b^h+jQ5`3-0dMDRMbZ_WG}j+3f>Ci|Z}@f3!N4CG4z^1WHD*4M zeR;5I7I*N!WSg^`yjL0bl7)p}@Um#*4Kc*1`s1QbNX$|E!C*Foo6Xc07Grfd z&O!&e3e>yB7h)C)&%Ix5YC!Wb;K(^$P~sBl3}4=~ge$qErMh~l?R0z&{Ftr04&1>1 zaY#@Rl&C`G+H@F4C50kB6on!v{7101@Cg4w+Z>v+efU_;xn)I=7a#Q4_z!YA6Vs2ggi0c z;&y>|+oy7qIl3@$azI^~d?jATj2cBn52akk(RTO>l8`I*Kh)&ZTW};kV+E^rPkIe| zW9#|xn-XoiT>G=;A+M^ndVzW{XOe*_7%DxSC74l?!m){;A%uQ)r1TorG6Hb}L>#RA zHrJAH7vGnv+K_FG7I(p|W?J9IanMeh*RT2-N-)x3n+g}jSa?*ZD8fSm=6Iwfn-OKm z4@gN~wQuzogyrkpsDUc53vpy^4$cvjuOf9|(;fKL%#eJ6 zoi?^m6kO!LPSSelVDU7p^m0A}cNfc=@13XwJQI8D3|J_aZk=dla4+OLNta*Tt&#ba z=t@KYJ-pgKt(!yGNR3r*ot(9tW`P07shrlSALH3WF^Da`cUnY*_IAc>ad7sc8+@SP zlY%9{S-_n{I!3K5y9KisQp0;I%T^#?l!5ERdM=ot$E^bkc79s3Vmrmdqk;bpc9Xd8 z7+1a8yLx)fZam>o#bEIF^`cNI>$gx$8XgKviwIt5u-@5Zqe=YyJ_p++w8sK(pKd=u zhvreCFRSgTSq;1##3@u==7g7yde9f77aCgtS^qB>4cY@X+l5gUz@yS11};IWDHawI z5drvp@b{d0g_oEfbl2>~v|pX}C}s_`rlf_HW77Y_*}?hKoPpvgzvJ;2U#v)_%+5T< z7sKp<3(pRhtDtBu<^r(yfXk_Nl^*2L2T%wihS!=zSe2CtM5?zY660sAt$I{9W?YBC z$p2NtTArImA+D-fwHjW7pv{bEuV}I19A>}U>GZ0PR-cXB9@ww}UNdZ{{SvMx4a>+I z5(4BnzN3w1hB`wAqYm-VLR|vFR%9J=owt26vQu&FaG;_H3lU{^S|vlzL-0@Anz9|C zbHmi1EIVbj{x!KsmdS<);R|Vqdqrp?WK4GI~WDtX++k>Ylym11C$h zyVa5v3o$y;Y>p6ujW(2G5As>htv%~Ovetb(@eX8%o3h$$y8aSga{C69m3P~B{^!*C z>H!`1mk0bly12RXCbr1f+Oz47tMe^$D@x(FVLPAd&wN`|AUxSn3C|;O z>6C?78AwNY%G%CG|k z>W-;@W-AZ1V5D?IR%m5TGDRE{-D^bPr};}M` zs#}bzw`||U-oJl4>z2Ey=>?)k!1Fk52i*298ojoJHqa$5w*6U^L{II0DH^UHz&-VT zWCku-YNJFyO8Z}oj^Q21v-gcI;a%|&kTsFuus*I9emOI_bf#~Gkck-^2KxOj07V6HdJ?VuR(;US%Br1%_Eb0EvW-ke*_TXqL~ zb6`kGZa25WL>5Sy^oe}GO2J2fJhGkWtyxKv^lP8LriD_uk_eAOHFIVhp5fx9?;^-!K08pz2H))5-Z3TfOocZ?J~+nWaR46?6y~IPeLLfOHfH} zS8rcHx`GL|!NI3+1^@B#atJeg6Pn?5`iUwsiHX0L0RUKRsU`QFv`YWrL&&G0^{bj3 zfh&v!o}g`kw1P#hmkWbH1pO!iSu3s%fVEePO~@%|zW}=b9@AzpfTA^tP+e(8Y8lU7 zXhc)u%P1KPK)At7?3Lw((32f)MAdI5?!j>!JNjidW~V)jea;*L;qj|?CjW#jj=>TN znWYaVTL54h`lCp7P6MKw8>&AaUplOrV`KHIzf`F-1?L=dIlH^K-toIjCg7K`VvrAT z&-g_h#t^yVpm-e{Ho_N?^D+9%GS%g=`?^0nse&8TcOSE~csB1j3k}~n+e0fZA1*j` z9X&nQPG7!07xvaku9HzK*S;}97W1Kpj!oF{=qHBcn(%ZWMN%6 zMuP!*EsRX&vBav8(m`f43JD19MfUlkOzSXavL4E)LuJRU#*ygn#YErN(E803ZFF** z2b=+QXa?&H6elG~JK_;BM1CVab&w2AYNbsdO=Sh+`H3FA}z>{2t_> z`9mghPOjKQGom=}cv9t3R627fU*)S!X4yyeNC5qd2h>PQC-#94X@(HQ%H4fWTLtH* z@hj{rezbZe?jjV?!83%9B7kjh1>YgpotrAbAC4WtFGD{3YKiS}oE17iaD`wl*enbA zs`EOZ!H55hZ5~(3f%e(QC-34#pQ!+^PJ#hgs)$yefi71PyQ{--00}To;)uVTl!)gK zU8&nYF--PKN}lLg!3!=@Csw?BWI493u4->jpE!qfO&D|Yj<((P%PUz~K zu$lL%yzWPfTPejXOY5jNtNsfSI+q71f6W9u9wQGd-II(~?h>2nqNE|WBmp5?0s$)X znsfe1kCdO}=V3$Ew}x85_T90J_FJw81?V;)!MS(C@1xO17KY-B4?bhe96){!6H7)I z%Y(x_NVRtKxrcY4&*vEl;q|TfSffKgy@$Nranr~GZO`C6+^sj_Hvv(HhS047b5iHf zbj&>0piqGgO^>w8`_<^$3h{43a5u<#dJdgDRnh^5Zpz5RANswo~ zn3(#or5Ccp{;hpv(CtiW%j3+5-t$gvo5I|0q08UBdM(Y8wJF2~K>xwo!I?eovNErA zU>(hWq2R1}r0Ls~Q#tLtxkS#(>jrLJT7XVqJ1rYt{LSfaAG-5;y6<(`{s+nG0P&Tn znJ1qs;Cw!#1Fov%5ZLdV zJSQ6?3n}OwVpw`@-V%)a7>}4W39PvL=|yp1k#I$bUL$;@Xs01B;(DkLmz<7$i5d)~ zFsw!V%f(YDZKA}Ya(mowc3NUdMT&Kqc~@RGY)=fcZl$XyOde z!RhFKpix1746eVrsKqY13gA%o6M}hUvnCzg($d9!f3=lB{G(%>hIJdE2f225sfzFT zN+kU7aY%%AoW<1;UWTLp{mu@AFyl4^`BQo~7U8`LLdphxKQQw<(fI>hkV6OPivy?O z)nSaOt+7p9e!be7LBA|p(1be;@955JmKqm`=@}^4Q-sxDjTl~FRXFW4OJ*al8E>S> zc;2mBI+IW%;^x=tfwJ3?5yCHqb@2`5(QqYPi`$MRxug)6xqryns=d}<;!5zOc~Owa z+UYbCc1h~Ah2R_Pzl_P}#AzWy(tkOL^ZCbkbb|Zqb-ca9hnirPqM<(kCa70ioIK}w z(QY&hQeSBGY947=MFujt!(m+?@$^2^TNe}jU1VvYY+PqMU+ZRO02v#|0d-gl&a6AR zW+q>b*{REK)Gv|`;vnGmx@iBo6c`VggXo{{Q?Ypk7>}bma%+h!TdoNdWAyjrnGdYLW$`}t3-5aLDRlVM zC{97dM#>WVILPFm3FbJ?ilC_)XJ0Og%RaBC&2{CX!oS@EN!VxZSPpUVRqp4_OHdNg?N&<>-#2 z^Y`kqE%*Ohgw;*+S|9|7oeJsTM(V7$z_em1aF!a3KJzuupDPU_Y%H;(L8ur;@_TeUZ^Q-l|bpsv%2DO9A)BeTxwsf1<%gJ&Gc16-Bi40i)GLN*4EY1 z)FiG54jXOV|9ASQqdLsk`AySyN(yy&8(R$`Y%vJ@4zhr3R!0Bjyj>olzk8drd{yzn zPWsYwe5N1O5Z&=hn*K=O9PB-LKhZk(A+mhH>y%6Xr=ag4;BOqTxhD znCYL>GZUay!h42mW#P`8i2UC%@4N2KOu?@OWwKD!&YUPR2%+Sxg-9K2zI(h3-j|n& zWXmzDl(@z^QooyL#d)O?o(aV8V+QBO;tH5yfSz;4*@M2%k`;~3^@032N{Hio)gi}e zHrXiWle{F_CQG~4%&PwAX#kt{#*Gr6eyLv}FO22A}S`4E4bpA{aNdVbP> zjp>debvG`tPYca;fUxeJLe0}{+4qhw_}glq(TMxljZC1 z{gF#R0|H0dV|<*Z8b6=$5+BEXW4L7G*IB=ntb;LESs!6`Ib4VGGAK>wm{>y?bC~f3 zne;K>pK{Vc-7vRCx{TpAJt$;_ML%nKBPrZDdki+zz(`ML&WUmMfLFcOUPL@}fE~J# zo8z4bpkM-|5f>4{1H^s+MZru52Xx4#*BQzgAJ2)}^B%X3o2%|YUwOatS(v`RX`4kG z>5h4n*@?*Se5nB8fNzB809om=7Pp0`>!)IsR|JYCBEUV9R3P=Nwj5 z=4u?yb+t`H1KxEWNe0_&k_3i5U+MOA*?C!Lwi-G!jE=z=VKpP^LX4Aq?!A^>s+X?#-iA$bTY1ayDg5-1DF&cWT``S&GDt^gqZ_nf1@4#Ys=){0RV+{% ztOiyr#-zfSYu0x|Lp3E~Z*VL~K*TV>6j&(}#x($5V0w7ZsEC zEse6EHy}jpTgYj0>AGux=Z7Kb#L3;*!^T%v2HNawBd?L|Rg`j)QKl?r8VQA3u+bwTBPs?tiAJhHcq^?g) z&~UCn&G(;Z6_O;+|6!2QwqixtNwGmdSG^IB;1SPG+MqbEPDtjOE@PC6ly!y)2GlL0)IVoU!cG@abWZ>bz(ne;!%@!c|d_{-*9I<(8 z_!%K5+tuS%srlXDefzti_SNBhG$uEmUZL8*_t5BrwUw43ex8Qf!Qv8J(Z1j#OROfAf^r*4I6aGhUJLo*x zF!QT8?IN&p$ijtyD_{{I5;wNo^Tjg{5FLpXdKE+M4e<_q!YgfY;^#-{QSh3NnFn6S zk~!08g49#vmV;nA`wYX|i$LztE3qRELN+zDXb+E{wCPmmmRug>eX(#LSaZKx!fTW= zF9Yartq1iD8vjLqPuH<=y_tJ8468?*Rz=cSjL&Z#X{8U0Wm@nS6yZM1`s1w z!|EaXi~sx~<-z+ax3!et1-9=-9KOOL>wbgr0|3a66aWMP+&}zxzV!beMNPa*_y33e z1AK*o5DD#JDIwN@p0_48Leub!;UZAor4zM#S^})Vi}1?u8v7Ta#UDou5Ds2gL6%oH zVJQ35p&B!ukV)3?I#jb2YX-_|_YZ42aVf~x3C9}#Sg6}yC^I5;`*59p-98z79-eu{ z%Dw(d?!FNgF@vz{XV5=Lt$qSGpN6A(cpkPr@tGPP-0?qod+IUE8}!vLmx1OD{O9}^ zR$Rs_zWL6CvvA9r`?sFt*hlm;#8YryJtGSvo1q0QsOOSm@D+eNvb>5iY4aSY#p?9MtNVE^UmfQgi z1eue-P!^oh)h5!0EZ_1q+!f|4_l^zA9C94s9OCk$i*x70BZ=l!L5d3185K`rk1@p_ zbyjVv$YE$vPLfJL2&?*YT`uM`x2IRXuU~+p5Z{HG{P#7~QyQL;Xpxl&m%S)#v+`ro z+yh*V&L#!A+!|L9Ni9+Lum3V~8$4SCTuI#eAkI8ifyDBuE0Dyi1I>0AJ<>}!s)1h% z8;rAlnwR%K$k1NGT*r2LW#e{B&zcQ#=sBQ(U6o&|zoxRTLluLB`d^LczW-9FK!5R|oQQ0oaP{=#`h5MJjmzyXCF?2p7kbb#%KDz@%H~cWL&*H$zkQ3o zijit}2Etmr>Dpe*OAcOq>D7p0jaepSAHBL;ycMpTf#ODHZiY7%Z|!qpjZ49GlQZE; zj*H*LRUURs-+&PdkL%@qmvzP_ND%t{1AO3q|F*dmn5%mIKlsPup+FJEluV^bChiKa z)>J-+BVem`AOTd6zp*BRQlhy1OJ36oZ98huA&F;K=(R>y!8Lf*i>bpfgXC@cD>O{TQ;7Me@Jk`9x}OgnTkUz|(R zx_=;RsU)3HgF;0F478$vvbbBIUTFz}EMyl&{p*4&t6kg$1YKOk6*vFi`=0Y%=bHqc zt$FZqp65;GJLmn*Iq&7X=RNPa%&)42ST97qP@jQvQQEXTo$VEajY5oiMBT-)?0PNI z6H9l-(wT&os^IKpvE4DTzeIn{_&-n~%6Fzy$)2X=VsH_c5LlT^YSCsbmC=&1z|L4Y z6-zcPU)GaMiow~8;ae4p^*M4Da8AW4EuD;{P?{rqA!k=LC$&s$4G;=SeitLuHfz0o zk#uZzA{lE>^g63Qjge-eZP`RB7i)=i=eCD-#Zp;EZK^TNTHhWjX{96kJzUJ(=5#EQ zjVVIgqUl&HwJH~n$I=e;#f)Aj(OVMfSTw7p_c#mHDda-kYSkNWAZ&>A^(9ik>r0~HS$Ca#H`CY$(V39#&%DIvN@K~a_MM6 zDN43fijER0&=sA_$y{cK;>X$)*fCiTUror=Zi$pBLZO!KjbxRUIw@3rVKt12s?|}5 z1z~-nI~_^yaUiI!OC{*kIWXq3^S2njg@)U272TR%uL%TkaDqx_hf|1zD7Zjt^ z&VrFkXSDR%R9tgZsKjn!ZqRz1s-`TTi6b?$pjM^ACZ5$OyVR`=vx(oH$QCM{g_c}8 zjlrU*317mDok8VEO!vONl+o%7(AGL_tfhUjJXcF>;f@unpfs~}Es4xd(vP;jNMY|# zeGIK@Nhfy2+V}Jo$X^*NpoCJp5@{{f3$C=mOr*9ubzXHNJ8EYnorrW7a@wSX3}rJE z!JUC7B|6>|jA2`%+p&Vd&Qu%1BR!!Gig9Yy9#>aGbwSWX_-%=gI`!3#;9_eX2w<_J zSD2Dtol7QLBiS7rBfSN3P$n1+SszJnk7d9z?v7hv*|dI_hM66AeI%0&rPG?zSFvEw zsN&LgQ=;p&?KG&fnkeZz&6!Du71^mIrrgo_b4m8z+~_q+lXy}(&N|=A-Ro3vWn-?l zJC@!Qx7u%Z_nZwlmtR>}_{s(?mw`3UX2Dp8i01Pz(?te~f)4WnwTG`W+hIizk#EygfHL-}(J-6W$A;c7; zBDM$xX7|s0){>keGRIG8moh~qpqs^{)*VUmEYeY{&VNSW zsb18{S>XZv3!SHHp3Fsyb3zF!ywjW8+6hDqg@a8@(MV%>X$0EC?z*LN-Sc`JxogGIpmN4Xa=OE2eLJ?12sSuSQ2k4dIb&f)eN-&bUiN~k} z`R+YVIRv&@XwiAKwK})%r<6q&R#cjt?b`XQ?*q%Jt5#~<)j@R#uAyxQTv}%l)*1>F zMhsftckM1pU8!;8K03r zh_)rs6Qg;%qcN(foBCoYms*q^lXEeS11TMIl%mGE)>sUq68on-k#@F9c^I1`iA*fC zI~wbAi4-aBY(_Xr73C~NRc66(txUDuf~JBUj<&0*K_Q+#nQ-7MkGufCXi!A4m|k#U zv4t9P-{6|b@xoE7@;NqREZG$+I=ULn%V4~AoiHiA*_=&wr1~+3a8#q1fl0My#E7gj zY^N+#g>4i|a1RqGFT#S6O($i)cIu)stQOQ_5e4NSJ26|e3`}@I@KLFqiCsMYVB$<3 ze=zZ^+;OoL%5s|c?eG+f#oLsSEy$AuD@-iubGi7k7KTm{)-dH5O7*xJ9Fq`BKwyel zKAK1xZ;)FsEjJ}Yc&%E3!mJLJRMu9N<>HQ;g-Eq>^NUUTrkE9@8Xgy1>M_eGHV;u_ zG0G?!f;C0_7Um8p=&j5h2yIGlUzsi7cBFRj>PnAcg2DVkzAMAjwnOXJ`!;t+hj?`E z!)?;yMaHu^JjW?*OBSvP=`71-Faq_snk-$5ji`1}&qFb{J(liGq~wI04638W${x2T zGj7h%JZ@__a*KPK$fQ|QB$;!L?MhjJ07knZD9iO0WuROs>14PJ9*X%gzXc7?k6=D%Th#GI)vA){d=X}+k>tvqdEmzyymvFvp zt+%g82!r44E7%!ec{N#}DV9bd(@|^Th7H=Ufsl5Z_iM;^E2+<~Cn>C~q%3`}h7@Cs zkxPr3b`06D3c{e}*rJ)O>DVrNrlsa~ZBwk*o@=R@a|>&>yx&3kRrGz%Eqq_<@r)3Z zSGpA{G-+di9JFXd3<6I(vs#}-vf)Tg4y?@(6IN1>u{T8yS@o8DEK0=EiKrdTR*Z`* zZ22w}OXaJw1bS?(RN4B@2zXkPWn<%nEnAN6)%x4oZmgEu5R^0^$99eRV9Qm~G;#~1 zVb#)sT2UQMCc3Za?$I*KqLEBw&@aRxA3chLB|_{N^oon_yy;*-l!n_wm$mzvH?@Qg z-cl~kXb>e{&qB^s6S;J~!W8JpESb>T2K3w9CV zU$hr=J>n+v1{V3#PLbQ`jeR6X^xkWs7fDmldl5loKD4f6D^Ry~js3{UO(E?3+!@hm804u|yg{?N(>-9OcXYX8P17;3VEmM9!|y_VSP+qIh*urU)y9ubOuSt2Tcl;Z z@up+Uv||P%?DY4gQ$+vgE%YO43i_w5|5$aS50P|)5kTfOZoOxA?L&`sjXiFV2|W2R z?InzZG8eOzy_6}b$w!4bB<*?AAZ=wMWuwse>d^&OLGKR*n!bm@p>AASif1IPHu{u# zs50q8$`tgypXmGJG|*QEZLVNrNEQIPef`J`Bvo<}n+p)VWMn4NsyGei085*&28Tv3 zn8X@19aGjIp5IWzqvyPM{`m11Fp@snHCFFX2^+su_pdhjg_J4ybr$ifd>Z&=>I0c1 z>iFka^#L7!26yt}z5WRY?bIV|{hvA&_5aVB{hyNFDgED65AOYF{d{}hhxJE)u=V|c z8KRc`gQ%9qW`}roS#+PIPEQaAv1(xP{Yt}zw`cfw%A@-(xrGZz;HQ{=py~RtzgIHh z?HHaVX37l%*5!CHF<2o6{vbT?;>52kWPl+I{f*KFjWiEmuSxw?DcN_FJyVTB%m2-=XYlrptk@s& zlgF121zs*`g0p+QvS)RoM#>K>Io;`<%c8$f)XC@U+mzlqlHM=u((?&8?suEgYZS8( zP}Sqm<_eN13x{LaNGLR$AZ5pl%JyLA*Y`&^sg9Ws`74fPy=!u_?<84GJhSguuJS6O zJF_qQ&OP>W=~2jBbUo@Lmme=2BFv-o=PHjBe%ILC+h>UrHSONR^E*ophdMncKG^O# zv7+7k?YnA(7qbymM}>IAYC|um0QwBnhye4iCzgyrJDx$)#i3GuO219sRTJ+{v-3_6 z@9s5u=NB^aE>bogRikxfVXhU8dUbS$;?P9S&)n!5`yW#6@=nhcb`p&Ki^)v1w>N?Q zyGQn4J>l*4-*bry&*W5`De9biuX%2>5z&5{+f;Gd(#ML32TE z&*=M!+VA*;fP9a?Q1Uer%*6ZZnDTwcvK3E+-lU|LB`=0TZ{|a9J~?*&?bYINJ)~XL z={G(& zg@8qXMnDkoF2G{I62NJIrGR$>P6wO;I1_Ld;5~q|0m}gA0Nx8Y7qA@A1b83d{ebfT z=L1#%E&%)$-~)gQ0Urc>2=IRZ7XelRRsos;Er1YUHQ-{v8o*k>C4hB+^?(h4jet#n zR=}lz&44yQJD>y53D^R-3~)K%!+@=TD*#=9ZGbS~N3MM7Qkl!w*o#3xD9YS z;10m&0Hc6A0e1lo0S*H`54aof1;7^p_W2hs#Mnq{TmFhA0Uo4}|GdOIc74kd-`24W7{N}=Y4=oH&D4PI zzif|XqwK%@UivTU`R)2Ii)i$!pM3P1JSrpI6;(a#@N5;0%g6@S2=T|!#cFtt9~Dgq zK0btr6TFl7QBTwU4!CKY@GBmUjPVBr_GBY8{tWB(mlAePKK@9TVj5;oAj?w@15a%N z(H}EBkhUY|j0f{$7+!9+$_+UDvCcEi&EXn01`P#NY-VcfL)JvWD2RBCRPGp^sZ)8Ro5JQK*rgW7 z$(S#p{kvl6I4NwM(IY8kiuuy1)Z|&yAW`Wt$z~?vG~;hn0TT37G!$t-@s0+~zS=$> zjNft#NBAJYBg=SB)iu^^QEWq>6RAEe&H9{>5|jz?$@}YaqFzh`^-`Z@o4PT3cy$D8 z8XjL5DbVhlly=K}uqLb)QIOCNXYTaT^K`D{JN!+@;=hyzj2~XHe0OI2&cZ4bYw@q) zTsEyZkJM$Z&M!)sf?r=Ie(gIc{MsP=;Y@5hE#PA!3I{c%(VT=_YW`k)g~`pcovWF!X&QS2vLh(B!QYh1n^|dlNb>`-Q*FPKmpwjF%#JY~OAPgMOcln#1M6|O30hGGER|iB63ulkM zOe-b!)ic<_AT6Jr0|tFe^2CV$(N^D{h#bKmkTYyOX^QyY*~FF7lfsqBJr@}9Y z-J|C!W{~1->3lQ40g4jHU)^vZRCl1uf9di6D0%(!m+$>o@9T%Rg%_1?3wMoeG<5;& z6ox*ew0>HST^3y@M+5a7Ik;l#=wNv5#Y-y zDJ|RB9cxVIQjJ=wQLa?qG>Ro}Dw@h|C2zN+-Lu#-xFXpYUo{-|R|Cw8lA|gmGI<}n zkQnycY0xG)!l*`}<~FTRpS98kUbY`b)0{rT^lX@!>uEkc#4;^1CoC#WeWZ+CH@7bjen|9;9tq;nMP;q z+>+1v;bmg~!jUuJUjHz>?ZSziuj$y!CHY6G7xwCO4^)dPj!*VsL))_Gg>rWWJxnpO zo=J52r-4qnJA+yTB0sEDfF8TCX7w}lA&immw%W?t4uoh0dTHLfwOsnpMq1OcrTb;- zCv?J57=29owVknL(dCMMJWN6Vw5>Wzo$o`7y0L8k1Jxzy8O?7sR-X-8^P#$>Lxn7W zDl8q8$zv8C81_QBHZ&riF7;idOrh^{Ne||p3_URB!P3VPV&UkiO1OyI4vXP6CBv=0 z;mgW~uk;V^sO%cM(n1FdljNz#BjKd0`S5`B7iB`vqW;J`q{+=8KW8F=zk%^&fS~|Aqc<0o`XE9TwsvPh8g{&c8?0FJ?}x|J1nH^MJT@ z>zzV8JIO6Tr6M3|DvV2f_z|n81&4V!qrvSQEaz03r&{@WHXp2^jpcM&#XQ6z%MZ}` zIQ_&QC)K;`*q6AxomFlsZ7lJM(t;gaJ4!0V>3D#!(*r&#ewQt~QRt08oys{Ns>cxZ}xoXz?oEM8}6=B`qUEr$~b;Wnpy~pPl zi%P>ZF!lJVM1v?}? zq6wSi{ZyPWqfIZjRb8bZ@#X5K{9a`_nj=%n!%5zmFQ0Tx;ms_x_pKkgP*q7$NEyF* z3KAw|`E&lpkw<5TmE(#lt4T$e)(Ta*U^RH3FkF>l0U^Syp#F0 zjtkmk>TF(_Rh@UOd4-nDEqad$XIDa7I^{Kl{9IvN>mc7&dP8Ta6+Yi|Ku0b4IUw=n z%?F&)06o!n3K$1SIj6?Vp(CK2R%fQktD&4_$Q|Kyx{`AOz&FlF8Y#w!Ku)Ql)|sc_ zIBn8{IE>-f&j#?5eOKXdNvW8J*b z3tH2;AI?EdIUcak5q!jpsTg`FG|@7Wl!ZA;Smi4f?;0Sdh(+T<{PRpHS8~VnOGcR~>drv^J`dbi(z70OH*6tG*Lkv> z->f7V$r||CPxhPY;-?uj!rM;xakB7Z^fm=s>o~G1aRSyes+?3|99UGPutmYiIDV8? z6(_xHPYHffXL{se9M*tRvMa$$;8c=TQAXx6JT~f{gRwWBJqPJyV)tioxTKukAp=d1 zPnTeEq(a|H7<{P&^C3~j$`Gvb;WSM-X$q#JH~MA@_+uyc^H-lod40#kL!C=*#KW@w^q$wm`QVqw=dYn(a zU3!m%#TUPE`Yfcwn{(Wr##w?cS(K*1?(dP-$wAq2%@n^fx9Alb1sNfnebv=KW zB9#cju7ubT&iqq+J|V=K$1d#txOni~XHov8fY%p(Nr=y45l*~xLhKav*{dfC?kZ-I z9ajcRE|Ij={Y8>5GR%SznnvHp~yYmz1NEkeuQ;v?*1O)u~0CeQfuk z#Yb<$l&>C^=2Ag6Ky2M7&Zqxhc_MYM*gkH#JetdseZ#cA)wbJ*WQ%I-H}`NNd)uyK zK!Z7OJKTb5EA5K^GdZnrP>?+`l2t7rp_m6gnQFI_my#XULkeF-XPk%rx833?(%20X z931t|0%QDm!q6QLKINT*jw`49!RNeKyvBQKRrXbHji~jjm8jr*d^ojPq4()-*{S_u z6@l;Y1w=(Dg=K?T-$}ReB+Fu-da(gnUl4gl*qM#qf9qfGZTb|Z{R=*fqz^rK`Zuii ztV`ay+?mc9wdjk@mYaelHroJs=Z|IHG#j|qYe407Q5hv;x(`<>g?WRKEUk+C1$FnE zOsSM++3*>vEH_U`49x7KX&lH`_&n;H{X>q-6z?wKO2_Z?Or2(3BH=V7eYOekAQ>t@`?RRI+o9m=0SOBfo!M7IjP2e zNSf2+N#jeTp0f8qUZ%2GDli#*qXY{CF8fB-c*_KiZ`(c>k*^`vUN;iOzxyu#2l3cK zgaf~M1|xmCsrSLd&(vCDd^qhbsVUfF&&d?!Q%p1BCT@3I%QC8fP2JX%!Ca)+y*&NC z4*7;2MO1g!8g)WF!z-GK><7ODXUh?C~{%>t!4T?v`O-mcpOz z&*g~vY@*_?zjjYt)FbRWFC)YSlybVbNh}f}e7n`Je$pdYO3N_(a~(`5^E7NCG5r%SB(DLGd<9R~LJ6S~b#4$3VU>WnlM(WKM%kI@YKZydxNY z88ay3Q!K%Gi2h&(E=@UhV6E_0h*^F$7zaCi*spe0`rZK35Vm~QMQ|e^uPb) z>TgcoE(TOV=e4ZoZ`d9o#1KaZ#TAFDTKH!>SZtElG~d$wcRBBp>3laa?2+R(Va}xa zTjA}%@;zyZ$pM$o^AJNQa;qRC%rpD3HQHd95sJJzMirzKt~BTo0=`~~OD?|o31%Sgsu|9_Fqwv z5+V(-|8Rgz*DX5zP=KDI?ii?EI`8aVt(k7i4iRw1%WpJ`2 zzcQ@BGB0M$>e$*mZ$MP(JIF_|a5EDl^>&WUacGWwc-lA_eASC zm`VQnn1=uLhpyNxXeM*(jpvExcZ;XW_&1+|u>CmqMOJ{O=eFOZk(@8~BQ!F%!F z8zBi=Hv}5r*eA=7^Yh8P7CAFjVMbxOVu_7Qg}z7}T;OBNON^eD&v~0qeGoT#ps%kH zQLz&#RBgEhivb@D2C z)`$y$R8+-!y^$M1*_M|r3vA8Qt8 zoO(ZW0o!tK<{1G_Ft6Va)!1{z*K5fCH-CkR*+}+Z`P^0}i6XyF!0))6s^@f`(cAj+ zyn+au;V<$V?kBuCOVIpGN!NCPuFS1Mu5O5AN(IXmYXCCPFKYQ&tuo?9Fo~sRXOz-irL_Lq|4v(KjFRnd{ZRe#-5itnB+36W zk;31LKZ8HliqDCq;%@V2_#`iCTkOAsCR2HpPDXj`b1P_y{RfZ~N0H7Z+pw%OpRliv zs}+4?#jehIsWlf>=e)(0Q)}$ki*lM=;fbg@q7kFV4QR3l>#KU|?jl~d@l${YVff%m bALh +#pragma hdrstop + +#if !defined(AFFNMTRX_HPP) + #include +#endif + +#if !defined(MATRIX_HPP) +# include +#endif + +#if !defined(LINMTRX_HPP) + #include +#endif + +#if !defined(ORIGIN_HPP) + #include +#endif + +const AffineMatrix + AffineMatrix::Identity(True); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile AffineMatrix *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::BuildIdentity() +{ + Check_Pointer(this); + + entries[0] = 1.0f; + entries[1] = 0.0f; + entries[2] = 0.0f; + entries[3] = 0.0f; + + entries[4] = 0.0f; + entries[5] = 1.0f; + entries[6] = 0.0f; + entries[7] = 0.0f; + + entries[8] = 0.0f; + entries[9] = 0.0f; + entries[10] = 1.0f; + entries[11] = 0.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const AffineMatrix& m) +{ + Check_Pointer(this); + Check(&m); + + #if sizeof(entries)>sizeof(m.entries) + # error memcpy mismatch + #endif + + memcpy(entries, m.entries, sizeof(m.entries)); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const Origin& p) +{ + Check_Pointer(this); + Check(&p); + + *this = p.angularPosition; + *this = p.linearPosition; + return *this; +} + +AffineMatrix& + AffineMatrix::operator=(const Hinge &hinge) +{ + Check_Pointer(this); + Check(&hinge); + SinCosPair x,y,z; + + switch (hinge.axisNumber) + { + case X_Axis: + x = hinge.rotationAmount; + (*this)(0,0) = 1.0f; + (*this)(0,1) = 0.0f; + (*this)(0,2) = 0.0f; + + (*this)(1,0) = 0.0f; + (*this)(1,1) = x.cosine; + (*this)(1,2) = -x.sine; + + (*this)(2,0) = 0.0f; + (*this)(2,1) = x.sine; + (*this)(2,2) = x.cosine; + + break; + case Y_Axis: + y = hinge.rotationAmount; + (*this)(0,0) = y.cosine; + (*this)(0,1) = 0.0f; + (*this)(0,2) = y.sine; + + (*this)(1,0) = 0.0f; + (*this)(1,1) = 1.0f; + (*this)(1,2) = 0.0f; + + (*this)(2,0) = -y.sine; + (*this)(2,1) = 0.0f; + (*this)(2,2) = y.cosine; + break; + case Z_Axis: + z = hinge.rotationAmount; + (*this)(0,0) = z.cosine; + (*this)(0,1) = -z.sine; + (*this)(0,2) = 0.0f; + + (*this)(1,0) = z.sine; + (*this)(1,1) = z.cosine; + (*this)(1,2) = 0.0f; + + (*this)(2,0) = 0.0f; + (*this)(2,1) = 0.0f; + (*this)(2,2) = 1.0f; + break; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +AffineMatrix& + AffineMatrix::operator=(const EulerAngles &angles) +{ + Check_Pointer(this); + Check(&angles); + + SinCosPair + x, + y, + z; + + x = angles.pitch; + y = angles.yaw; + z = angles.roll; + + (*this)(0,0) = y.cosine*z.cosine; + (*this)(0,1) = y.cosine*z.sine; + (*this)(0,2) = -y.sine; + + (*this)(1,0) = x.sine*y.sine*z.cosine - x.cosine*z.sine; + (*this)(1,1) = x.sine*y.sine*z.sine + x.cosine*z.cosine; + (*this)(1,2) = x.sine*y.cosine; + + (*this)(2,0) = x.cosine*y.sine*z.cosine + x.sine*z.sine; + (*this)(2,1) = x.cosine*y.sine*z.sine - x.sine*z.cosine; + (*this)(2,2) = x.cosine*y.cosine; + + Check(this); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +AffineMatrix& + AffineMatrix::operator=(const YawPitchRoll &angles) +{ + Check_Pointer(this); + Check(&angles); + + SinCosPair + x, + y, + z; + + x = angles.pitch; + y = angles.yaw; + z = angles.roll; + + (*this)(0,0) = y.cosine*z.cosine + x.sine*y.sine*z.sine; + (*this)(0,1) = x.cosine*z.sine; + (*this)(0,2) = x.sine*y.cosine*z.sine - y.sine*z.cosine; + + (*this)(1,0) = x.sine*y.sine*z.cosine - y.cosine*z.sine; + (*this)(1,1) = x.cosine*z.cosine; + (*this)(1,2) = y.sine*z.sine + x.sine*y.cosine*z.cosine; + + (*this)(2,0) = x.cosine*y.sine; + (*this)(2,1) = -x.sine; + (*this)(2,2) = x.cosine*y.cosine; + + Check(this); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const Quaternion &q) +{ + Check_Pointer(this); + Check(&q); + + Scalar + a = q.x*q.y, + b = q.y*q.z, + c = q.z*q.x, + d = q.w*q.x, + e = q.w*q.y, + f = q.w*q.z, + g = q.w*q.w, + h = q.x*q.x, + i = q.y*q.y, + j = q.z*q.z; + + (*this)(0,0) = g + h - i - j; + (*this)(1,0) = 2.0f*(a - f); + (*this)(2,0) = 2.0f*(c + e); + + (*this)(0,1) = 2.0f*(f + a); + (*this)(1,1) = g - h + i - j; + (*this)(2,1) = 2.0f*(b - d); + + (*this)(0,2) = 2.0f*(c - e); + (*this)(1,2) = 2.0f*(b + d); + (*this)(2,2) = g - h - i + j; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const Matrix4x4 &m) +{ + Check_Pointer(this); + Check(&m); + Warn(!Small_Enough(m(0,3))); + Warn(!Small_Enough(m(1,3))); + Warn(!Small_Enough(m(2,3))); + Warn(!Close_Enough(m(3,3),1.0f)); + + (*this)(0,0) = m(0,0); + (*this)(0,1) = m(0,1); + (*this)(0,2) = m(0,2); + + (*this)(1,0) = m(1,0); + (*this)(1,1) = m(1,1); + (*this)(1,2) = m(1,2); + + (*this)(2,0) = m(2,0); + (*this)(2,1) = m(2,1); + (*this)(2,2) = m(2,2); + + (*this)(3,0) = m(3,0); + (*this)(3,1) = m(3,1); + (*this)(3,2) = m(3,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const TransposedMatrix &m) +{ + Check_Pointer(this); + Check(&m); + Warn(!Small_Enough(m(3,0))); + Warn(!Small_Enough(m(3,1))); + Warn(!Small_Enough(m(3,2))); + Warn(!Close_Enough(m(3,3),1.0f)); + + (*this)(0,0) = m(0,0); + (*this)(0,1) = m(1,0); + (*this)(0,2) = m(2,0); + + (*this)(1,0) = m(0,1); + (*this)(1,1) = m(1,1); + (*this)(1,2) = m(2,1); + + (*this)(2,0) = m(0,2); + (*this)(2,1) = m(1,2); + (*this)(2,2) = m(2,2); + + (*this)(3,0) = m(0,3); + (*this)(3,1) = m(1,3); + (*this)(3,2) = m(2,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + AffineMatrix::operator==(const AffineMatrix& m) const +{ + Check(this); + Check(&m); + + for (size_t i=0; iW_Axis); + + v->x = (*this)(index,X_Axis); + v->y = (*this)(index,Y_Axis); + v->z = (*this)(index,Z_Axis); +} + +// +//########################################################################### +//########################################################################### +// +void + AffineMatrix::GetToAxis( + size_t index, + Vector3D *v + ) const +{ + Check(this); + Check_Pointer(v); + Warn(index>Z_Axis); + + v->x = (*this)(X_Axis,index); + v->y = (*this)(Y_Axis,index); + v->z = (*this)(Z_Axis,index); +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::SetFromAxis( + size_t index, + const Vector3D &v + ) +{ + Check_Pointer(this); + Check(&v); + Warn(index>W_Axis); + + (*this)(index,X_Axis) = v.x; + (*this)(index,Y_Axis) = v.y; + (*this)(index,Z_Axis) = v.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::SetToAxis( + size_t index, + const Vector3D &v + ) +{ + Check_Pointer(this); + Check(&v); + Warn(index>Z_Axis); + + (*this)(X_Axis,index) = v.x; + (*this)(Y_Axis,index) = v.y; + (*this)(Z_Axis,index) = v.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply( + const AffineMatrix& Source1, + const AffineMatrix& Source2 + ) +{ + Check_Pointer(this); + Check(&Source1); + Check(&Source2); + + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source2(3,2); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Invert(const AffineMatrix& Source) +{ + Check_Pointer(this); + Check(&Source); + + (*this)(0,0) = Source(1,1)*Source(2,2) - Source(1,2)*Source(2,1); + (*this)(1,0) = Source(1,2)*Source(2,0) - Source(1,0)*Source(2,2); + (*this)(2,0) = Source(1,0)*Source(2,1) - Source(1,1)*Source(2,0); + + Scalar det = + (*this)(0,0)*Source(0,0) + + (*this)(1,0)*Source(0,1) + + (*this)(2,0)*Source(0,2); + Verify(!Small_Enough(det)); + + (*this)(3,0) = + -Source(3,0)*(*this)(0,0) + - Source(3,1)*(*this)(1,0) + - Source(3,2)*(*this)(2,0); + + (*this)(0,1) = Source(0,2)*Source(2,1) - Source(0,1)*Source(2,2); + (*this)(1,1) = Source(0,0)*Source(2,2) - Source(0,2)*Source(2,0); + (*this)(2,1) = Source(0,1)*Source(2,0) - Source(0,0)*Source(2,1); + (*this)(3,1) = + -Source(3,0)*(*this)(0,1) + - Source(3,1)*(*this)(1,1) + - Source(3,2)*(*this)(2,1); + + (*this)(0,2) = Source(0,1)*Source(1,2) - Source(0,2)*Source(1,1); + (*this)(1,2) = Source(1,0)*Source(0,2) - Source(0,0)*Source(1,2); + (*this)(2,2) = Source(0,0)*Source(1,1) - Source(0,1)*Source(1,0); + (*this)(3,2) = + -Source(3,0)*(*this)(0,2) + - Source(3,1)*(*this)(1,2) + - Source(3,2)*(*this)(2,2); + + det = 1.0f/det; + for (int i=0; i<12; ++i) + { + entries[i] *= det; + } + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply(const AffineMatrix &m,const Vector3D &v) +{ + Check_Pointer(this); + Check(&m); + Check(&v); + + (*this)(0,0) = m(0,0)*v.x; + (*this)(1,0) = m(1,0)*v.x; + (*this)(2,0) = m(2,0)*v.x; + (*this)(3,0) = m(3,0)*v.x; + + (*this)(0,1) = m(0,1)*v.y; + (*this)(1,1) = m(1,1)*v.y; + (*this)(2,1) = m(2,1)*v.y; + (*this)(3,1) = m(3,1)*v.y; + + (*this)(0,2) = m(0,2)*v.z; + (*this)(1,2) = m(1,2)*v.z; + (*this)(2,2) = m(2,2)*v.z; + (*this)(3,2) = m(3,2)*v.z; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply(const AffineMatrix& m,const Quaternion &q) +{ + Check_Pointer(this); + Check(&m); + Check(&q); + + LinearMatrix t(LinearMatrix::Identity); + t = q; + return Multiply(m,t); +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply(const AffineMatrix &m,const Point3D& p) +{ + Check_Pointer(this); + Check(&m); + Check(&p); + + (*this)(3,0) = m(3,0) + p.x; + (*this)(3,1) = m(3,1) + p.y; + (*this)(3,2) = m(3,2) + p.z; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Scalar + AffineMatrix::Determinant() const +{ + Check(this); + + return + (*this)(0,0)*((*this)(1,1)*(*this)(2,2) - (*this)(1,2)*(*this)(2,1)) + + (*this)(0,1)*((*this)(1,2)*(*this)(2,0) - (*this)(1,0)*(*this)(2,2)) + + (*this)(0,2)*((*this)(1,0)*(*this)(2,1) - (*this)(1,1)*(*this)(2,0)); +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Solve() +{ + Check(this); + + int column; + Scalar temp; + + // + //------------------------------------------------------------------ + // Make sure that we get a decent value into the first diagonal spot + //------------------------------------------------------------------ + // + if (!(*this)(0,0)) + { + for (column=0; column<3; ++column) + if ((*this)(0,column)) + break; + Verify(column != 3); + + // + //-------------- + // Swap the columns + //-------------- + // + temp = (*this)(0,0); + (*this)(0,0) = (*this)(0,column); + (*this)(0,column) = temp; + + temp = (*this)(1,0); + (*this)(1,0) = (*this)(1,column); + (*this)(1,column) = temp; + + temp = (*this)(2,0); + (*this)(2,0) = (*this)(2,column); + (*this)(2,column) = temp; + + temp = (*this)(3,0); + (*this)(3,0) = (*this)(3,column); + (*this)(3,column) = temp; + } + + // + //------------------------------------ + // Make sure the diagonal entry is 1.0 + //------------------------------------ + // + temp = (*this)(0,0); + (*this)(0,0) = 1.0f; + (*this)(1,0) /= temp; + (*this)(2,0) /= temp; + (*this)(3,0) /= temp; + + // + //------------------------ + // Make the first row zero + //------------------------ + // + temp = (*this)(0,1); + (*this)(0,1) = 0.0f; + (*this)(1,1) -= temp * (*this)(1,0); + (*this)(2,1) -= temp * (*this)(2,0); + (*this)(3,1) -= temp * (*this)(3,0); + + temp = (*this)(0,2); + (*this)(0,2) = 0.0f; + (*this)(1,2) -= temp * (*this)(1,0); + (*this)(2,2) -= temp * (*this)(2,0); + (*this)(3,2) -= temp * (*this)(3,0); + + // + //------------------------------------------------------------------- + // Make sure that we get a decent value into the second diagonal spot + //------------------------------------------------------------------- + // + if (!(*this)(1,1)) + { + Verify(!(*this)(2,2)); + + // + //--------------------- + // Swap the (*this) columns + //--------------------- + // + temp = (*this)(1,1); + (*this)(1,1) = (*this)(1,2); + (*this)(1,2) = temp; + + temp = (*this)(2,1); + (*this)(2,1) = (*this)(2,2); + (*this)(2,2) = temp; + + temp = (*this)(3,1); + (*this)(3,1) = (*this)(3,2); + (*this)(3,2) = temp; + } + + // + //----------------------------------- + // Make the second diaginal entry 1.0 + //----------------------------------- + // + temp = (*this)(1,1); + (*this)(1,1) = 1.0f; + (*this)(2,1) /= temp; + (*this)(3,1) /= temp; + + // + //------------------------------------ + // Make the second row zeros otherwise + //------------------------------------ + // + temp = (*this)(1,0); + (*this)(1,0) = 0.0f; + (*this)(2,0) -= temp * (*this)(2,1); + (*this)(3,0) -= temp * (*this)(3,1); + + temp = (*this)(1,2); + (*this)(1,2) = 0.0f; + (*this)(2,2) -= temp * (*this)(2,1); + (*this)(3,2) -= temp * (*this)(3,1); + + // + //--------------------------- + // Make the last diagonal 1.0 + //--------------------------- + // + Verify((*this)(2,2)); + temp = (*this)(2,2); + (*this)(2,2) = 1.0f; + (*this)(3,2) /= temp; + + // + //------------------------------------ + // Make the third row zeros otherwise + //------------------------------------ + // + temp = (*this)(2,0); + (*this)(2,0) = 0.0f; + (*this)(3,0) -= temp * (*this)(3,2); + + temp = (*this)(2,1); + (*this)(2,1) = 0.0f; + (*this)(3,1) -= temp * (*this)(3,2); + + // + //------------------------- + // Return the reduced array + //------------------------- + // + return *this; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator <<(ostream& Stream, const AffineMatrix& M) +{ + Check(&M); + return Stream << setprecision(4) << "\n\t| " << setw(9) << M(0,0) << ", " + << setw(9) << M(0,1) << ", " << setw(9) << M(0,2) << ", 0 |\n\t| " + << setw(9) << M(1,0) << ", " << setw(9) << M(1,1) << ", " << setw(9) + << M(1,2) << ", 0 |\n\t| " << setw(9) << M(2,0) << ", " << setw(9) + << M(2,1) << ", " << setw(9) << M(2,2) << ", 0 |\n\t| " << setw(9) + << M(3,0) << ", " << setw(9) << M(3,1) << ", " << setw(9) << M(3,2) + << ", 1 |"; +} + +// +//########################################################################### +//########################################################################### +// +Logical + AffineMatrix::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) +# include "affnmtrx.tcp" +#endif + diff --git a/CODE/RP/MUNGA/AFFNMTRX.HPP b/CODE/RP/MUNGA/AFFNMTRX.HPP new file mode 100644 index 0000000..5c215a0 --- /dev/null +++ b/CODE/RP/MUNGA/AFFNMTRX.HPP @@ -0,0 +1,195 @@ +//===========================================================================// +// File: affnmtrx.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specifications for Affine matrices // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AFFNMTRX_HPP) +# define AFFNMTRX_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + + class Origin; + class TransposedMatrix; + class Hinge; + class EulerAngles; + class Quaternion; + class YawPitchRoll; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AffineMatrix ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AffineMatrix + { + public: + static const AffineMatrix + Identity; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile AffineMatrix *); + #endif + + Scalar + entries[12]; + + // + // Constructors + // + AffineMatrix() + {} + AffineMatrix& + BuildIdentity(); + AffineMatrix(int) + {BuildIdentity();} + + // + // Assignment Operators + // + AffineMatrix& + operator=(const AffineMatrix &m); + AffineMatrix& + operator=(const Origin &p); + AffineMatrix& + operator=(const Hinge &hinge); + AffineMatrix& + operator=(const EulerAngles &angles); + AffineMatrix& + operator=(const YawPitchRoll &angles); + AffineMatrix& + operator=(const Quaternion &q); + AffineMatrix& + operator=(const Point3D &p) + {return SetFromAxis(W_Axis,p);} + AffineMatrix& + operator=(const Matrix4x4 &m); + AffineMatrix& + operator=(const TransposedMatrix &m); + + // + // Comparison operators + // + Logical + operator==(const AffineMatrix& m) const; + Logical + operator!=(const AffineMatrix& m) const; + + // + // Index operators + // + Scalar& + operator()(size_t row,size_t column) + { + Check_Pointer(this); Warn(row>3); Warn(column>2); + return entries[(column<<2)+row]; + } + const Scalar& + operator ()(size_t row,size_t column) const + { + Check_Pointer(this); Warn(row>3); Warn(column>2); + return entries[(column<<2)+row]; + } + + // + // Axis Manipulation functions + // + void + GetFromAxis(size_t index, Vector3D *v) const; + void + GetToAxis(size_t index, Vector3D *v) const; + + AffineMatrix& + SetFromAxis(size_t index, const Vector3D &v); + AffineMatrix& + SetToAxis(size_t index, const Vector3D &v); + + // + // Matrix Multiplication + // + AffineMatrix& + Multiply( + const AffineMatrix& m1, + const AffineMatrix& m2 + ); + AffineMatrix& + operator*=(const AffineMatrix& m) + {AffineMatrix temp(*this); return Multiply(temp,m);} + + // + // Matrix Inversion + // + AffineMatrix& + Invert(const AffineMatrix& Source); + AffineMatrix& + Invert() + {AffineMatrix src(*this); return Invert(src);} + + // + // Scaling, Rotation and Translation + // + AffineMatrix& + Multiply(const AffineMatrix &m,const Vector3D &v); + AffineMatrix& + operator*=(const Vector3D &v) + {AffineMatrix m(*this); return Multiply(m,v);} + AffineMatrix& + Multiply(const AffineMatrix &m,const Quaternion &q); + AffineMatrix& + operator*=(const Quaternion &q) + {AffineMatrix m(*this); return Multiply(m,q);} + AffineMatrix& + Multiply(const AffineMatrix &m,const Point3D &p); + AffineMatrix& + operator*=(const Point3D& p) + {AffineMatrix m(*this); return Multiply(m,p);} + + // + // Miscellaneous Functions + // + Scalar + Determinant() const; + AffineMatrix& + Solve(); + + // + // Support functions + // + friend ostream& + operator <<( + ostream& stream, + const AffineMatrix& m + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + inline Point3D& + Point3D::operator=(const AffineMatrix& m) + {m.GetFromAxis(W_Axis,this); return *this;} + + inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + AffineMatrix *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const AffineMatrix *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + +#endif + diff --git a/CODE/RP/MUNGA/AFFNMTRX.TCP b/CODE/RP/MUNGA/AFFNMTRX.TCP new file mode 100644 index 0000000..a8d051a --- /dev/null +++ b/CODE/RP/MUNGA/AFFNMTRX.TCP @@ -0,0 +1,27 @@ +//===========================================================================// +// File: affnmtrx.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the Affine matrices // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/94 JMA Initial coding. // +// 12/01/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +//########################################################################### +//########################################################################### +// +Logical + AffineMatrix::TestClass() +{ + cout << "Starting AffineMatrix Test...\n"; + + Tell(" AffineMatrix::TestClass() stubbed out!\n"); + return False; +} diff --git a/CODE/RP/MUNGA/ANGLE.CPP b/CODE/RP/MUNGA/ANGLE.CPP new file mode 100644 index 0000000..d92049a --- /dev/null +++ b/CODE/RP/MUNGA/ANGLE.CPP @@ -0,0 +1,205 @@ +//===========================================================================// +// File: angle.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for angle classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(ANGLE_HPP) + #include +#endif + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Radian *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +Scalar + Radian::Normalize(Scalar Value) +{ + Scalar temp; + + temp = fmod(Value,TWO_PI); + if (temp > PI) { + temp -= TWO_PI; + } + else if (temp < -PI) { + temp += TWO_PI; + } + return temp; +} + +// +//############################################################################# +//############################################################################# +// +Radian& + Radian::Normalize() +{ + Check(this); + angle = fmod(angle,TWO_PI); + if (angle > PI) { + angle -= TWO_PI; + } + else if (angle < -PI) { + angle += TWO_PI; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Radian& + Radian::Lerp(const Radian &a,const Radian &b,Scalar t) +{ + Scalar a1,a2; + + Check_Pointer(this); + Check(&a); + Check(&b); + a1 = Radian::Normalize(a.angle); + a2 = Radian::Normalize(b.angle); + if (a2-a1 > PI) { + a2 -= TWO_PI; + } + else if (a2-a1 < -PI) { + a2 += TWO_PI; + } + angle = ::Lerp(a1, a2, t); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +ostream& + operator<<( + ostream& stream, + const Radian& radian + ) +{ + return stream << radian.angle << " rad"; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Radian::TestInstance() const +{ + return angle >= -100.0f && angle <= 100.0f; +} + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Degree *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +ostream& + operator<<( + ostream& stream, + const Degree& degree + ) +{ + return stream << degree.angle << " deg"; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Degree::TestInstance() const +{ + return True; +} + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile SinCosPair *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +SinCosPair& + SinCosPair::operator=(const Radian &radian) +{ + Check_Pointer(this); + Check(&radian); + + cosine = cos(radian); + sine = sin(radian); + #if defined(__BCPLUSPLUS__) + cosine = cos(radian); // STUPID FUCKING BORLAND LIBRARY HACK!!!!! + #endif + Check(this); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +ostream& + operator<<( + ostream& stream, + const SinCosPair& pair + ) +{ + return stream << '{' << pair.cosine << ',' << pair.sine << '}'; +} + +// +//############################################################################# +//############################################################################# +// +Logical + SinCosPair::TestInstance() const +{ + Scalar t = sine*sine + cosine*cosine; + if (!Close_Enough(t,1.0f,0.001f)) + { + Dump(*this); + Dump(t); + return False; + } + return True; +} + +#if defined(TEST_CLASS) +# include "angle.tcp" +#endif + diff --git a/CODE/RP/MUNGA/ANGLE.HPP b/CODE/RP/MUNGA/ANGLE.HPP new file mode 100644 index 0000000..cd20991 --- /dev/null +++ b/CODE/RP/MUNGA/ANGLE.HPP @@ -0,0 +1,276 @@ +//===========================================================================// +// File: angle.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for angle classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/18/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ANGLE_HPP) +# define ANGLE_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + + class Degree; + class SinCosPair; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Radian ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Radian + { + public: + Scalar + angle; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Radian *); + #endif + + // + // Constructors + // + Radian() + {} + Radian(Scalar angle) + {this->angle = angle;} + + // + // Assignment operators + // + Radian& + operator=(Scalar angle) + { + Check_Pointer(this); + this->angle = angle; return *this; + } + Radian& + operator=(const Radian &radian) + { + Check_Pointer(this); Check(&radian); + angle = radian.angle; return *this; + } + Radian& + operator=(const Degree °ree); + Radian& + operator=(const SinCosPair &pair); + + // + // Casting + // + operator Scalar() const + {Check(this); return angle;} + + // + // These comparator functions are not designed to make exact comparisons + // of Scalaring point numbers, but rather to compare them to within some + // specified error threshold + // + Logical + operator!() const + {Check(this); return Small_Enough(angle);} + + Logical + operator==(const Radian &r) const + {Check(this); Check(&r); return Close_Enough(angle,r.angle);} + Logical + operator==(float r) const + {Check(this); return Close_Enough(angle,r);} + + Logical + operator!=(const Radian &r) const + {Check(this); Check(&r); return !Close_Enough(angle,r.angle);} + Logical + operator!=(float r) const + {Check(this); return !Close_Enough(angle,r);} + + // + // Math operators + // + Radian& + Negate(Scalar r) + {Check_Pointer(this); angle = -r; return *this;} + + Radian& + Add(Scalar r1,Scalar r2) + {Check_Pointer(this); angle = r1 + r2; return *this;} + Radian& + operator+=(Scalar r) + {Check(this); angle += r; return *this;} + + Radian& + Subtract(Scalar r1,Scalar r2) + {Check_Pointer(this); angle = r1 - r2; return *this;} + Radian& + operator-=(Scalar r) + {Check(this); angle -= r; return *this;} + + Radian& + Multiply(Scalar r1,Scalar r2) + {Check_Pointer(this); angle = r1 * r2; return *this;} + Radian& + operator*=(Scalar r) + {Check(this); angle *= r; return *this;} + + Radian& + Divide(Scalar r1,Scalar r2) + { + Check_Pointer(this); Verify(!Small_Enough(r2)); + angle = r1 / r2; return *this; + } + Radian& + operator/=(Scalar r) + {Check(this); Verify(!Small_Enough(r)); angle /= r; return *this;} + + // + // Template support + // + Radian& + Lerp( + const Radian &a, + const Radian &b, + Scalar t + ); + + // + // Support functions + // + static Scalar + Normalize(Scalar Value); + Radian& + Normalize(); + + friend ostream& + operator<<( + ostream& stream, + const Radian &radian + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Degree ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Degree + { + public: + Scalar + angle; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Degree *); + #endif + + // + // constructors + // + Degree() + {} + Degree(Scalar angle) + {this->angle = angle;} + + // + // Assignment operators + // + Degree& + operator=(const Degree °ree) + {Check(this); Check(°ree); angle = degree.angle; return *this;} + Degree& + operator=(Scalar angle) + {Check(this); this->angle = angle; return *this;} + Degree& + operator=(const Radian &radian) + { + Check(this); Check(&radian); + angle = radian.angle * DEG_PER_RAD; return *this; + } + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const Degree &angle + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + inline Radian& + Radian::operator=(const Degree& degree) + { + Check_Pointer(this); Check(°ree); + angle = degree.angle * RAD_PER_DEG; return *this; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SinCosPair ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SinCosPair + { + public: + Scalar + sine, + cosine; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile SinCosPair *); + #endif + + // + // Constructors + // + SinCosPair() + {} + SinCosPair(Scalar sin, Scalar cos) + {Check_Pointer(this); sine = sin; cosine = cos; Check(this);} + + // + // Assignment operators + // + SinCosPair& + operator=(const SinCosPair &pair) + { + Check_Pointer(this); Check(&pair); + sine = pair.sine; cosine = pair.cosine; return *this; + } + SinCosPair& + operator=(const Radian &radian); + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const SinCosPair &pair + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + inline Radian& + Radian::operator=(const SinCosPair& pair) + { + Check_Pointer(this); Check(&pair); + angle = Arctan(pair.sine,pair.cosine); return *this; + } + +#endif + diff --git a/CODE/RP/MUNGA/ANGLE.TCP b/CODE/RP/MUNGA/ANGLE.TCP new file mode 100644 index 0000000..ac9c6db --- /dev/null +++ b/CODE/RP/MUNGA/ANGLE.TCP @@ -0,0 +1,170 @@ +//===========================================================================// +// File: angle.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Tests for angle classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +//############################################################################# +//############################################################################# +// +Logical + Radian::TestClass() +{ + cout << "Starting Radian Test...\n"; + + const Radian a(1.25f); + Radian + b,c; + + Test(a); + + c = 0.0f; + Test(!c); + + Test(Normalize(3.1f) == 3.1f); + Test(Normalize(-3.1f) == -3.1f); + Scalar f = Normalize(PI+PI_OVER_2); + Test(Close_Enough(f,PI_OVER_2 - PI)); + f = Normalize(-PI-PI_OVER_2); + Test(Close_Enough(f,PI - PI_OVER_2)); + + c = a; + Test(c == a); + Test(c.angle == a); + Test(c == a.angle); + + b.Negate(c); + Test(b == -c.angle); + #if 0 + b = -c; + d.Add(b,c); + Test(d == b.angle + c.angle); + Test(a+b == a.angle + b.angle); + Test(a+c == a.angle + c.angle); + Test(a+1.25f == a.angle+1.25f); + Test(1.25f+c == 1.25f+c.angle); + + c = 1.5f; + d.Subtract(c,a); + Test(d == c.angle - a.angle); + Test(c-a == c.angle - a.angle); + Test(c-1.25f == c.angle - 1.25f); + Test(1.5f-a == 1.5f - a.angle); + Test(c-b == c.angle - b.angle); + + c = 2.5f; + d.Multiply(a,c); + Test(d == a.angle * c.angle); + Test(a*c == a.angle * c.angle); + Test(1.25f*c == 1.25f * c.angle); + Test(a*2.5f == a.angle * 2.5f); + Test(a*b == a.angle * b.angle); + + c = 2.0f; + d.Divide(a,c); + Test(d == a.angle / c.angle); + Test(a/c == a.angle / c.angle); + Test(1.25f/c == 1.25f / c.angle); + Test(a/2.0f == a.angle / 2.0f); + Test(a/b == a.angle / b.angle); + + b = a; + b += c; + b.Normalize(); + Test(b == 3.25f - TWO_PI); + b += 2.0f; + b.Normalize(); + Test(b == 5.25f - TWO_PI); + + b -= c; + b.Normalize(); + Test(b == 3.25f - TWO_PI); + b -= 2.0f; + b.Normalize(); + Test(b == 1.25f); + + b *= c; + b.Normalize(); + Test(b == 1.25f*2.0f); + b *= 2.0f; + b.Normalize(); + Test(b == 1.25f*2.0f*2.0f - TWO_PI); + + b = a*c; + b.Normalize(); + Test(b == 1.25f*2.0f); + b /= 2.0f; + b.Normalize(); + Test(b == 1.25f); + + b = -3.0f*PI_OVER_4; + c = 3.0f*PI_OVER_4; + Test(Lerp(b,c,0.25f) < b); + Test(Normalize(Lerp(b,c,0.75f)) > c); + #endif + + return True; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Degree::TestClass() +{ + cout << "Starting Degree test...\n"; + + const Degree a(DEG_PER_RAD); + Degree + b,c; + + Radian + r(1.0f),s; + + s = a; + Test(r == s); + b = r; + s = b; + Test(r == s); + c = DEG_PER_RAD; + s = c; + Test(r == s); + b = c; + s = b; + Test(r == s); + + return True; +} + +// +//############################################################################# +//############################################################################# +// +Logical + SinCosPair::TestClass() +{ + cout << "Starting SinCos test...\n"; + Radian + s,r(PI_OVER_2); + + SinCosPair a; + a = r; + + Test(Close_Enough(a.sine,1.0f)); + Test(Small_Enough(a.cosine)); + + s = a; + Test(s == r); + + return True; +} diff --git a/CODE/RP/MUNGA/APP.TCP b/CODE/RP/MUNGA/APP.TCP new file mode 100644 index 0000000..a669306 --- /dev/null +++ b/CODE/RP/MUNGA/APP.TCP @@ -0,0 +1,97 @@ +//===========================================================================// +// File: app.tst // +// Project: MUNGA Brick: Application // +// Contents: Interface specification for Application // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/12/94 ECH Added event utilities. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "app.thp" +#include "entity.thp" +#include "controls.thp" + +TestApplication::TestApplication(ResourceFile *resource_file): + Application(resource_file, (ApplicationID)0) +{ +} + +TestApplication::~TestApplication() +{ +} + +void + TestApplication::Initialize() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Create the network manager + //-------------------------------------------------------------------------- + // + application = this; + networkManager = MakeNetworkManager(); + Register_Object(networkManager); + +#if 0 + // + //-------------------------------------------------------------------------- + // Create the registry, load static object streams + //-------------------------------------------------------------------------- + // + registry = MakeRegistry(); + Register_Object(registry); + registry->LoadStaticObjectStreamResource(); + + // + //-------------------------------------------------------------------------- + // Create the controls manager + //-------------------------------------------------------------------------- + // + controlsManager = MakeControlsManager(); + Register_Object(controlsManager); + + // + //-------------------------------------------------------------------------- + // Create the intercom manager + //-------------------------------------------------------------------------- + // + intercomManager = MakeIntercomManager(); + Register_Object(intercomManager); +#endif + + // + //-------------------------------------------------------------------------- + // Add background tasks + //-------------------------------------------------------------------------- + // + ApplicationTask *application_task; + + application_task = new RoutePacketTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new ProcessEventTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new CompleteCyclesTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); +} + +void + TestApplication::Terminate() +{ + Check(this); + application = this; + networkManager->Shutdown(); + Application::Terminate(); +} + diff --git a/CODE/RP/MUNGA/APP.THP b/CODE/RP/MUNGA/APP.THP new file mode 100644 index 0000000..c96d6c9 --- /dev/null +++ b/CODE/RP/MUNGA/APP.THP @@ -0,0 +1,45 @@ +//===========================================================================// +// File: tstapp.hh // +// Project: MUNGA Brick: Application // +// Contents: Interface specification for Application // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 ECH Added event utilities. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(APP_THP) +# define APP_THP + +# if !defined(APP_HPP) +# include "app.hpp" +# endif + +# if !defined(RENDERER_THP) +# include "renderer.thp" +# endif + +# if !defined(VIDREND_HPP) +# include "vidrend.hpp" +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TestApplication ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class TestApplication: + public Application + { + public: + TestApplication(ResourceFile *resource_file); + ~TestApplication(); + + void + Initialize(); + void + Terminate(); + }; + +#endif diff --git a/CODE/RP/MUNGA/APPMGR.CPP b/CODE/RP/MUNGA/APPMGR.CPP new file mode 100644 index 0000000..39c29ff --- /dev/null +++ b/CODE/RP/MUNGA/APPMGR.CPP @@ -0,0 +1,131 @@ +#include +#pragma hdrstop + +#if !defined(APPMGR_HPP) +# include +#endif + +ApplicationManager::ApplicationManager(Scalar frame_rate): + Node(ApplicationManagerClassID), + runningApplications(this) +{ + frameRate = frame_rate; + frameDuration = 1.0f/frameRate; + Check_Fpu(); +} + +ApplicationManager::~ApplicationManager() +{ +} + +void + ApplicationManager::StartApplication(Application *new_app) +{ + Check(this); + Check(new_app); + + runningApplications.Add(new_app); + application = new_app; + new_app->Initialize(); +} + +// +//############################################################################# +// RunMissions +//############################################################################# +// +void + ApplicationManager::RunMissions() +{ + Check(this); + + SChainIteratorOf current_application(runningApplications); + +Start_Of_Frame: + current_application.First(); + Time end_of_frame = Now(); + end_of_frame += frameDuration; + #if defined(LAB_ONLY) + int bad_count = 0; + #endif + + if (frameDuration > 0.1f) + { + Fail("frameDuration has grown!\n"); + } + + // + //---------------------------------- + // Run all relevant foreground loops + //---------------------------------- + // + while ((application = current_application.ReadAndNext()) != NULL) + { + Check(application); + if (!application->ExecuteForeground(end_of_frame, frameDuration)) + { + if (!application->Shutdown()) + { + application->Terminate(); + Unregister_Object(application); + delete application; + } + } + } + + // + //----------------------------------------------------------------------- + // Run all relevant background loops until it is time for the next frame. + // If no applications remain, exit the whole loop + //----------------------------------------------------------------------- + // + current_application.First(); + application = current_application.GetCurrent(); + if (!application) + { + return; + } + + // + //------------------------------------------------------------------ + // Give each application a chance to do at least one background task + //------------------------------------------------------------------ + // +Background_Loop: + do { + Check(application); + application->ExecuteBackgroundTask(); + + // + // Move to the next application + // + current_application.Next(); + application = current_application.GetCurrent(); + } while (application); + + // + //--------------------------------------------------------------------- + // If time remains before the next frame is due, do another pass on the + // background tasks + //--------------------------------------------------------------------- + // + Time t2 = Now(); + if (t2 < end_of_frame) + { + current_application.First(); + application = current_application.GetCurrent(); + #if defined(LAB_ONLY) + if (end_of_frame - t2 > 0.1f) + { + DEBUG_STREAM << t2 << ',' << end_of_frame << endl; + if (++bad_count == 1000) + { + Fail("End-of-frame cannot be correctly calculated!"); + } + } + #endif + goto Background_Loop; + } + goto Start_Of_Frame; +} + diff --git a/CODE/RP/MUNGA/APPMGR.HPP b/CODE/RP/MUNGA/APPMGR.HPP new file mode 100644 index 0000000..bfe5cdc --- /dev/null +++ b/CODE/RP/MUNGA/APPMGR.HPP @@ -0,0 +1,33 @@ +#if !defined(APPMGR_HPP) +# define APPMGR_HPP + +# if !defined(APP_HPP) +# include +# endif + + class ApplicationManager: + public Node + { + public: + ApplicationManager(Scalar frame_rate); + ~ApplicationManager(); + + void + StartApplication(Application *new_app); + + void + RunMissions(); + + Scalar + GetFrameRate() + {Check(this); return frameRate;} + + protected: + Scalar + frameDuration, + frameRate; + SChainOf + runningApplications; + }; + +#endif diff --git a/CODE/RP/MUNGA/APPMSG.CPP b/CODE/RP/MUNGA/APPMSG.CPP new file mode 100644 index 0000000..fb16678 --- /dev/null +++ b/CODE/RP/MUNGA/APPMSG.CPP @@ -0,0 +1,87 @@ +//===========================================================================// +// File: cnslmsgs.cpp // +// Project: MUNGA Brick: // +// Contents: Console messages // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/02/95 ECH Initial coding. // +// 06/03/95 GAH Added corresponding Macintosh message defintions. // +// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(APPMSG_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~ Application__StateQueryMessage ~~~~~~~~~~~~~~~~~~~~~~~~ +Application__StateQueryMessage::Application__StateQueryMessage( + HostID requesting_host +): + NetworkClient::Message( + Application::StateQueryMessageID, + sizeof(Application__StateQueryMessage) + ) +{ + requestingHost = requesting_host; +} + +//~~~~~~~~~~~~~~~~~~~~~~ Application__RunMissionMessage ~~~~~~~~~~~~~~~~~~~~~~~ +Application__RunMissionMessage::Application__RunMissionMessage(): + NetworkClient::Message( + Application::RunMissionMessageID, + sizeof(Application__RunMissionMessage) + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~ Application__StopMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +Application__StopMissionMessage::Application__StopMissionMessage(Enumeration exit_code): + NetworkClient::Message( + Application::StopMissionMessageID, + sizeof(Application__StopMissionMessage) + ) +{ + exitCode = exit_code; +} + +//~~~~~~~~~~~~~~~~~~~~~~ Application__AbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +Application__AbortMissionMessage::Application__AbortMissionMessage(Enumeration exit_code): + NetworkClient::Message( + Application::AbortMissionMessageID, + sizeof(Application__AbortMissionMessage) + ) +{ + exitCode = exit_code; +} + +//~~~~~~~~~~~~~~~~~~~~ Application__SuspendMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +Application__SuspendMissionMessage::Application__SuspendMissionMessage(): + NetworkClient::Message( + Application::SuspendMissionMessageID, + sizeof(Application__SuspendMissionMessage) + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~ Application__ResumeMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +Application__ResumeMissionMessage::Application__ResumeMissionMessage(): + NetworkClient::Message( + Application::ResumeMissionMessageID, + sizeof(Application__ResumeMissionMessage) + ) +{ +} + +//============================================================================== diff --git a/CODE/RP/MUNGA/APPMSG.HPP b/CODE/RP/MUNGA/APPMSG.HPP new file mode 100644 index 0000000..d6d5301 --- /dev/null +++ b/CODE/RP/MUNGA/APPMSG.HPP @@ -0,0 +1,246 @@ +//===========================================================================// +// File: cnslmsgs.hpp // +// Project: MUNGA Brick: // +// Contents: Console messages // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/02/95 ECH Initial coding. // +// 06/03/95 GAH Added corresponding Macintosh message defintions. // +// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(APPMSG_HPP) +# define APPMSG_HPP + +#ifdef MAC +#pragma once +#endif + +#ifdef MAC +#include "NetworkEndpoint.h" +#include "Participant.h" +#else +#include +#endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Application IDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC + enum ApplicationMessageID + { + StateQueryMessageID = NetworkEndpoint::NextMessageID, + CheckLoadMessageID, + RunMissionMessageID, + StopMissionMessageID, + KeyCommandMessageID, + SuspendMissionMessageID, + ResumeMissionMessageID, + LoadMissionMessageID, + AbortMissionMessageID, + ApplicationNextMessageID + }; + + enum ApplicationID + { + RPL4, + BTL4, + BTW4 + }; + typedef ApplicationID ApplicationID; + + enum ExitCodeID + { + NullExitCodeID = 0, + AbortExitCodeID, + RunRedPlanetExitCodeID, + RunBattleTechExitCodeID, + RunSinglePlayerRedPlanetExitCodeID, + RunSinglePlayerBattleTechExitCodeID, + DisplayMainTestPatternExitCodeID, + DisplayAuxTestPatternExitCodeID, + TestPlasmaDisplayExitCodeID, + ResetRIOExitCodeID, + RunAudioTestExitCodeID, + RunNortonDiskDoctorExitCodeID, + CheckDiskUsageExitCodeID, + RefreshRedPlanetExitCodeID, + RefreshBattleTechExitCodeID, + ChangeScreenModeExitCodeID, + SoftwareResetExitCodeID, + ClearCrashlogExitCodeID, + KillSpoolFileExitCodeID, + RunRedPlanetCameraExitCodeID, + RunBattleTechCameraExitCodeID, + RunRedPlanetMissionReviewExitCodeID, + RunBattleTechMissionReviewExitCodeID + }; + typedef ExitCodeID ExitCodeID; +#endif + + //~~~~~~~~~~~~~~~~~~~ Application__StateQueryMessage ~~~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__StateQueryMessage: + public NetworkEndpoint::Message + { + public: + Application__StateQueryMessage(HostID requesting_host); + + long + GetRequestingHostID() + {return requestingHost.value();} + + private: + HostID + requestingHost; + }; +#pragma options align=reset +#else + class Application__StateQueryMessage: + public NetworkClient::Message + { + public: + Application__StateQueryMessage(HostID requesting_host); + + HostID + GetRequestingHostID() + {return requestingHost;} + + private: + HostID + requestingHost; + }; +#endif + + //~~~~~~~~~~~~~~~~~~~~ Application__RunMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__RunMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__RunMissionMessage(); + }; +#pragma options align=reset +#else + class Application__RunMissionMessage: + public NetworkClient::Message + { + public: + Application__RunMissionMessage(); + }; +#endif + + //~~~~~~~~~~~~~~~~~~~~ Application__StopMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__StopMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__StopMissionMessage(ExitCodeID exit_code); + + ExitCodeID + GetExitCodeID() + {return((ExitCodeID) exitCode.value());} + + private: + LEDWORD + exitCode; + }; +#pragma options align=reset +#else + class Application__StopMissionMessage: + public NetworkClient::Message + { + public: + Application__StopMissionMessage(Enumeration exit_code); + + Enumeration + GetExitCode() + {return(exitCode);} + + private: + Enumeration + exitCode; + }; +#endif + + //~~~~~~~~~~~~~~~~~~~~ Application__AbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__AbortMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__AbortMissionMessage(ExitCodeID exit_code); + + ExitCodeID + GetExitCode() + {return((ExitCodeID) exitCode.value());} + + private: + LEDWORD + exitCode; + }; +#pragma options align=reset +#else + class Application__AbortMissionMessage: + public NetworkClient::Message + { + public: + Application__AbortMissionMessage(Enumeration exit_code); + + Enumeration + GetExitCode() + {return(exitCode);} + + private: + Enumeration + exitCode; + }; +#endif + + //~~~~~~~~~~~~~~~~~~ Application__SuspendMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__SuspendMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__SuspendMissionMessage(); + }; +#pragma options align=reset +#else + class Application__SuspendMissionMessage: + public NetworkClient::Message + { + public: + Application__SuspendMissionMessage(); + }; +#endif + + //~~~~~~~~~~~~~~~~~~~ Application__ResumeMissionMessage ~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__ResumeMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__ResumeMissionMessage(); + }; +#pragma options align=reset +#else + class Application__ResumeMissionMessage: + public NetworkClient::Message + { + public: + Application__ResumeMissionMessage(); + }; +#endif + +#endif diff --git a/CODE/RP/MUNGA/APPTASK.CPP b/CODE/RP/MUNGA/APPTASK.CPP new file mode 100644 index 0000000..3d03c77 --- /dev/null +++ b/CODE/RP/MUNGA/APPTASK.CPP @@ -0,0 +1,206 @@ +//===========================================================================// +// File: apptask.cpp // +// Project: MUNGA Brick: Application // +// Contents: Interface specification for Application // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/24/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(APPTASK_HPP) +# include +#endif + +#if !defined(RENDERER_HPP) +# include +#endif + +#if !defined(AUDREND_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#if !defined(NTTMGR_HPP) +# include +#endif + +#if !defined(GAUGEREND_HPP) +# include +#endif + +#if defined(TRACE_COMPLETE_CYCLES) + BitTrace Complete_Cycles("Complete Cycles"); +#endif + +#if defined(TRACE_DEATH_ROW) + BitTrace Death_Row("Death Row"); +#endif + +//############################################################################# +//########################### ApplicationTask ########################### +//############################################################################# + +ApplicationTask::ApplicationTask(ClassID class_ID): + Component(class_ID) +{ +} + +ApplicationTask::~ApplicationTask() +{ +} + +//############################################################################# +//########################### BackgroundTasks ########################### +//############################################################################# + +BackgroundTasks::BackgroundTasks(): + taskSocket(NULL) +{ + taskIterator = new SChainIteratorOf(&taskSocket); + Register_Object(taskIterator); +} + +BackgroundTasks::~BackgroundTasks() +{ + Check(taskIterator); + taskIterator->DeletePlugs(); + Unregister_Object(taskIterator); + delete taskIterator; +} + +Logical + BackgroundTasks::TestInstance() const +{ + Component::TestInstance(); + Check(&taskSocket); + Check(taskIterator); + return True; +} + +void + BackgroundTasks::AddTask(ApplicationTask *task) +{ + Check(this); + Check(task); + taskSocket.Add(task); +} + +void + BackgroundTasks::Execute() +{ + Check(this); + + Check(taskIterator); + if (taskIterator->GetCurrent() == NULL) + { + taskIterator->First(); + } + + ApplicationTask *task = taskIterator->GetCurrent(); + Check(task); + task->Execute(); + taskIterator->Next(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManagerTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + NetworkManagerTask::Execute() +{ + Check(this); + Check(application); + Check(application->GetNetworkManager()); + application->GetNetworkManager()->ExecuteBackground(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RoutePacketTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + RoutePacketTask::Execute() +{ + Check(this); + + Check(application); + Check(application->GetNetworkManager()); + application->GetNetworkManager()->RoutePacket(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ProcessEventTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + ProcessEventTask::Execute() +{ + Check(this); + Check(application); + application->ProcessOneEvent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + AudioRendererTask::Execute() +{ + Check(this); + Check(application); + if (application->GetAudioRenderer() != NULL) + { + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->ExecuteBackground(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + GaugeRendererTask::Execute() +{ + Check(this); + Check(application); + if (application->GetGaugeRenderer() != NULL) + { + Check(application->GetGaugeRenderer()); + application->GetGaugeRenderer()->ExecuteBackground(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompleteCyclesTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + CompleteCyclesTask::Execute() +{ + SET_COMPLETE_CYCLES(); + + Check(this); + Check(application); + Check(application->GetRendererManager()); + application->GetRendererManager()->CompleteCycles(); + + CLEAR_COMPLETE_CYCLES(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FryDeathRowTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + FryDeathRowTask::Execute() +{ + SET_DEATH_ROW(); + + Check(this); + Check(application); + Check(application->GetEntityManager()); + application->GetEntityManager()->FryDeathRow(); + + CLEAR_DEATH_ROW(); +} + diff --git a/CODE/RP/MUNGA/APPTASK.HPP b/CODE/RP/MUNGA/APPTASK.HPP new file mode 100644 index 0000000..072cdb8 --- /dev/null +++ b/CODE/RP/MUNGA/APPTASK.HPP @@ -0,0 +1,179 @@ +//===========================================================================// +// File: apptask.hpp // +// Project: MUNGA Brick: Application // +// Contents: Interface specification for Application // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/24/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(APPTASK_HPP) +# define APPTASK_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(CMPNNT_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if defined(TRACE_COMPLETE_CYCLES) + extern BitTrace Complete_Cycles; +# define SET_COMPLETE_CYCLES() Complete_Cycles.Set() +# define CLEAR_COMPLETE_CYCLES() Complete_Cycles.Clear() +# else +# define SET_COMPLETE_CYCLES() +# define CLEAR_COMPLETE_CYCLES() +# endif + +# if defined(TRACE_DEATH_ROW) + extern BitTrace Death_Row; +# define SET_DEATH_ROW() Death_Row.Set() +# define CLEAR_DEATH_ROW() Death_Row.Clear() +# else +# define SET_DEATH_ROW() +# define CLEAR_DEATH_ROW() +# endif + + //########################################################################## + //####################### ApplicationTask ############################ + //########################################################################## + + class ApplicationTask: + public Component + { + public: + ApplicationTask(ClassID class_ID = ApplicationTaskClassID); + ~ApplicationTask(); + }; + + //########################################################################## + //####################### BackgroundTasks ############################ + //########################################################################## + + class BackgroundTasks: + public Component + { + public: + BackgroundTasks(); + ~BackgroundTasks(); + + Logical + TestInstance() const; + + void + AddTask(ApplicationTask *task); + + void + Execute(); + + private: + SChainOf + taskSocket; + SChainIteratorOf + *taskIterator; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManagerTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class NetworkManagerTask: + public ApplicationTask + { + public: + NetworkManagerTask() {} + ~NetworkManagerTask() {} + + void + Execute(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ RoutePacketTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class RoutePacketTask: + public ApplicationTask + { + public: + RoutePacketTask() {} + ~RoutePacketTask() {} + + void + Execute(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ ProcessEventTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class ProcessEventTask: + public ApplicationTask + { + public: + ProcessEventTask() {} + ~ProcessEventTask() {} + + void + Execute(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioRendererTask: + public ApplicationTask + { + public: + AudioRendererTask() {} + ~AudioRendererTask() {} + + void + Execute(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class GaugeRendererTask: + public ApplicationTask + { + public: + GaugeRendererTask() {} + ~GaugeRendererTask() {} + + void + Execute(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ CompleteCyclesTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class CompleteCyclesTask: + public ApplicationTask + { + public: + CompleteCyclesTask() {} + ~CompleteCyclesTask() {} + + void + Execute(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FryDeathRowTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class FryDeathRowTask: + public ApplicationTask + { + public: + FryDeathRowTask() {} + ~FryDeathRowTask() {} + + void + Execute(); + }; + +#endif + diff --git a/CODE/RP/MUNGA/AUDCMP.HPP b/CODE/RP/MUNGA/AUDCMP.HPP new file mode 100644 index 0000000..dcd9bd2 --- /dev/null +++ b/CODE/RP/MUNGA/AUDCMP.HPP @@ -0,0 +1,751 @@ +//===========================================================================// +// File: audcmp.hpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDCMP_HPP) +# define AUDCMP_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + +# if !defined(AUDLOC_HPP) +# include +# endif + +# if !defined(AVERAGE_HPP) +# include +# endif + +# if !defined(AUDTIME_HPP) +# include +# endif + + //########################################################################## + //######################## AudioMessageWatcher ####################### + //########################################################################## + + class AudioMessageWatcher: + public AudioComponent + { + public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor + //----------------------------------------------------------------------- + // + AudioMessageWatcher( + PlugStream *stream, + Entity *entity + ); + ~AudioMessageWatcher(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // MessageTapScanCallback + //----------------------------------------------------------------------- + // + void + MessageTapScanCallback( + Receiver::Message *message, + Receiver *receiver + ); + + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + virtual Logical + DoesMessageMatch(Receiver::Message*) + {return True;} + + // + //----------------------------------------------------------------------- + // Private Data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlID controlID; + AudioControlValue controlValue; + + MessageTap *messageTap; + + #if DEBUG_LEVEL>0 + Receiver *verifyReceiver; + Receiver::MessageID verifyMessageID; + #endif + }; + + //########################################################################## + //############### AudioControlsButtonMessageWatcher ################## + //########################################################################## + + class AudioControlsButtonMessageWatcher: + public AudioMessageWatcher + { + public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor + //----------------------------------------------------------------------- + // + AudioControlsButtonMessageWatcher( + PlugStream *stream, + Entity *entity + ); + ~AudioControlsButtonMessageWatcher(); + + private: + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + Logical + DoesMessageMatch(Receiver::Message*); + }; + + //########################################################################## + //######################### AudioControlSend ######################### + //########################################################################## + + class AudioControlSend: + public AudioComponent + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlSend( + PlugStream *stream, + Entity *entity + ); + ~AudioControlSend(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + }; + + //########################################################################## + //####################### AudioControlSplitter ####################### + //########################################################################## + + class AudioControlSplitter: + public AudioComponent + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlSplitter( + PlugStream *stream, + Entity *entity + ); + void + AudioControlSplitterX(Entity *entity); + ~AudioControlSplitter(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SChainOf audioComponentSocket; + }; + + //########################################################################## + //####################### AudioControlMixer ########################## + //########################################################################## + + #define AUDIO_CONTROL_MIXER_MAX_CONTROLS (4) + + class AudioControlMixer: + public AudioComponent + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlMixer( + PlugStream *stream, + Entity *entity + ); + void + AudioControlMixerX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID first_input_control_ID, + AudioControlID last_input_control_ID, + AudioControlID output_control_ID + ); + ~AudioControlMixer(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlValue + controlValueArray[AUDIO_CONTROL_MIXER_MAX_CONTROLS]; + AudioControlID + firstInputControlID; + int + numberOfInputs; + AudioControlID + outputControlID; + }; + + //########################################################################## + //###################### AudioControlMultiplier ###################### + //########################################################################## + + #define AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS (4) + + class AudioControlMultiplier: + public AudioComponent + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlMultiplier( + PlugStream *stream, + Entity *entity + ); + void + AudioControlMultiplierX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID first_input_control_ID, + AudioControlID last_input_control_ID, + AudioControlID output_control_ID + ); + ~AudioControlMultiplier(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlValue + controlValueArray[AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS]; + AudioControlID + firstInputControlID; + int + numberOfInputs; + AudioControlID + outputControlID; + }; + + //########################################################################## + //######################## AudioControlSmoother ###################### + //########################################################################## + + class AudioControlSmoother: + public AudioComponent + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlSmoother( + PlugStream *stream, + Entity *entity + ); + void + AudioControlSmootherX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID control_ID + ); + ~AudioControlSmoother(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + AverageOf + audioControlAverage; + AudioControlID + controlID; + }; + + //########################################################################## + //####################### AudioResourceSelector ###################### + //########################################################################## + + class AudioResourceIndex; + + class AudioResourceSelector: + public AudioComponent + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioResourceSelector( + PlugStream *stream, + Entity *entity + ); + void + AudioResourceSelectorX( + AudioSource *audio_source, + Entity *entity, + AudioResourceIndex *audio_resource_index, + AudioControlID control_ID, + AudioControlValue min_control_value, + AudioControlValue max_control_value, + Logical dump_value + ); + ~AudioResourceSelector(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioSourceSocket; + + AudioResourceIndex + *audioResourceIndex; + + AudioControlID + controlID; + AudioControlValue + minControlValue, + maxControlValue; + + Logical + dumpValue; + }; + + //########################################################################## + //######################## AudioSampleAndHold ######################## + //########################################################################## + + class AudioSampleAndHold: + public AudioComponent + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioSampleAndHold( + PlugStream *stream, + Entity *entity + ); + void + AudioSampleAndHoldX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID audio_control_ID, + const AudioTime &sample_duration, + Scalar min_value, + Scalar max_value + ); + ~AudioSampleAndHold(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Execute + //-------------------------------------------------------------------- + // + void + Execute(); + + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //----------------------------------------------------------------------- + // Private methods + //----------------------------------------------------------------------- + // + void + SampleAndHold(); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlID + audioControlID; + AudioControlValue + minValue, + maxValue, + currentValue; + AudioTime + nextSampleTime, + sampleDuration; + }; + + //########################################################################## + //############################# AudioLFO ############################# + //########################################################################## + + enum AudioLFOWaveForm + { + SinusoidalAudioLFOWaveForm = 0, + TriangularAudioLFOWaveForm = 1 + }; + + inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + AudioLFOWaveForm *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const AudioLFOWaveForm *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + + class AudioLFO: + public AudioComponent + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioLFO( + PlugStream *stream, + Entity *entity + ); + void + AudioLFOX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID audio_control_ID, + AudioLFOWaveForm wave_form, + Scalar the_period, + AudioControlValue min_value, + AudioControlValue max_value, + Logical dump_value + ); + ~AudioLFO(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Execute + //-------------------------------------------------------------------- + // + void + Execute(); + + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + // + //----------------------------------------------------------------------- + // Private methods + //----------------------------------------------------------------------- + // + void + Generate(); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlID + audioControlID; + AudioLFOWaveForm + waveForm; + AudioControlValue + minValue, + maxValue; + AudioTime + period; + AudioTime + startTime; + Logical + dumpValue; + }; + +#endif diff --git a/CODE/RP/MUNGA/AUDENT.CPP b/CODE/RP/MUNGA/AUDENT.CPP new file mode 100644 index 0000000..6d9a240 --- /dev/null +++ b/CODE/RP/MUNGA/AUDENT.CPP @@ -0,0 +1,203 @@ +//===========================================================================// +// File: audent.cpp // +// Project: MUNGA Brick: Model Manager // +// Contents: Implementation details of audio entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/20/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDENT_HPP) +# include +#endif + +#if !defined(JMOVER_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +//############################################################################# +//########################### AudioEntity ############################### +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation + AudioEntity::ClassDerivations( + Explosion::ClassDerivations, + "AudioEntity" + ); + +AudioEntity::SharedData + AudioEntity::DefaultData( + AudioEntity::ClassDerivations, + AudioEntity::MessageHandlers, + AudioEntity::AttributeIndex, + AudioEntity::StateCount, + (Entity::MakeHandler)AudioEntity::Make + ); + +// +//############################################################################# +//############################################################################# +// +AudioEntity::AudioEntity( + AudioEntity::MakeMessage *creation_message, + AudioEntity::SharedData &shared_data +): + Explosion(creation_message, shared_data), + parentEntitySocket(NULL) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + + // + // Get the parent entity + // + Entity *parent_entity; + + parent_entity = + application->GetHostManager()->GetEntityPointer( + creation_message->parentEntityID + ); + if (parent_entity != NULL) + { + parentEntitySocket.Add(parent_entity); + parentEntitySegment = creation_message->parentEntitySegment; + } + else + { + parentEntitySegment = NULL; + } + + // + // Set simulation + // + SetPerformance(&AudioEntity::AudioEntitySimulation); + SetValidFlag(); +} + +// +//############################################################################# +//############################################################################# +// +AudioEntity::~AudioEntity() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioEntity::TestInstance() const +{ + if (!IsDerivedFrom(ClassDerivations)) + { + return False; + } + Check(&parentEntitySocket); + if (parentEntitySegment != NULL) + { + Check(parentEntitySegment); + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +AudioEntity* + AudioEntity::Make(AudioEntity::MakeMessage *creation_message) +{ + return new AudioEntity(creation_message); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioEntity::AudioEntitySimulation(Scalar time_slice) +{ + Check(this); + + // + // Get the parent entity, if it does not exist, condemn to death row + // + Entity *parent_entity; + + if ((parent_entity = parentEntitySocket.GetCurrent()) == NULL) + { + CondemnToDeathRow(); + return; + } + + // + // Get the orign of the parent entities segment + // + JointedMover *jointed_mover; + + Verify(parent_entity->IsDerivedFrom(JointedMover::ClassDerivations)); + jointed_mover = Cast_Object(JointedMover*, parent_entity); + Check(jointed_mover); + Check(parentEntitySegment); + jointed_mover->GetSegmentToWorld( + *parentEntitySegment, + &localToWorld + ); + + // + // Set the origin of this entity + // + localOrigin = localToWorld; + updateOrigin = localOrigin; + + // + // Call inherited simulation + // + Explosion::ExplosionSimulation(time_slice); +} + +//############################################################################# +//##################### AudioEntity__MakeMessage ######################## +//############################################################################# + +AudioEntity__MakeMessage::AudioEntity__MakeMessage( + ResourceDescription::ResourceID resource_ID, + Entity *parent_entity, + EntitySegment *parent_entity_segment +): + Explosion::MakeMessage( + AudioEntity::MakeMessageID, + sizeof(AudioEntity__MakeMessage), + RegisteredClass::AudioEntityClassID, + EntityID::Null, + resource_ID, + Entity::HermitInstance|Entity::DynamicFlag, + parent_entity->localOrigin, + parent_entity->GetEntityID(), + EntityID::Null + ), + parentEntityID(parent_entity->GetEntityID()), + parentEntitySegment(parent_entity_segment) +{ +} + diff --git a/CODE/RP/MUNGA/AUDENT.HPP b/CODE/RP/MUNGA/AUDENT.HPP new file mode 100644 index 0000000..0ac2788 --- /dev/null +++ b/CODE/RP/MUNGA/AUDENT.HPP @@ -0,0 +1,118 @@ +//===========================================================================// +// File: audent.hpp // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for audio entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/20/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDENT_HPP) +# define AUDENT_HPP + +# if !defined(EXPLODE_HPP) +# include +# endif + +# if !defined(SEGMENT_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + + //########################################################################## + //########################## AudioEntity ############################# + //########################################################################## + + class AudioEntity__MakeMessage; + + class AudioEntity: + public Explosion + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + typedef AudioEntity__MakeMessage + MakeMessage; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + AudioEntity( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~AudioEntity(); + + static AudioEntity* + Make(MakeMessage *creation_message); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (AudioEntity::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + AudioEntitySimulation(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + SlotOf + parentEntitySocket; + EntitySegment + *parentEntitySegment; + }; + + //########################################################################## + //#################### AudioEntity__MakeMessage ###################### + //########################################################################## + + class AudioEntity__MakeMessage: + public Explosion::MakeMessage + { + public: + AudioEntity__MakeMessage( + ResourceDescription::ResourceID resource_ID, + Entity *parent_entity, + EntitySegment *parent_entity_segment + ); + + EntityID + parentEntityID; + EntitySegment + *parentEntitySegment; + }; + +#endif diff --git a/CODE/RP/MUNGA/AUDIO.CPP b/CODE/RP/MUNGA/AUDIO.CPP new file mode 100644 index 0000000..ce5dc75 --- /dev/null +++ b/CODE/RP/MUNGA/AUDIO.CPP @@ -0,0 +1,488 @@ +//===========================================================================// +// File: audio.hh // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDIO_HPP) +# include +#endif + +#if !defined(AUDREND_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Audio Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const Scalar AudioDoubleTriggerCutoff = 0.2f; + +const AudioControlValue MaxAudioVolume = 1.0f; +const AudioControlValue MinAudioVolume = 0.0f; +const AudioControlValue LowAudioVolumeThreshold = 0.3f; + +const AudioControlValue MaxAudioBrightness = 1.0f; +const AudioControlValue MinAudioBrightness = 0.0f; + +const AudioControlValue MaxAudioAttack = 1.0f; +const AudioControlValue MinAudioAttack = 0.0f; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioHead::AudioHead(): + headEntitySocket(NULL) +{ + // + // Start frame counter at 0, other counts should be at + // NullAudioFrameCount + // + audioFrameCount = 0; + + // + // Other audio parameters + // + clippingRadius = 100.0f; + distanceBetweenEars = 1.0f; + amplitudeRollOffExponent = 1.0f; + amplitudeRollOffKnee = 10.0f, + amplitudeRollOffDistanceScale = 0.05f; + highFrequencyRollOffExponent = 0.5f; + highFrequencyRollOffKnee = 10.0f; + highFrequencyRollOffDistanceScale = 0.05f; + reverbToDryRatio = 0.1f; + audioSoundSpeed = 345.0f; + audioDopplerConstant = 20.0f; + sourceCompressionExponent = 0.5f; + sourceCompressionScale = 0.5f; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +AudioHead::~AudioHead() +{ + Check(this); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioHead::TestInstance() const +{ + Check(&headEntitySocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::LinkToEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + // Remove existing entity, add new one + // + if (headEntitySocket.GetCurrent() != NULL) + { + headEntitySocket.Remove(); + } + headEntitySocket.Add(entity); + + #if 0 + // + // Make the new clipping sphere + // + clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition); + #endif +} + +// +//############################################################################# +//############################################################################# +// +LinearMatrix + AudioHead::GetEarToWorld() +{ + Check(this); + + Entity *entity = headEntitySocket.GetCurrent(); + Check(entity); + return entity->localToWorld; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::Execute() +{ + Check(this); + + // + // Increment frame counter + // + audioFrameCount++; + Verify(audioFrameCount < LONG_MAX); + + #if 0 + // + // Get the entity + // + Entity *entity = headEntitySocket.GetCurrent(); + Check(entity); + + // + // Make the new clipping sphere + // + clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::DefineClippingSphere(Scalar radius) +{ + Check(this); + + clippingRadius = radius; + + #if 0 + // + // Get entity position + // + Entity *entity; + Point3D position(0.0f, 0.0f, 0.0f); + + if ((entity = headEntitySocket.GetCurrent()) != NULL) + { + Check(entity); + position = entity->localOrigin.linearPosition; + } + + // + // Make the new clipping sphere + // + clippingSphere.SetCurrentOrigin(position); + clippingSphere.SetReferenceRadius(radius); + #endif +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioHead::IsPointClipped(const Point3D &point) +{ + Check(this); + + Entity + *entity; + Vector3D + difference; + + entity = headEntitySocket.GetCurrent(); + Check(entity); + difference.Subtract(entity->localOrigin.linearPosition, point); + return difference.LengthSquared() > clippingRadius*clippingRadius; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlDopplerEffect( + Scalar doppler_constant, + Scalar sound_speed + ) +{ + Check(this); + audioDopplerConstant = doppler_constant; + audioSoundSpeed = sound_speed; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlAmplitudeRollOff( + Scalar exponent, + Scalar amplitude_rolloff_knee, + Scalar distance_scale + ) +{ + Check(this); + amplitudeRollOffExponent = exponent; + amplitudeRollOffKnee = amplitude_rolloff_knee; + amplitudeRollOffDistanceScale = distance_scale; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlHighFrequencyRollOff( + Scalar exponent, + Scalar high_frequency_rolloff_knee, + Scalar distance_scale + ) +{ + Check(this); + highFrequencyRollOffExponent = exponent; + highFrequencyRollOffKnee = high_frequency_rolloff_knee; + highFrequencyRollOffDistanceScale = distance_scale; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlSourceCompression( + Scalar exponent, + Scalar scale + ) +{ + Check(this); + sourceCompressionExponent = exponent; + sourceCompressionScale = scale; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::SetPositionalCulling(Logical) +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +const Receiver::HandlerEntry + AudioComponent::MessageHandlerEntries[]= +{ + { + AudioComponent::ReceiveControlMessageID, + "ReceiveControl", + (AudioComponent::Handler)&AudioComponent::ReceiveControlMessageHandler + } +}; + +AudioComponent::MessageHandlerSet + AudioComponent::MessageHandlers( + ELEMENTS(AudioComponent::MessageHandlerEntries), + AudioComponent::MessageHandlerEntries, + Component::MessageHandlers + ); + +// +//############################################################################# +//############################################################################# +// +Derivation + AudioComponent::ClassDerivations( + Component::ClassDerivations, + "AudioComponent" + ); + +AudioComponent::SharedData + AudioComponent::DefaultData( + AudioComponent::ClassDerivations, + AudioComponent::MessageHandlers + ); + +// +//############################################################################# +//############################################################################# +// +AudioComponent::AudioComponent( + PlugStream *stream, + SharedData &shared_data +): + Component(stream, shared_data), + audioWatcherSocket(NULL) +{ + nextExecuteWatcherFrame = NullAudioFrameCount; +} + +// +//############################################################################# +//############################################################################# +// +AudioComponent::~AudioComponent() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioComponent::TestInstance() const +{ + if (!IsDerivedFrom(ClassDerivations)) + { + return False; + } + Check(&audioWatcherSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::ExecuteWatchers() +{ + Check(this); + + // + // Execute watchers if this is the next watcher frame + // + AudioFrameCount + audio_frame_count; + + Check(application); + Check(application->GetAudioRenderer()); + audio_frame_count = application->GetAudioRenderer()->GetAudioFrameCount(); + if (nextExecuteWatcherFrame <= audio_frame_count) + { + nextExecuteWatcherFrame = audio_frame_count + DefaultAudioFrameDelay; + + // + // Execute watchers + // + ChainIteratorOf + iterator(&audioWatcherSocket); + Component + *component; + + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + component->Execute(); + } + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::Execute() +{ + Check(this); + ExecuteWatchers(); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::ReceiveControl( + AudioControlID, + AudioControlValue + ) +{ + Fail("AudioComponent::ReceiveControl - Should never reach here"); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::PostReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + ReceiveControlMessage + message(control_ID, control_value); + + Check(application); + // ECH 1/26/96 - application->Post(HighEventPriority, this, &message); + application->Post(DefaultEventPriority, this, &message); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::ReceiveControlMessageHandler(ReceiveControlMessage *message) +{ + Check(this); + Check(message); + ReceiveControl(message->controlID, message->controlValue); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~~~~ + + +AudioComponent__ReceiveControlMessage::AudioComponent__ReceiveControlMessage( + AudioControlID control_ID, + AudioControlValue control_value +): + Receiver::Message( + AudioComponent::ReceiveControlMessageID, + sizeof(AudioComponent__ReceiveControlMessage) + ) +{ + controlID = control_ID; + controlValue = control_value; +} + diff --git a/CODE/RP/MUNGA/AUDIO.HPP b/CODE/RP/MUNGA/AUDIO.HPP new file mode 100644 index 0000000..062ac5c --- /dev/null +++ b/CODE/RP/MUNGA/AUDIO.HPP @@ -0,0 +1,687 @@ +//===========================================================================// +// File: audio.hpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDIO_HPP) +# define AUDIO_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(ENTITY_HPP) +# include +# endif + +# if !defined(SPHERE_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + + class PlugStream; + + // + //-------------------------------------------------------------------------- + // Support types + //-------------------------------------------------------------------------- + // + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef long AudioTick; + typedef long AudioDivisionsPerBeat; + typedef long AudioTempo; + + typedef long AudioFrameCount; + const AudioFrameCount NullAudioFrameCount = -1; + const AudioFrameCount DefaultAudioFrameDelay = 2; + + extern const Scalar AudioDoubleTriggerCutoff; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Resource types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef int AudioResourceID; + typedef int AudioVoiceCount; + typedef Scalar AudioRadiationProfile; + typedef Scalar AudioPitchCents; + + enum AudioRenderType + { + TransientAudioRenderType = 0, + SustainedAudioRenderType = 1 + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + enum AudioRepresentation + { + InternalAudioRepresentation = 0, + ExternalAudioRepresentation = 1 + }; + + #define AUDIO_SOURCE_PRIORITY_COUNT (5) + enum AudioSourcePriority + { + MinAudioSourcePriority = 0, + LowAudioSourcePriority = 1, + MedAudioSourcePriority = 2, + HighAudioSourcePriority = 3, + MaxAudioSourcePriority = 4 + }; + + enum AudioSourceState + { + StoppedAudioSourceState = 0, + DormantAudioSourceState = 1, + RunningAudioSourceState = 2, + SuspendedAudioSourceState = 3 + }; + + enum AudioSourceMixPresence + { + ManualAudioSourceMixPresence = 0, + MaxAudioSourceMixPresence = 1, + HighAudioSourceMixPresence = 2, + MedAudioSourceMixPresence = 3, + LowAudioSourceMixPresence = 4, + MinAudioSourceMixPresence = 5 + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + enum AudioControlID + { + NullAudioControlID = 0, + StartAudioControlID, + StopAudioControlID, + VolumeAudioControlID, + PitchAudioControlID, + BrightnessAudioControlID, + AttackVolumeAudioControlID, + AttackTimeAudioControlID, + NoteAudioControlID, + IdleAudioControlID, + DurationAudioControlID, + FlushMessagesAudioControlID, + TempoAudioControlID, + AudioControlIDCount + }; + + typedef Scalar AudioControlValue; + + extern const AudioControlValue MaxAudioVolume; + extern const AudioControlValue MinAudioVolume; + extern const AudioControlValue LowAudioVolumeThreshold; + + extern const AudioControlValue MaxAudioBrightness; + extern const AudioControlValue MinAudioBrightness; + + extern const AudioControlValue MaxAudioAttack; + extern const AudioControlValue MinAudioAttack; + + #if 0 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioClippingSphere SIGNATURED + { + public: + AudioClippingSphere(); + ~AudioClippingSphere(); + + void + SetReferenceRadius(Scalar radius); + void + SetCurrentOrigin(const Point3D &origin); + void + SetCurrentScale(Scalar scale); + Logical + Contains(const Point3D &point) const; + + private: + Scalar + referenceRadius; + Sphere + currentSphere; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere inlines ~~~~~~~~~~~~~~~~~~~~~~ + + inline AudioClippingSphere::AudioClippingSphere(): + referenceRadius(100.0f), + currentSphere(0.0f, 0.0f, 0.0f, 100.0f) + { + } + + inline AudioClippingSphere::~AudioClippingSphere() + { + } + + inline void + AudioClippingSphere::SetReferenceRadius(Scalar radius) + { + Check(this); + referenceRadius = radius; + currentSphere.radius = radius; + } + + inline void + AudioClippingSphere::SetCurrentOrigin(const Point3D &origin) + { + Check(this); + currentSphere.center = origin; + } + + inline void + AudioClippingSphere::SetCurrentScale(Scalar scale) + { + Check(this); + currentSphere.radius = scale * referenceRadius; + } + + inline Logical + AudioClippingSphere::Contains(const Point3D &point) const + { + Check(this); + return currentSphere.Contains(point); + } + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioSource; + + class AudioHead SIGNATURED + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioHead(); + ~AudioHead(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // Get current frame of audio simulation + //----------------------------------------------------------------------- + // + AudioFrameCount + GetAudioFrameCount() + {return audioFrameCount;} + + // + //----------------------------------------------------------------------- + // Sets the location and orientation of the head + //----------------------------------------------------------------------- + // + virtual void + LinkToEntity(Entity *entity); + Entity* + GetHeadEntity(); + + // + //----------------------------------------------------------------------- + // Get the ear to world linear matrix + //----------------------------------------------------------------------- + // + virtual LinearMatrix + GetEarToWorld(); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + virtual void + Execute(); + + // + //----------------------------------------------------------------------- + // Sets the distance between ears. Expressed in meters. + //----------------------------------------------------------------------- + // + void + SetDistanceBetweenEars(Scalar distance) + {distanceBetweenEars = distance;} + Scalar + GetDistanceBetweenEars() + {return distanceBetweenEars;} + + // + //----------------------------------------------------------------------- + // Controls Doppler effects + //----------------------------------------------------------------------- + // + void + ControlDopplerEffect( + Scalar doppler_constant, + Scalar sound_speed + ); + Scalar + GetAudioSoundSpeed() + {return audioSoundSpeed;} + AudioPitchCents + GetAudioDopplerConstant() + {return audioDopplerConstant;} + + // + //----------------------------------------------------------------------- + // Reverb scaling + //----------------------------------------------------------------------- + // + void + SetReverbToDryRatio(Scalar ratio) + {reverbToDryRatio = ratio;} + Scalar + GetReverbToDryRatio() + {return reverbToDryRatio;} + + // HACK + void + SetGlobalReverbScale(Scalar global_reverb_scale) + {globalReverbScale = global_reverb_scale;} + Scalar + GetGlobalReverbScale() + {return globalReverbScale;} + + // + //----------------------------------------------------------------------- + // Controls the attenuation of an audio source with respect to its + // distance from the head. + //----------------------------------------------------------------------- + // + void + ControlAmplitudeRollOff( + Scalar exponent, + Scalar amplitude_rolloff_knee, + Scalar distance_scale + ); + Scalar + GetAmplitudeRollOffExponent() + {return amplitudeRollOffExponent;} + Scalar + GetAmplitudeRollOffKnee() + {return amplitudeRollOffKnee;} + Scalar + GetAmplitudeRollOffDistanceScale() + {return amplitudeRollOffDistanceScale;} + + // + //----------------------------------------------------------------------- + // Controls the attenuation of the high frequencies + // of an audio source with respect to its distance from + // the head. + //----------------------------------------------------------------------- + // + void + ControlHighFrequencyRollOff( + Scalar exponent, + Scalar high_frequency_rolloff_knee, + Scalar distance_scale + ); + Scalar + GetHighFrequencyRollOffExponent() + {return highFrequencyRollOffExponent;} + Scalar + GetHighFrequencyRollOffKnee() + {return highFrequencyRollOffKnee;} + Scalar + GetHighFrequencyRollOffDistanceScale() + {return highFrequencyRollOffDistanceScale;} + + // + //----------------------------------------------------------------------- + // Controls source compression + //----------------------------------------------------------------------- + // + void + ControlSourceCompression( + Scalar exponent, + Scalar scale + ); + Scalar + GetSourceCompressionExponent() + {return sourceCompressionExponent;} + Scalar + GetSourceCompressionScale() + {return sourceCompressionScale;} + + // + //----------------------------------------------------------------------- + // Defines the audio clipping sphere + //----------------------------------------------------------------------- + // + void + DefineClippingSphere(Scalar radius); + Logical + IsPointClipped(const Point3D &point); + Scalar + GetClippingRadius() + {return clippingRadius;} + + // + //----------------------------------------------------------------------- + // ITD Difference + //----------------------------------------------------------------------- + // + void + SetITDDifference(Scalar itd_difference) + {itdDifference = itd_difference;} + Scalar + GetITDDifference() + {return itdDifference;} + + // + //----------------------------------------------------------------------- + // The SetPositionalCulling method allows the rendering process to + // not play audio locations whose positions are masked by other + // audio sources. This has found to be useful for controlling + // audio when resources are limited, but must be + // selectable globally or on a per audio effect basis. + //----------------------------------------------------------------------- + // + void + SetPositionalCulling(Logical turn_on); + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + AudioFrameCount + audioFrameCount; + SlotOf + headEntitySocket; + + Scalar + clippingRadius; + Scalar + distanceBetweenEars; + Scalar + amplitudeRollOffExponent, + amplitudeRollOffKnee, + amplitudeRollOffDistanceScale; + Scalar + highFrequencyRollOffExponent, + highFrequencyRollOffKnee, + highFrequencyRollOffDistanceScale; + Scalar + reverbToDryRatio; + Scalar + audioSoundSpeed; + Scalar + audioDopplerConstant; + Scalar + sourceCompressionExponent, + sourceCompressionScale; + Scalar + itdDifference; + Scalar + globalReverbScale; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline Entity* + AudioHead::GetHeadEntity() + { + Check(this); + return headEntitySocket.GetCurrent(); + } + + //########################################################################## + //######################### AudioComponent ########################### + //########################################################################## + + class AudioComponent__ReceiveControlMessage; + + class AudioComponent: + public Component + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + AudioComponent( + PlugStream *stream, + SharedData &shared_data = DefaultData + ); + ~AudioComponent(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Audio Component Methods + // + public: + void + AddWatcher(Component *component); + + void + ExecuteWatchers(); + + void + Execute(); + + virtual void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + void + PostReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum { + ReceiveControlMessageID = Component::NextMessageID, + NextMessageID + }; + + typedef AudioComponent__ReceiveControlMessage + ReceiveControlMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void + ReceiveControlMessageHandler( + ReceiveControlMessage *message + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + AudioFrameCount + nextExecuteWatcherFrame; + ChainOf + audioWatcherSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + + inline void + AudioComponent::AddWatcher(Component *component) + { + Check(component); + Check(&audioWatcherSocket); + audioWatcherSocket.Add(component); + } + + //~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~ + + class AudioComponent__ReceiveControlMessage: + public Receiver::Message + { + friend class AudioComponent; + + public: + AudioComponent__ReceiveControlMessage( + AudioControlID control_ID, + AudioControlValue control_value + ); + + private: + AudioControlID + controlID; + AudioControlValue + controlValue; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ Resource type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioRenderType *output + ) + { + return stream->ReadBytes(output, sizeof(*output)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioRenderType *input + ) + { + return stream->WriteBytes(input, sizeof(*input)); + } + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioRepresentation *output + ) + { + return stream->ReadBytes(output, sizeof(*output)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioRepresentation *input + ) + { + return stream->WriteBytes(input, sizeof(*input)); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioSourceState *output + ) + { + return stream->ReadBytes(output, sizeof(*output)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioSourceState *input + ) + { + return stream->WriteBytes(input, sizeof(*input)); + } + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioSourcePriority *output + ) + { + return stream->ReadBytes(output, sizeof(*output)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioSourcePriority *input + ) + { + return stream->WriteBytes(input, sizeof(*input)); + } + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioSourceMixPresence *output + ) + { + return stream->ReadBytes(output, sizeof(*output)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioSourceMixPresence *input + ) + { + return stream->WriteBytes(input, sizeof(*input)); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioControlID *output + ) + { + return stream->ReadBytes(output, sizeof(*output)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioControlID *input + ) + { + return stream->WriteBytes(input, sizeof(*input)); + } + +#endif diff --git a/CODE/RP/MUNGA/AUDLOC.CPP b/CODE/RP/MUNGA/AUDLOC.CPP new file mode 100644 index 0000000..b70b1b7 --- /dev/null +++ b/CODE/RP/MUNGA/AUDLOC.CPP @@ -0,0 +1,531 @@ +//===========================================================================// +// File: audloc.cpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDLOC_HPP) +# include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLocation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioLocation::AudioLocation( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + vectorToSource(0.0f, 0.0f, 0.0f), + locationOffset(0.0f, 0.0f, 0.0f) +{ + AudioFrameCount next_update_delay; + Scalar clipping_scale; + + MemoryStream_Read(stream, &locationOffset); + MemoryStream_Read(stream, &next_update_delay); + MemoryStream_Read(stream, &clipping_scale); + + AudioLocationX(entity, next_update_delay, clipping_scale); +} + +// +//############################################################################# +//############################################################################# +// +AudioLocation::~AudioLocation() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::AudioLocationX( + Entity *entity, + AudioFrameCount next_update_delay, + Scalar clipping_scale + ) +{ + Check(entity); + linkedEntity = entity; + entity->AddAudioComponent(this); + + clippingScale = clipping_scale; + isHeadSource = False; + distanceToSource = 1.0f; + dopplerCents = 0; + #if 0 + angleOffOrientation = 0.0f; + #endif + azimuthOfSource = 0.0f; + distanceVolumeScale = 1.0f; + highFreqCutoffScale = 1.0f; + #if 0 + reverbVolumeScale = 0.0f; + #endif + nextUpdateDelay = next_update_delay; + nextUpdateFrame = NullAudioFrameCount; +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLocation::TestInstance() const +{ + Component::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Point3D, location_offset); + + // + // Read update delay + // + CString update_delay_string("update_delay"); + AudioFrameCount update_delay = DefaultAudioFrameDelay; + + if (name_list->FindData(update_delay_string) != NULL) + { + Check_Pointer(name_list->FindData(update_delay_string)); + Convert_From_Ascii( + (const char *)name_list->FindData(update_delay_string), + &update_delay + ); + } + MemoryStream_Write(stream, &update_delay); + + // + // Read culling scale + // + CString clipping_scale_string("clipping_scale"); + Scalar clipping_scale = 1.0f; + + if (name_list->FindData(clipping_scale_string) != NULL) + { + Check_Pointer(name_list->FindData(clipping_scale_string)); + Convert_From_Ascii( + (const char *)name_list->FindData(clipping_scale_string), + &clipping_scale + ); + } + MemoryStream_Write(stream, &clipping_scale); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::ReceiveControl( + AudioControlID, + AudioControlValue + ) +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLocation::IsAudioLocationClipped(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + + // + // HACK - This is a rough approximation in that it does not + // take into account the offset of the location from the + // center of the entity. But, this is more efficient and is OK + // as long as the clipping sphere does not exclude the location + // unnaturally + // + Entity + *head_entity; + Vector3D + difference; + Scalar + scaled_radius; + + head_entity = audio_head->GetHeadEntity(); + Check(head_entity); + Check(linkedEntity); + difference.Subtract( + head_entity->localOrigin.linearPosition, + linkedEntity->localOrigin.linearPosition + ); + scaled_radius = audio_head->GetClippingRadius() * clippingScale; + return difference.LengthSquared() > scaled_radius * scaled_radius; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::UpdateSpatialModelImplementation(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + + // + //-------------------------------------------------------------------------- + // Get head and source entity + //-------------------------------------------------------------------------- + // + Entity *source_entity = GetLinkedEntity(); + Entity *head_entity = audio_head->GetHeadEntity(); + + Check(source_entity); + Check(head_entity); + + // + //-------------------------------------------------------------------------- + // Catch case of head == source at origin + //-------------------------------------------------------------------------- + // + if ( + head_entity == source_entity && + locationOffset == Vector3D::Identity + ) + { + isHeadSource = True; + vectorToSource = Vector3D::Identity; + distanceToSource = 0.0f; + dopplerCents = 0; + #if 0 + angleOffOrientation = 0.0f; + #endif + azimuthOfSource = 0.0f; + distanceVolumeScale = 1.0f; + highFreqCutoffScale = 1.0f; + #if 0 + reverbVolumeScale = audio_head->GetReverbToDryRatio(); + #endif + return; + } + isHeadSource = False; + + // + //-------------------------------------------------------------------------- + // Get the ear to world linear matrix + //-------------------------------------------------------------------------- + // + LinearMatrix ear_to_world = audio_head->GetEarToWorld(); + + // + //-------------------------------------------------------------------------- + // Calculate vector to source with respect to local coordinate system + // of the ears + //-------------------------------------------------------------------------- + // + { + // + // Get the source location offset from the entity position in + // world coordinates + // + Vector3D world_location_offset; + Vector3D world_source_location; + + world_location_offset.Multiply( + locationOffset, + source_entity->localToWorld + ); + Check(&world_location_offset); + + world_source_location.Add( + source_entity->localOrigin.linearPosition, + world_location_offset + ); + Check(&world_source_location); + + // + // Get the vector from the ear to the source, note that the vector + // is not calculated by the ears offset but from the entities location + // + Vector3D world_ear_to_source_vector; + + world_ear_to_source_vector.Subtract( + world_source_location, + head_entity->localOrigin.linearPosition + ); + Check(&world_ear_to_source_vector); + + // + // Transform the vector into ear coordinates + // + vectorToSource.MultiplyByInverse( + world_ear_to_source_vector, + ear_to_world + ); + Check(&vectorToSource); + } + + // + //-------------------------------------------------------------------------- + // Calculate distance to source + //-------------------------------------------------------------------------- + // + distanceToSource = vectorToSource.Length(); + + // + //-------------------------------------------------------------------------- + // Calculate normal to source + //-------------------------------------------------------------------------- + // + Vector3D normal_to_source(0.0f, 0.0f, -1.0f); + + if (!Small_Enough(distanceToSource)) + { + normal_to_source.Normalize(vectorToSource); + Check(&normal_to_source); + } + + #if 0 + // + //-------------------------------------------------------------------------- + // Calculate angle between the orientation of the head and source + //-------------------------------------------------------------------------- + // + if (Small_Enough(distanceToSource)) + { + angleOffOrientation = 0.0f; + } + else + { + UnitVector direction; + Scalar cosine; + + ear_to_world.GetToAxis(Z_Axis, &direction); + Check(&direction); + + Check(&normal_to_source); + cosine = normal_to_source * direction; + Clamp(cosine, -1.0f, 1.0f); + angleOffOrientation = Arccos(cosine); + angleOffOrientation.Normalize(); + } + Verify( + angleOffOrientation <= 180.0f*RAD_PER_DEG && + angleOffOrientation >= -180.0f*RAD_PER_DEG + ); + #endif + + // + //-------------------------------------------------------------------------- + // Calculate azimuth + //-------------------------------------------------------------------------- + // + if (Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z)) + { + azimuthOfSource = 0.0f; + } + else + { + Verify(!(Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z))); + azimuthOfSource = Arctan(vectorToSource.x, vectorToSource.z); + } + Verify( + azimuthOfSource <= 180.0f*RAD_PER_DEG && + azimuthOfSource >= -180.0f*RAD_PER_DEG + ); + + // + //-------------------------------------------------------------------------- + // Calculate distance volume scaling + // Apply clipping scale to rolloff distance scale, thereby giving this + // audio location a specifc rolloff characteristic + //-------------------------------------------------------------------------- + // + if (distanceToSource > audio_head->GetAmplitudeRollOffKnee()) + { + // + // y = 1 / 1 + (K(x - knee))^exp + // + Verify(!Small_Enough(clippingScale)); + const Scalar temp = + (audio_head->GetAmplitudeRollOffDistanceScale() / clippingScale) * + (distanceToSource - audio_head->GetAmplitudeRollOffKnee()); + const Scalar temp2 = + 1.0f + pow(temp, audio_head->GetAmplitudeRollOffExponent()); + + Verify(!Small_Enough(temp2)); + distanceVolumeScale = 1.0f / temp2; + } + else + { + distanceVolumeScale = 1.0f; + } + Verify(distanceVolumeScale >= 0.0f && distanceVolumeScale <= 1.0f); + + // + //-------------------------------------------------------------------------- + // Calculate high frequency cutoff scaling + // Apply clipping scale to high frequency rolloff distance scale, thereby + // giving this audio location a specifc rolloff characteristic + //-------------------------------------------------------------------------- + // + if (distanceToSource > audio_head->GetHighFrequencyRollOffKnee()) + { + // + // y = 1 / 1 + (K(x - knee))^exp + // + Verify(!Small_Enough(clippingScale)); + const Scalar temp = + (audio_head->GetHighFrequencyRollOffDistanceScale() / clippingScale) * + (distanceToSource - audio_head->GetHighFrequencyRollOffKnee()); + const Scalar temp2 = + 1.0f + pow(temp, audio_head->GetHighFrequencyRollOffExponent()); + + Verify(!Small_Enough(temp2)); + highFreqCutoffScale = 1.0f / temp2; + } + else + { + highFreqCutoffScale = 1.0f; + } + Verify(highFreqCutoffScale >= 0.0f && highFreqCutoffScale <= 1.0f); + + #if 0 + // + //-------------------------------------------------------------------------- + // Calculate reverb volume scaling + //-------------------------------------------------------------------------- + // + if (distanceToSource > audio_head->GetAmplitudeRollOffKnee()) + { + const Scalar temp = + distanceToSource - audio_head->GetAmplitudeRollOffKnee() + 1.0f; + + reverbVolumeScale = + audio_head->GetReverbToDryRatio() * + pow(temp, audio_head->GetAmplitudeRollOffExponent()); + if (reverbVolumeScale > 1.0f) + reverbVolumeScale = 1.0f; + } + else + { + reverbVolumeScale = audio_head->GetReverbToDryRatio(); + } + Verify(reverbVolumeScale >= 0.0f && reverbVolumeScale <= 1.0f); + #endif + + // + //-------------------------------------------------------------------------- + // Calculate relative velocity of source + //-------------------------------------------------------------------------- + // + Vector3D relative_velocity_temp; + Vector3D relative_velocity; + + relative_velocity_temp.Subtract( + source_entity->GetWorldLinearVelocity(), + head_entity->GetWorldLinearVelocity() + ); + Check(&relative_velocity_temp); + + relative_velocity.MultiplyByInverse( + relative_velocity_temp, + head_entity->localToWorld + ); + Check(&relative_velocity); + + // + //-------------------------------------------------------------------------- + // Calculate doppler shift in cents + // cents = (c / (c - v)) / ScaleRatio + //-------------------------------------------------------------------------- + // + if (!Small_Enough(distanceToSource)) + { + AudioPitchCents + cents; + Scalar speed_of_source = + normal_to_source * relative_velocity; + const Scalar ear_radius = + audio_head->GetDistanceBetweenEars() * 0.5f; + + if (distanceToSource < ear_radius) + { + Verify(!Small_Enough(ear_radius)); + speed_of_source *= (distanceToSource / ear_radius); + } + + if (CalculateDoppler(audio_head, speed_of_source, ¢s)) + { + dopplerCents = cents; + } + } + else + { + dopplerCents = 0; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLocation::CalculateDoppler( + AudioHead *audio_head, + Scalar speed, + AudioPitchCents *result + ) +{ + Check(this); + Check(audio_head); + Check_Pointer(result); + + Scalar speed_of_sound = audio_head->GetAudioSoundSpeed(); + + Clamp(speed, -speed_of_sound, speed_of_sound); + if (!Small_Enough(speed_of_sound - speed)) + { + *result = audio_head->GetAudioDopplerConstant() * + ( 1 - speed_of_sound / (speed_of_sound - speed) ); + return True; + } + return False; +} + diff --git a/CODE/RP/MUNGA/AUDLOC.HPP b/CODE/RP/MUNGA/AUDLOC.HPP new file mode 100644 index 0000000..020c47e --- /dev/null +++ b/CODE/RP/MUNGA/AUDLOC.HPP @@ -0,0 +1,221 @@ +//===========================================================================// +// File: audloc.hpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDLOC_HPP) +# define AUDLOC_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + + //########################################################################## + //######################## AudioLocation ############################# + //########################################################################## + + class AudioLocation: + public AudioComponent + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + AudioLocation( + PlugStream *stream, + Entity *entity + ); + void + AudioLocationX( + Entity *entity, + AudioFrameCount next_update_delay, + Scalar clipping_scale + ); + ~AudioLocation(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Resource Building + // + public: + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Audio Component Support + // + public: + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Audio Location Support + // + public: + // + //----------------------------------------------------------------------- + // GetLinkedEntity + //----------------------------------------------------------------------- + // + Entity* + GetLinkedEntity(); + + // + //----------------------------------------------------------------------- + // IsAudioLocationClipped + //----------------------------------------------------------------------- + // + Logical + IsAudioLocationClipped(AudioHead *audio_head); + + // + //----------------------------------------------------------------------- + // UpdateSpatialModel + //----------------------------------------------------------------------- + // + void + UpdateSpatialModel(AudioHead *audio_head); + + // + //----------------------------------------------------------------------- + // Access to localization results + //----------------------------------------------------------------------- + // + Logical + IsHeadSource() + {return isHeadSource;} + Scalar + GetDistanceToSource() + {return distanceToSource;} + Scalar + GetDistanceToSourceListenerPlane(); + Radian + GetAzimuthOfSource() + {return azimuthOfSource;} + Scalar + GetDistanceVolumeScale() + {return distanceVolumeScale;} + Scalar + GetHighFreqCutoffScale() + {return highFreqCutoffScale;} + AudioPitchCents + GetDopplerCents() + {return dopplerCents;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected Implementations + // + protected: + virtual void + UpdateSpatialModelImplementation(AudioHead *audio_head); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Methods + // + private: + Logical + CalculateDoppler( + AudioHead *audio_head, + Scalar speed, + AudioPitchCents *result + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + Entity + *linkedEntity; + + Point3D + locationOffset; + Scalar + clippingScale; + + Logical + isHeadSource; + Vector3D + vectorToSource; + Scalar + distanceToSource; + #if 0 + Radian + angleOffOrientation; + #endif + Radian + azimuthOfSource; + Scalar + distanceVolumeScale; + Scalar + highFreqCutoffScale; + #if 0 + Scalar + reverbVolumeScale; + #endif + AudioPitchCents + dopplerCents; + + AudioFrameCount + nextUpdateDelay; + AudioFrameCount + nextUpdateFrame; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLocation inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + + inline Entity* + AudioLocation::GetLinkedEntity() + { + Check(this); + return linkedEntity; + } + + inline Scalar + AudioLocation::GetDistanceToSourceListenerPlane() + { + Check(this); + Vector3D + vector_to_source_listener_plane( + vectorToSource.x, + 0.0f, + vectorToSource.z + ); + return vector_to_source_listener_plane.Length(); + } + + inline void + AudioLocation::UpdateSpatialModel(AudioHead *audio_head) + { + Check(this); + Check(audio_head); + if (nextUpdateFrame <= audio_head->GetAudioFrameCount()) + { + nextUpdateFrame = audio_head->GetAudioFrameCount() + nextUpdateDelay; + UpdateSpatialModelImplementation(audio_head); + } + } + +#endif diff --git a/CODE/RP/MUNGA/AUDLVL.CPP b/CODE/RP/MUNGA/AUDLVL.CPP new file mode 100644 index 0000000..5a47e1a --- /dev/null +++ b/CODE/RP/MUNGA/AUDLVL.CPP @@ -0,0 +1,480 @@ +//===========================================================================// +// File: audio.hh // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDLVL_HPP) +# include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(AUDREND_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioLevelOfDetail::AudioLevelOfDetail(PlugStream *stream): + Plug(stream) +{ + #if 0 + amplitudeRadiationProfile = 0.0f; + filterRadiationProfile = 0.0f; + #endif + + // + // Read fields + // + MemoryStream_Read(stream, &voiceCount); + MemoryStream_Read(stream, &audioRenderType); + + // + // Read suspend seconds and calculate suspendDelay + // + Scalar + suspend_delay_seconds; + + MemoryStream_Read(stream, &suspend_delay_seconds); + Check(application); + Check(application->GetAudioRenderer()); + suspendDelay = suspend_delay_seconds * + application->GetAudioRenderer()->GetCalibrationRate() + 0.5f; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLevelOfDetail::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Plug::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioVoiceCount, voice_count); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, render_type); + + // + // Store suspend delay + // + CString suspend_delay_string("suspend_delay"); + Scalar suspend_delay_seconds = 0.33f; // HACK - should come from somewhere else + + if (name_list->FindData(suspend_delay_string) != NULL) + { + Check_Pointer(name_list->FindData(suspend_delay_string)); + Convert_From_Ascii( + (const char *)name_list->FindData(suspend_delay_string), + &suspend_delay_seconds + ); + } + MemoryStream_Write(stream, &suspend_delay_seconds); +} + +// +//############################################################################# +//############################################################################# +// +AudioLevelOfDetail::~AudioLevelOfDetail() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLevelOfDetail::TestInstance() const +{ + Plug::TestInstance(); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioResource::AudioResource(PlugStream *stream): + Node(stream), + audioLevelOfDetailSocket(NULL, True) +{ + // + // Read the table + // + CollectionSize i, number_of_entries; + + MemoryStream_Read(stream, &number_of_entries); + for (i = 0; i < number_of_entries; i++) + { + Scalar distance; + AudioLevelOfDetail *audio_level_of_detail; + + MemoryStream_Read(stream, &distance); + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_level_of_detail); + Check(audio_level_of_detail); + audioLevelOfDetailSocket.AddValue(audio_level_of_detail, distance); + } + + // + // Verify that there is at least one entry and the first one is at 0.0f + // + #if DEBUG_LEVEL>0 + { + TableIteratorOf iterator(&audioLevelOfDetailSocket); + Check(&iterator); + Verify(iterator.GetSize() > 0); + Verify(iterator.GetCurrent() != NULL); + Verify(iterator.GetValue() == 0.0f); + } + #endif + + // + // Select the first entry + // + TableIteratorOf iterator(&audioLevelOfDetailSocket); + + audioLevelOfDetail = iterator.GetCurrent(); + Check(audioLevelOfDetail); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Node::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Count number of entries + // + int number_of_entries = 0; + NameList::Entry *entry; + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_level_of_detail")) + number_of_entries++; + entry = entry->GetNextEntry(); + } + + // + // Store entries + // + MemoryStream_Write(stream, &number_of_entries); + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_level_of_detail")) + { + CString object_string; + Scalar distance; + ObjectID object_ID; + + Check_Pointer(entry->GetChar()); + object_string = entry->GetChar(); + + Check_Pointer(object_string.GetNthToken(0)); + Convert_From_Ascii(object_string.GetNthToken(0), &distance); + MemoryStream_Write(stream, &distance); + + Check(stream); + Check_Pointer(object_string.GetNthToken(1)); + object_ID = stream->FindObjectID(object_string.GetNthToken(1)); + Verify(object_ID != NullObjectID); + MemoryStream_Write(stream, &object_ID); + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +//############################################################################# +// +AudioResource::~AudioResource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioResource::TestInstance() const +{ + Node::TestInstance(); + Check(&audioLevelOfDetailSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResource::SetDistance(Scalar distance) +{ + Check(this); + Verify(distance >= 0.0f); + + // + // Goto the last entry + // + TableIteratorOf + iterator(&audioLevelOfDetailSocket); + + Check(&iterator); + iterator.Last(); + + // + // While the distance is less than the distance of the entry + // + while (distance < iterator.GetValue()) + { + iterator.Previous(); + } + audioLevelOfDetail = iterator.GetCurrent(); + Check(audioLevelOfDetail); + + // + // Verify that the distance is greater than this entry, and less than + // the next + // + #if DEBUG_LEVEL>0 + Verify(distance >= iterator.GetValue()); + iterator.Next(); + if (iterator.GetCurrent() != NULL) + { + Verify(distance < iterator.GetValue()); + } + #endif + + // + // Dump the LOD of the resource + // + #if 0 + CollectionSize i = 0; + iterator.First(); + while (iterator.GetCurrent() != NULL) + { + Check(iterator.GetCurrent()); + if (audioLevelOfDetail == iterator.GetCurrent() /* && i > 0 */ ) + { + Tell( + "AudioLOD:" << i << + " d:" << distance << + " t:" << iterator.GetValue() << + "\n" + ); + break; + } + iterator.Next(); + i++; + } + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResourceIndex ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioResourceIndex::AudioResourceIndex(PlugStream *stream): + Node(stream), + audioResourceSocket(NULL, True) +{ + CollectionSize i, number_of_entries; + + MemoryStream_Read(stream, &number_of_entries); + for (i = 0; i < number_of_entries; i++) + { + AudioResource *audio_resource; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource); + Check(audio_resource); + AddAudioResource(audio_resource, i); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResourceIndex::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Node::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Count number of entries + // + int number_of_entries = 0; + NameList::Entry *entry; + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_resource")) + number_of_entries++; + entry = entry->GetNextEntry(); + } + + // + // Store entries + // + MemoryStream_Write(stream, &number_of_entries); + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_resource")) + { + CString object_name; + ObjectID object_ID; + + Check_Pointer(entry->GetChar()); + object_name = entry->GetChar(); + + Check(stream); + object_ID = stream->FindObjectID(object_name); + Verify(object_ID != NullObjectID); + MemoryStream_Write(stream, &object_ID); + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +//############################################################################# +// +AudioResourceIndex::~AudioResourceIndex() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioResourceIndex::TestInstance() const +{ + Node::TestInstance(); + Check(&audioResourceSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResourceIndex::AddAudioResource( + AudioResource *audio_resource, + Enumeration index + ) +{ + Check(this); + audioResourceSocket.AddValue(audio_resource, index); + + #if DEBUG_LEVEL>0 + TableIteratorOf iterator(&audioResourceSocket); + Check(&iterator); + for (int i = 0; i < iterator.GetSize(); i++) + { + Verify(iterator.GetNth(i) == audioResourceSocket.Find(i)); + } + #endif +} + +// +//############################################################################# +//############################################################################# +// +AudioResource* + AudioResourceIndex::GetAudioResource(Enumeration index) +{ + Check(this); + + TableIteratorOf iterator(&audioResourceSocket); + Check(&iterator); + Verify(iterator.GetNth(index) == audioResourceSocket.Find(index)); + + return iterator.GetNth(index); +} + +// +//############################################################################# +//############################################################################# +// +CollectionSize + AudioResourceIndex::GetSize() +{ + Check(this); + + TableIteratorOf iterator(&audioResourceSocket); + Check(&iterator); + + return iterator.GetSize(); +} + + diff --git a/CODE/RP/MUNGA/AUDLVL.HPP b/CODE/RP/MUNGA/AUDLVL.HPP new file mode 100644 index 0000000..30cd961 --- /dev/null +++ b/CODE/RP/MUNGA/AUDLVL.HPP @@ -0,0 +1,270 @@ +//===========================================================================// +// File: audlvl.hpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDLVL_HPP) +# define AUDLVL_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + + //########################################################################## + //####################### AudioLevelOfDetail ######################### + //########################################################################## + + class AudioLevelOfDetail: + public Plug + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioLevelOfDetail(PlugStream *stream); + ~AudioLevelOfDetail(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + AudioVoiceCount + GetVoiceCount() + {return voiceCount;} + AudioRenderType + GetAudioRenderType() + {return audioRenderType;} + AudioFrameCount + GetSuspendDelay() + {return suspendDelay;} + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + + #if 0 + // + //----------------------------------------------------------------------- + // Defines the radial variation of the amplitude of the audio source. + // This feature is implemented well in Crystal River Engineering's + // API. The radiation profile of an audio source is specified with + // an array of sound levels in decibels paired with angles off of + // the audio source orientation. For example, you can design a + // rocket sound that is louder when heard from directly behind then + // from the side. + //----------------------------------------------------------------------- + // + AudioRadiationProfile + amplitudeRadiationProfile; + #endif + + #if 0 + // + //----------------------------------------------------------------------- + // Defines the radial variation of the high frequency content of the + // audio source. This concept is analogous to + // SetAmplitudeRadiationProfile except applied to the high frequency + // content of the audio source. Again, this allows the audio source + // to vary with respect to the position and orientation of the audio + // source and head. + //----------------------------------------------------------------------- + // + AudioRadiationProfile + filterRadiationProfile; + #endif + + // + //----------------------------------------------------------------------- + // Misc + //----------------------------------------------------------------------- + // + AudioVoiceCount + voiceCount; + AudioRenderType + audioRenderType; + AudioFrameCount + suspendDelay; + }; + + //########################################################################## + //########################## AudioResource ############################ + //########################################################################## + + class AudioResource: + public Node + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioResource(PlugStream *stream); + ~AudioResource(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // SetDistance + //----------------------------------------------------------------------- + // + void + SetDistance(Scalar distance); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + AudioVoiceCount + GetVoiceCount(); + AudioRenderType + GetAudioRenderType(); + AudioFrameCount + GetSuspendDelay(); + + protected: + // + //----------------------------------------------------------------------- + // Protected data + //----------------------------------------------------------------------- + // + AudioLevelOfDetail* + GetAudioLevelOfDetail(); + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + AudioLevelOfDetail + *audioLevelOfDetail; + TableOf + audioLevelOfDetailSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResource inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline AudioLevelOfDetail* + AudioResource::GetAudioLevelOfDetail() + { + Check(this); + return audioLevelOfDetail; + } + + inline AudioVoiceCount + AudioResource::GetVoiceCount() + { + Check(this); + Check(audioLevelOfDetail); + return audioLevelOfDetail->GetVoiceCount(); + } + + inline AudioRenderType + AudioResource::GetAudioRenderType() + { + Check(this); + Check(audioLevelOfDetail); + return audioLevelOfDetail->GetAudioRenderType(); + } + + inline AudioFrameCount + AudioResource::GetSuspendDelay() + { + Check(this); + Check(audioLevelOfDetail); + return audioLevelOfDetail->GetSuspendDelay(); + } + + //########################################################################## + //######################## AudioResourceIndex ######################## + //########################################################################## + + class AudioResourceIndex: + public Node + { + public: + AudioResourceIndex(PlugStream *stream); + ~AudioResourceIndex(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + void + AddAudioResource( + AudioResource *audio_resource, + Enumeration index + ); + + AudioResource* + GetAudioResource(Enumeration index); + + CollectionSize + GetSize(); + + private: + TableOf + audioResourceSocket; + }; + + +#endif diff --git a/CODE/RP/MUNGA/AUDMIDI.CPP b/CODE/RP/MUNGA/AUDMIDI.CPP new file mode 100644 index 0000000..86843ad --- /dev/null +++ b/CODE/RP/MUNGA/AUDMIDI.CPP @@ -0,0 +1,706 @@ +//===========================================================================// +// File: audmidi.cpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/23/95 ECH Initial code +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDMIDI_HPP) +# include +#endif + +//############################################################################# +//########################### MidiParse ################################# +//############################################################################# + +#define NOTEOFF (0x80) +#define NOTEON (0x90) +#define PRESSURE (0xa0) +#define CONTROLLER (0xb0) +#define PITCHBEND (0xe0) +#define PROGRAM (0xc0) +#define CHANPRESSURE (0xd0) + +#define METATEXT "Text Event" +#define METACOPYRIGHT "Copyright Notice" +#define METASEQUENCE "Sequence/Track Name" +#define METAINSTRUMENT "Instrument Name" +#define METALYRIC "Lyric" +#define METAMARKER "Marker" +#define METACUE "Cue Point" +#define METAUNRECOGNIZED "Unrecognized" + +#define CHAR_BUFF_SIZE (32) + +// +//############################################################################# +//############################################################################# +// +MidiParse::MidiParse() +{ + Mf_nomerge = 0; // 1 => continue'ed system exclusives are not collapsed. + Mf_currtime = 0L; // current time in delta-time units + Mf_skipinit = 0; // 1 if initial garbage should be skipped + + Mf_toberead = 0L; + + Msgbuff = NULL; // message buffer + Msgsize = 0; // Size of currently allocated Msg + Msgindex = 0; // index of next available location in Msg +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::~MidiParse() +{ + if (Msgbuff != NULL) + { + Unregister_Pointer(Msgbuff); +#if 0 + free(Msgbuff); +#else + delete[] Msgbuff; +#endif + Msgbuff = NULL; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + MidiParse::TestInstance() const +{ + Node::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::CurTime() +{ + Check(this); + return Mf_currtime; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::Parse() +{ + Check(this); + + SignedWord ntrks; + + ntrks = readheader(); + Verify(ntrks > 0); + while (ntrks-- > 0) + readtrack(); +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::readmt( + char *s, + SignedWord skip + ) +{ + Check(this); + + SignedWord nread = 0; + char b[4]; + char buff[CHAR_BUFF_SIZE]; + SignedWord c; + char *errmsg = "expecting "; + + // read through the "MThd" or "MTrk" header string + // if 1, we attempt to skip initial garbage. + +retry: + while ( nread<4 ) + { + c = Mf_getc(); + if ( c == EOF ) + { + errmsg = "EOF while expecting "; + goto err; + } + b[nread++] = (char)c; + } + + // See if we found the 4 characters we're looking for + + if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] ) + return 0; + if ( skip ) + { + + // If we are supposed to skip initial garbage, + // try again with the next character. + + b[0]=b[1]; + b[1]=b[2]; + b[2]=b[3]; + nread = 3; + goto retry; + } +err: + Str_Copy(buff, errmsg, CHAR_BUFF_SIZE); + Str_Cat(buff, s, CHAR_BUFF_SIZE); + mferror(buff); + return 0; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::egetc() +{ + Check(this); + + // read a single character and abort on EOF + + SignedWord c = Mf_getc(); + + if ( c == EOF ) + mferror("premature EOF"); + Mf_toberead--; + return c; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::readheader() +{ + Check(this); + + // read a header chunk + + SignedWord + format, ntrks, division; + + if ( readmt("MThd", Mf_skipinit) == EOF ) + return 0; + + Mf_toberead = read32bit(); + format = read16bit(); + ntrks = read16bit(); + division = read16bit(); + + Mf_header(format,ntrks,division); + + // flush any extra stuff, in case the length of header is not 6 + + while ( Mf_toberead > 0 ) + egetc(); + return ntrks; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::readtrack() +{ + Check(this); + + // read a track chunk + + // This array is indexed by the high half of a status byte. It's + // value is either the number of bytes needed (1 or 2) for a channel + // message, or 0 (meaning it's not a channel message). + + static SignedWord chantype[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 through 0x70 + 2, 2, 2, 2, 1, 1, 2, 0 // 0x80 through 0xf0 + }; + + SignedLongWord lookfor, lng; + SignedWord c, c1, type; + SignedWord sysexcontinue = 0; // 1 if last message was an unfinished sysex + SignedWord running; // 1 when running status used + SignedWord status = 0; // (possibly running) status byte + SignedWord needed; + + if ( readmt("MTrk",0) == EOF ) + return; + + Mf_toberead = read32bit(); + Mf_currtime = 0; + + Mf_starttrack(); + + while ( Mf_toberead > 0 ) + { + Mf_currtime += readvarinum(); // delta time + + c = egetc(); + + if ( sysexcontinue && c != 0xf7 ) + mferror("didn't find expected continuation of a sysex"); + + if ( (c & 0x80) == 0 ) // running status? + { + if ( status == 0 ) + mferror("unexpected running status"); + running = 1; + } + else + { + status = c; + running = 0; + } + + needed = chantype[ (status>>4) & 0xf ]; + + if ( needed ) // ie. is it a channel message? + { + if ( running ) + c1 = c; + else + c1 = egetc(); + chanmessage( status, c1, (needed>1) ? egetc() : (SignedWord)0 ); + continue; + } + + switch ( c ) + { + case 0xff: // meta event + type = egetc(); + // watch out - Don't combine the next 2 statements + lng = readvarinum(); + lookfor = Mf_toberead - lng; + msginit(); + + while ( Mf_toberead > lookfor ) + msgadd(egetc()); + + metaevent(type); + break; + + case 0xf0: // start of system exclusive + // watch out - Don't combine the next 2 statements + lng = readvarinum(); + lookfor = Mf_toberead - lng; + msginit(); + msgadd(0xf0); + + while ( Mf_toberead > lookfor ) + msgadd(c=egetc()); + + if ( c==0xf7 || Mf_nomerge==0 ) + sysex(); + else + sysexcontinue = 1; // merge into next msg + break; + + case 0xf7: // sysex continuation or arbitrary stuff + // watch out - Don't combine the next 2 statements + lng = readvarinum(); + lookfor = Mf_toberead - lng; + + if ( ! sysexcontinue ) + msginit(); + + while ( Mf_toberead > lookfor ) + msgadd(c=egetc()); + + if ( ! sysexcontinue ) + { + Mf_arbitrary(msgleng(),msg()); + } + else if ( c == 0xf7 ) + { + sysex(); + sysexcontinue = 0; + } + break; + + default: + badbyte(c); + break; + } + } + Mf_endtrack(); + return; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::badbyte(SignedWord c) +{ + Check(this); + + char buff[CHAR_BUFF_SIZE]; + + sprintf(buff,"unexpected byte: 0x%02x",c); + mferror(buff); +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::metaevent(SignedWord type) +{ + Check(this); + + SignedWord leng = msgleng(); + char *m = msg(); + + switch ( type ) + { + case 0x00: + Mf_seqnum(to16bit(m[0],m[1])); + break; + case 0x01: // Text event + case 0x02: // Copyright notice + case 0x03: // Sequence/Track name + case 0x04: // Instrument name + case 0x05: // Lyric + case 0x06: // Marker + case 0x07: // Cue point + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + // These are all text events + Mf_text(type,leng,m); + break; + case 0x2f: // End of Track + Mf_eot(); + break; + case 0x51: // Set tempo + Mf_tempo(to32bit((SignedWord)0,m[0],m[1],m[2])); + break; + case 0x54: + Mf_smpte(m[0],m[1],m[2],m[3],m[4]); + break; + case 0x58: + Mf_timesig(m[0],m[1],m[2],m[3]); + break; + case 0x59: + Mf_keysig(m[0],m[1]); + break; + case 0x7f: + Mf_sqspecific(leng,m); + break; + default: + Mf_metamisc(type,leng,m); + } +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::sysex() +{ + Check(this); + Mf_sysex(msgleng(),msg()); +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::chanmessage( + SignedWord status, + SignedWord c1, + SignedWord c2 + ) +{ + Check(this); + + SignedWord chan = status & (SignedWord)0xf; + + switch ( status & 0xf0 ) + { + case NOTEOFF: + Mf_off(chan,c1,c2); + break; + case NOTEON: + Mf_on(chan,c1,c2); + break; + case PRESSURE: + Mf_pressure(chan,c1,c2); + break; + case CONTROLLER: + Mf_controller(chan,c1,c2); + break; + case PITCHBEND: + Mf_pitchbend(chan,c1,c2); + break; + case PROGRAM: + Mf_program(chan,c1); + break; + case CHANPRESSURE: + Mf_chanpressure(chan,c1); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::readvarinum() +{ + Check(this); + + // readvarinum - read a varying-length number, and return the + // number of characters it took. + + SignedLongWord value; + SignedWord c; + + c = egetc(); + value = c; + if (c & 0x80) + { + value &= 0x7f; + do + { + c = egetc(); + value <<= 7; + value += (c & 0x7f); + } while (c & 0x80); + } + return value; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::to32bit(SignedWord c1, SignedWord c2,SignedWord c3, SignedWord c4) +{ + Check(this); + + SignedLongWord value; + + value = (c1 & 0xff); + value = (value<<8) + (c2 & 0xff); + value = (value<<8) + (c3 & 0xff); + value = (value<<8) + (c4 & 0xff); + return value; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::to16bit(SignedWord c1,SignedWord c2) +{ + Check(this); + + SignedWord value; + + value = (c1 & (SignedWord)0xff); + value = (SignedWord)((SignedWord)(value<<8) + (c2 & (SignedWord)0xff)); + return value; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::read32bit() +{ + Check(this); + + SignedWord c1, c2, c3, c4; + + c1 = egetc(); + c2 = egetc(); + c3 = egetc(); + c4 = egetc(); + return to32bit(c1,c2,c3,c4); +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::read16bit() +{ + Check(this); + + SignedWord c1, c2; + + c1 = egetc(); + c2 = egetc(); + return to16bit(c1,c2); +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::mferror(char *s) +{ + Check(this); + Mf_error(s); +} + +// The code below allows collection of a system exclusive message of +// arbitrary length. The Msgbuff is expanded as necessary. The only +// visible data/routines are msginit(), msgadd(), msg(), msgleng(). + +#define MSGINCREMENT ((SignedWord)128) + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::msginit() +{ + Check(this); + Msgindex = 0; +} + +// +//############################################################################# +//############################################################################# +// +char* + MidiParse::msg() +{ + Check(this); + return Msgbuff; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::msgleng() +{ + Check(this); + return Msgindex; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::msgadd(SignedWord c) +{ + Check(this); + + // If necessary, allocate larger message buffer. + + if ( Msgindex >= Msgsize ) + msgenlarge(); + Msgbuff[Msgindex++] = (char)c; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::msgenlarge() +{ + Check(this); + + char *newmess; + char *oldmess = Msgbuff; + SignedWord oldleng = Msgsize; + + Msgsize += MSGINCREMENT; +#if 0 + newmess = (char*)malloc( sizeof(char)*Msgsize ); +#else + newmess = new char[Msgsize]; +#endif + Register_Pointer(newmess); + + // copy old message into larger new one + if ( oldmess != 0 ) + { + char *p = newmess; + char *q = oldmess; + char *endq = &oldmess[oldleng]; + + for ( ; q!=endq ; p++,q++ ) + *p = *q; + Unregister_Pointer(oldmess); +#if 0 + free(oldmess); +#else + delete[] oldmess; +#endif + } + Msgbuff = newmess; +} + +// METHODS TO OVERRIDE + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::Mf_getc() +{ + Fail("MidiParse::Mf_getc - Should never reach here"); + return 0; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::Mf_error(char*) +{ + Fail("MidiParse::Mf_error - Should never reach here"); +} diff --git a/CODE/RP/MUNGA/AUDMIDI.HPP b/CODE/RP/MUNGA/AUDMIDI.HPP new file mode 100644 index 0000000..fe7eb05 --- /dev/null +++ b/CODE/RP/MUNGA/AUDMIDI.HPP @@ -0,0 +1,166 @@ +//===========================================================================// +// File: audmidi.hpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/23/95 ECH Initial code +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDMIDI_HPP) +# define AUDMIDI_HPP + +# if !defined(NODE_HPP) +# include +# endif + + //########################################################################## + //########################## MidiParse ############################### + //########################################################################## + + class MidiParse: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + typedef long SignedLongWord; // 4 bytes + typedef short int SignedWord; // 2 bytes + typedef char SignedByte; // 1 bytes + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + MidiParse(); + ~MidiParse(); + Logical + TestInstance() const; + + void + Parse(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessors + // + protected: + SignedLongWord + CurTime(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Sub-class callbacks + // + private: + virtual SignedWord + Mf_getc(); + virtual void + Mf_error(char *); + + virtual void + Mf_starttrack() {} + virtual void + Mf_endtrack() {} + virtual void + Mf_eot() {} + virtual void + Mf_header(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_on(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_off(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_pressure(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_controller(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_pitchbend(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_program(SignedWord,SignedWord) {} + virtual void + Mf_chanpressure(SignedWord,SignedWord) {} + virtual void + Mf_sysex(SignedWord,char*) {} + virtual void + Mf_arbitrary(SignedWord,char*) {} + virtual void + Mf_metamisc(SignedWord,SignedWord,char*) {} + virtual void + Mf_seqnum(SignedWord) {} + virtual void + Mf_smpte(SignedWord,SignedWord,SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_timesig(SignedWord,SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_tempo(SignedLongWord) {} + virtual void + Mf_keysig(SignedWord,SignedWord) {} + virtual void + Mf_sqspecific(SignedWord,char*) {} + virtual void + Mf_text(SignedWord,SignedWord,char*) {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + SignedWord + readmt(char *s,SignedWord skip); + SignedWord + egetc(); + SignedWord + readheader(); + void + readtrack(); + void + badbyte(SignedWord c); + void + metaevent(SignedWord type); + void + sysex(); + void + chanmessage(SignedWord status,SignedWord c1,SignedWord c2); + SignedLongWord + readvarinum(); + SignedLongWord + to32bit(SignedWord c1, SignedWord c2,SignedWord c3, SignedWord c4); + SignedWord + to16bit(SignedWord c1,SignedWord c2); + SignedLongWord + read32bit(); + SignedWord + read16bit(); + void + mferror(char *s); + void + msginit(); + char* + msg(); + SignedWord + msgleng(); + void + msgadd(SignedWord c); + void + msgenlarge(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + SignedWord Mf_nomerge; + SignedLongWord Mf_currtime; + SignedWord Mf_skipinit; + + SignedLongWord Mf_toberead; + + char *Msgbuff; + SignedWord Msgsize; + SignedWord Msgindex; + }; + +#endif diff --git a/CODE/RP/MUNGA/AUDSEQ.CPP b/CODE/RP/MUNGA/AUDSEQ.CPP new file mode 100644 index 0000000..3945d4d --- /dev/null +++ b/CODE/RP/MUNGA/AUDSEQ.CPP @@ -0,0 +1,894 @@ +//===========================================================================// +// File: audseq.cpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDSEQ_HPP) +# include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlEvent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlEvent::AudioControlEvent( + AudioTick start_tick, + AudioControlID audio_control_ID, + AudioControlValue audio_control_value +): + Plug(AudioControlEventClassID) +{ + startTick = start_tick; + audioControlID = audio_control_ID; + audioControlValue = audio_control_value; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlEvent::AudioControlEvent(): + Plug(AudioControlEventClassID) +{ + startTick = 0; + audioControlID = NullAudioControlID; + audioControlValue = 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlEvent::~AudioControlEvent() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlEvent::TestInstance() const +{ + Plug::TestInstance(); + Verify( + (Enumeration)audioControlID >= (Enumeration)0 && + (Enumeration)audioControlID < (Enumeration)AudioControlIDCount + ); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlEvent::Send(AudioComponent *audio_component) +{ + Check(this); + Check(audio_component); + audio_component->ReceiveControl(audioControlID, audioControlValue); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlEvent::Chase(AudioComponent *audio_component) +{ + Check(this); + Check(audio_component); + + switch (audioControlID) + { + case StartAudioControlID: + return False; + + case StopAudioControlID: + Send(audio_component); + return False; + + default: + break; + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + AudioControlEvent *control_event + ) +{ + Check(stream); + Check_Signature(control_event); + + MemoryStream_Read(stream, &control_event->startTick); + MemoryStream_Read(stream, &control_event->audioControlID); + MemoryStream_Read(stream, &control_event->audioControlValue); + + Check(control_event); + return *stream; +} + +// +//############################################################################# +//############################################################################# +// +MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const AudioControlEvent *control_event + ) +{ + Check(stream); + Check(control_event); + + MemoryStream_Write(stream, &control_event->startTick); + MemoryStream_Write(stream, &control_event->audioControlID); + MemoryStream_Write(stream, &control_event->audioControlValue); + return *stream; +} + +// +//############################################################################# +//############################################################################# +// +ostream& + operator << ( + ostream &strm, + const AudioControlEvent &control_event + ) +{ + Check(&control_event); + + strm << "[" ; + strm << control_event.startTick << ","; + strm << control_event.audioControlID << ","; + strm << control_event.audioControlValue; + strm << "]"; + + return strm; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSequence ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlSequence::AudioControlSequence( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL), + audioControlEventSocket(NULL) +{ + Logical dump_value; + Logical is_looped; + AudioComponent *audio_component; + AudioControlEvent *audio_control_event; + CollectionSize i, number_of_control_events; + AudioDivisionsPerBeat divisions_per_beat; + AudioTempo tempo; + + MemoryStream_Read(stream, &dump_value); + MemoryStream_Read(stream, &is_looped); + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + MemoryStream_Read(stream, &divisions_per_beat); + MemoryStream_Read(stream, &tempo); + MemoryStream_Read(stream, &number_of_control_events); + + for (i = 0; i < number_of_control_events; i++) + { + audio_control_event = new AudioControlEvent; + Register_Object(audio_control_event); + MemoryStream_Read(stream, audio_control_event); + audioControlEventSocket.Add(audio_control_event); + } + + AudioControlSequenceX( + audio_component, + entity, + is_looped, + divisions_per_beat, + tempo, + dump_value + ); +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioControlSequence::AudioControlSequenceX( + AudioComponent *audio_component, + Entity *entity, + Logical is_looped, + AudioDivisionsPerBeat divisions_per_beat, + AudioTempo the_tempo, + Logical dump_value + ) +#else +void + AudioControlSequence::AudioControlSequenceX( + AudioComponent *audio_component, + Entity *entity, + Logical is_looped, + AudioDivisionsPerBeat divisions_per_beat, + AudioTempo the_tempo, + Logical + ) +#endif +{ + Check(audio_component); + audioComponentSocket.Add(audio_component); + + isLooped = is_looped; + isRunning = False; + startTime = AudioTime::Null; + audioControlEventIterator = NULL; + divisionsPerBeat = divisions_per_beat; + tempo = the_tempo; + + #if DEBUG_LEVEL>0 + dumpValue = dump_value; + #endif + + audio_component->AddWatcher(this); + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlSequence::~AudioControlSequence() +{ + StopSequence(); + Verify(!isRunning); + Verify(audioControlEventIterator == NULL); + + AudioControlEventIterator iterator(&audioControlEventSocket); + Check(&iterator); + iterator.DeletePlugs(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, is_looped); + + // + // Write audio component + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + // + // Read tempo + // + AudioTempo tempo = 100; + + if (name_list->FindData("tempo") != NULL) + { + Check_Pointer(name_list->FindData("tempo")); + Convert_From_Ascii((const char *)name_list->FindData("tempo"), &tempo); + } + + // + // Read midi file + // + DynamicMemoryStream midi_file_stream; + + { + CString midi_file_name; + + Check_Pointer(name_list->FindData("midi_file")); + midi_file_name = (const char*)name_list->FindData("midi_file"); + + ifstream input_midi_file(midi_file_name, ios::in|ios::binary); + #if DEBUG_LEVEL>0 + if (!input_midi_file) + { + Dump(midi_file_name); + } + #endif + + MemoryStream_Write(&midi_file_stream, &input_midi_file); + midi_file_stream.Rewind(); + } + + // + // Parse midi stream + // + DynamicMemoryStream control_event_stream; + CreateAudioControlEventStream midi_parser; + + Check(&midi_file_stream); + Check(&control_event_stream); + Check(&midi_parser); + midi_parser.Parse(&midi_file_stream, &control_event_stream, tempo); + control_event_stream.Rewind(); + + // + // Write the divisions per beat and tempo + // + AudioDivisionsPerBeat divisions_per_beat; + + divisions_per_beat = midi_parser.GetDivisionsPerBeat(); + tempo = midi_parser.GetTempo(); + MemoryStream_Write(stream, &divisions_per_beat); + MemoryStream_Write(stream, &tempo); + + // + // Write control event stream + // + CollectionSize number_of_control_events; + + number_of_control_events = midi_parser.GetNumberOfEvents(); + MemoryStream_Write(stream, &number_of_control_events); + MemoryStream_Write(stream, &control_event_stream); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlSequence::TestInstance() const +{ + AudioComponent::TestInstance(); + + Check(&audioComponentSocket); + Check(&audioControlEventSocket); + if (isRunning) + { + Check(audioControlEventIterator); + } + else + { + Verify(audioControlEventIterator == NULL); + } + Verify(tempo >= 1 && tempo <= 600); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::StartSequence() +{ + Check(this); + + // + // If already running, stop sequence + // + if (isRunning) + { + StopSequence(); + } + + // + // Make an iterator for the control sequence + // + Verify(audioControlEventIterator == NULL); + audioControlEventIterator = + new AudioControlEventIterator(&audioControlEventSocket); + Register_Object(audioControlEventIterator); + + startTime = AudioTime::Now(); + isRunning = True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::StopSequence() +{ + Check(this); + + // + // If not running, return + // + if (!isRunning) + return; + + // + // Find next on or off event + // + AudioControlEvent *control_event; + + Check(audioControlEventIterator); + while ((control_event = audioControlEventIterator->ReadAndNext()) != NULL) + { + Check(control_event); + if (!control_event->Chase(audioComponentSocket.GetCurrent())) + break; + } + + // + // Destroy the iterator for the control sequence + // + Unregister_Object(audioControlEventIterator); + delete audioControlEventIterator; + audioControlEventIterator = NULL; + + isRunning = False; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::RunSequence() +{ + Check(this); + + // + // If the sequence is not running, then return + // + if (!isRunning) + return; + + // + // Play events which have a start time less then the + // current time + // + AudioControlEvent *control_event; + + Check(audioControlEventIterator); + control_event = audioControlEventIterator->GetCurrent(); + while ( + control_event != NULL && + IsEventReady(control_event) + ) + { + #if DEBUG_LEVEL>0 + if (dumpValue) + { + Dump(*control_event); + } + #endif + + #if 0 + // + // HACK - convert start control to use duration + // + Verify(control_event->audioControlID != StopAudioControlID); + if (control_event->audioControlID == StartAudioControlID) + { + // + // Convert ticks to seconds + // seconds = ticks / (divisionsPerBeat (t/b) * tempo (b/60s)) + // + Scalar denominator = + (Scalar)divisionsPerBeat * (Scalar)tempo / 60.0f; + Verify(!Small_Enough(denominator)); + control_event->audioControlValue = + control_event->audioControlValue / denominator; + } + #endif + + // + // Send the controller to the connected audio component + // + Check(control_event); + control_event->Send(audioComponentSocket.GetCurrent()); + + // + // Step to next event + // + audioControlEventIterator->Next(); + control_event = audioControlEventIterator->GetCurrent(); + } + + // + // If there are no more events to be played then stop running + // + if (control_event == NULL) + { + StopSequence(); + if (isLooped) + { + StartSequence(); + } + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + switch(control_ID) + { + case StartAudioControlID: + StartSequence(); + break; + + case StopAudioControlID: + StopSequence(); + break; + + case IdleAudioControlID: + RunSequence(); + break; + + case TempoAudioControlID: + tempo = control_value; + Verify(tempo >= 1 && tempo <= 600); + break; + + default: + break; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlSequence::IsEventReady(AudioControlEvent *audio_control_event) +{ + Check(this); + + AudioTime offset_time(startTime); + offset_time += CalculateEventSeconds(audio_control_event); + return (offset_time <= AudioTime::Now()); +} + +// +//############################################################################# +//############################################################################# +// +Scalar + AudioControlSequence::CalculateEventSeconds( + AudioControlEvent *audio_control_event + ) +{ + Check(this); + Check(audio_control_event); + + // + // Convert ticks to seconds + // seconds = ticks / (divisionsPerBeat (t/b) * tempo (b/60s)) + // + Scalar denominator = (Scalar)divisionsPerBeat * (Scalar)tempo / 60.0f; + Verify(!Small_Enough(denominator)); + return (Scalar)audio_control_event->GetStartTick() / denominator; +} + +//############################################################################# +//#################### CreateAudioControlEventStream #################### +//############################################################################# + +CreateAudioControlEventStream::CreateAudioControlEventStream(): + audioControlEventSocket(NULL, False) +{ + inputStream = NULL; + outputStream = NULL; + divisionsPerBeat = 120; + tempo = 100; +} + +// +//############################################################################# +//############################################################################# +// +CreateAudioControlEventStream::~CreateAudioControlEventStream(void) +{ + AudioControlEventIterator iterator(&audioControlEventSocket); + Check(&iterator); + iterator.DeletePlugs(); +} + +// +//############################################################################# +//############################################################################# +// +Logical + CreateAudioControlEventStream::TestInstance() const +{ + MidiParse::TestInstance(); + Check(&audioControlEventSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Parse( + MemoryStream *input_stream, + MemoryStream *output_stream, + SignedLongWord tempo_argument + ) +{ + Check(this); + Check(input_stream); + Check(output_stream); + + inputStream = input_stream; + outputStream = output_stream; + + // + // Parse the stream + // + tempo = tempo_argument; + Verify(GetNumberOfEvents() == 0); + MidiParse::Parse(); + + // + // Write the events + // + AudioControlEventIterator iterator(&audioControlEventSocket); + AudioControlEvent *control_event; + + Check(&iterator); + while ((control_event = iterator.ReadAndNext()) != NULL) + { + Check(control_event); + MemoryStream_Write(outputStream, control_event); + } +} + +// +//############################################################################# +//############################################################################# +// +CollectionSize + CreateAudioControlEventStream::GetNumberOfEvents() +{ + Check(this); + + AudioControlEventIterator iterator(&audioControlEventSocket); + Check(&iterator); + return iterator.GetSize(); +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + CreateAudioControlEventStream::Mf_getc() +{ + Check(this); + + unsigned char c; + + MemoryStream_Read(inputStream, &c); + return c; +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_error(char *str) +{ + Check(this); + Check_Pointer(str); + Fail(str); +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_header( + SignedWord, + SignedWord, + SignedWord division + ) +{ + Check(this); + divisionsPerBeat = division; +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_on( + SignedWord channel, + SignedWord pitch, + SignedWord vol + ) +{ + Check(this); + + // + // Interpret vol 0 as note off + // + if (vol == 0) + { + Mf_off(channel, pitch, vol); + return; + } + + // + // Verify that last event was a stop + // + #if DEBUG_LEVEL>0 + { + AudioControlEventIterator iterator(&audioControlEventSocket); + AudioControlEvent *last_control_event; + + iterator.Last(); + if ((last_control_event = iterator.GetCurrent()) != NULL) + { + Check(last_control_event); + Verify(last_control_event->audioControlID == StopAudioControlID); + } + } + #endif + + AudioTick current_ticks = CurTime(); + AudioControlEvent *audio_control_event; + + // + // Add note value event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + NoteAudioControlID, + (Scalar)pitch + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + + // + // Add velocity event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + AttackVolumeAudioControlID, + (Scalar)vol / (Scalar)127 + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + + // + // Add start event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + StartAudioControlID, + 0.0f + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_off( + SignedWord, + SignedWord pitch, + SignedWord + ) +{ + Check(this); + + AudioTick current_ticks = CurTime(); + AudioControlEvent *audio_control_event; + + #if 0 + // + // HACK - convert start control to use duration + // + AudioControlEventIterator + iterator(&audioControlEventSocket); + + iterator.Last(); + audio_control_event = iterator.GetCurrent(); + Check(audio_control_event); + Verify(audio_control_event->audioControlID == StartAudioControlID); + + audio_control_event->audioControlValue = + current_ticks - audio_control_event->startTick; + #else + // + // Add note value event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + NoteAudioControlID, + (Scalar)pitch + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + + // + // Add stop event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + StopAudioControlID, + 0.0f + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_tempo(SignedLongWord) +{ + Check(this); + // tempo = i1; // HACK - Cakewalk appears to produce bogus tempo +} diff --git a/CODE/RP/MUNGA/AUDSEQ.HPP b/CODE/RP/MUNGA/AUDSEQ.HPP new file mode 100644 index 0000000..8ebc47f --- /dev/null +++ b/CODE/RP/MUNGA/AUDSEQ.HPP @@ -0,0 +1,279 @@ +//===========================================================================// +// File: audseq.hpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDSEQ_HPP) +# define AUDSEQ_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + +# if !defined(AUDMIDI_HPP) +# include +# endif + +# if !defined(VCHAIN_HPP) +# include +# endif + +# if !defined(AUDTIME_HPP) +# include +# endif + + //########################################################################## + //####################### AudioControlEvent ########################## + //########################################################################## + + class AudioControlEvent: + public Plug + { + friend MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + AudioControlEvent *control_event + ); + + friend MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const AudioControlEvent *control_event + ); + + public: + AudioControlEvent( + AudioTick start_tick, + AudioControlID audio_control_ID, + AudioControlValue audio_control_value + ); + AudioControlEvent(); + ~AudioControlEvent(); + + Logical + AudioControlEvent::TestInstance() const; + + AudioTick + GetStartTick() + {return startTick;} + + void + Send(AudioComponent *audio_component); + + Logical + Chase(AudioComponent *audio_component); + + public: + friend ostream& + operator << ( + ostream &strm, + const AudioControlEvent &control_event + ); + + // private: // HACK + AudioTick + startTick; + AudioControlID + audioControlID; + AudioControlValue + audioControlValue; + }; + + //########################################################################## + //####################### AudioControlSequence ####################### + //########################################################################## + + class AudioControlSequence: + public AudioComponent + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + AudioControlSequence( + PlugStream *stream, + Entity *entity + ); + void + AudioControlSequenceX( + AudioComponent *audio_component, + Entity *entity, + Logical is_looped, + AudioDivisionsPerBeat divisions_per_beat, + AudioTempo tempo, + Logical dump_value + ); + ~AudioControlSequence(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Sequence methods + // + public: + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + // + //-------------------------------------------------------------------- + // Sequence control + //-------------------------------------------------------------------- + // + void + StartSequence(); + void + RunSequence(); + void + StopSequence(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + Logical + IsEventReady(AudioControlEvent *audio_control_event); + Scalar + CalculateEventSeconds(AudioControlEvent *audio_control_event); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + typedef SChainOf + AudioControlEventSocket; + typedef SChainIteratorOf + AudioControlEventIterator; + + Logical isLooped; + Logical isRunning; + AudioTime startTime; + AudioDivisionsPerBeat divisionsPerBeat; + AudioTempo tempo; + + SlotOf + audioComponentSocket; + + AudioControlEventSocket + audioControlEventSocket; + AudioControlEventIterator + *audioControlEventIterator; + + #if DEBUG_LEVEL>0 + Logical + dumpValue; + #endif + }; + + //########################################################################## + //################### CreateAudioControlEventStream ################## + //########################################################################## + + class CreateAudioControlEventStream: + public MidiParse + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + CreateAudioControlEventStream(); + ~CreateAudioControlEventStream(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Parsing + // + public: + void + Parse( + MemoryStream *input_stream, + MemoryStream *output_stream, + SignedLongWord tempo=100 + ); + AudioDivisionsPerBeat + GetDivisionsPerBeat() + {return divisionsPerBeat;} + AudioTempo + GetTempo() + {return tempo;} + CollectionSize + GetNumberOfEvents(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Implementations + // + private: + SignedWord + Mf_getc(); + void + Mf_error(char *); + + void + Mf_header(SignedWord,SignedWord,SignedWord); + void + Mf_on(SignedWord,SignedWord,SignedWord); + void + Mf_off(SignedWord,SignedWord,SignedWord); + void + Mf_tempo(SignedLongWord); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + typedef VChainOf + AudioControlEventSocket; + typedef VChainIteratorOf + AudioControlEventIterator; + + MemoryStream + *inputStream; + MemoryStream + *outputStream; + + AudioDivisionsPerBeat + divisionsPerBeat; + AudioTempo + tempo; + + AudioControlEventSocket + audioControlEventSocket; + }; + +#endif diff --git a/CODE/RP/MUNGA/AUDSRC.CPP b/CODE/RP/MUNGA/AUDSRC.CPP new file mode 100644 index 0000000..d7be62f --- /dev/null +++ b/CODE/RP/MUNGA/AUDSRC.CPP @@ -0,0 +1,848 @@ +//===========================================================================// +// File: audsrc.cpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDSRC_HPP) +# include +#endif + +#if !defined(AUDREND_HPP) +# include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSourceStartState ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// + +#define DEFAULT_NOTE (60) + +AudioSourceStartState::AudioSourceStartState() +{ + noteValue = DEFAULT_NOTE; + + isDurationSet = False; + hasDuration = False; + duration = 0.0f; + startTime = 0.0f; + endTime = 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +AudioSourceStartState::~AudioSourceStartState() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioSourceStartState::TestInstance() const +{ + if (isDurationSet || hasDuration) + { + Verify(duration >= 0.0f); + } + if (hasDuration) + { + Verify(endTime >= startTime); + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSourceStartState::CalculateDuration(AudioControlValue control_value) +{ + // + // Calculate duration + // + if (control_value > 0.0f) + { + hasDuration = True; + endTime = AudioTime::Now(); + endTime += control_value; + } + else if (isDurationSet) + { + hasDuration = True; + endTime = AudioTime::Now(); + endTime += duration; + isDurationSet = False; + } + else + { + hasDuration = False; + endTime = 0.0f; + } +} + +#if 0 +// +//############################################################################# +//############################################################################# +// +AudioTime + AudioSourceStartState::GetCurrentRunningTime() +{ + Check(this); + AudioTime current_duration = AudioTime::Now(); + return (current_duration -= startTime); +} +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +const Receiver::HandlerEntry + AudioSource::MessageHandlerEntries[]= +{ + { + AudioSource::StartMessageID, + "Start", + (AudioSource::Handler)&AudioSource::StartMessageHandler + }, + { + AudioSource::StopMessageID, + "Stop", + (AudioSource::Handler)&AudioSource::StopMessageHandler + } +}; + +AudioSource::MessageHandlerSet + AudioSource::MessageHandlers( + ELEMENTS(AudioSource::MessageHandlerEntries), + AudioSource::MessageHandlerEntries, + AudioComponent::MessageHandlers + ); + +// +//############################################################################# +//############################################################################# +// +Derivation + AudioSource::ClassDerivations( + AudioComponent::ClassDerivations, + "AudioSource" + ); + +AudioSource::SharedData + AudioSource::DefaultData( + AudioSource::ClassDerivations, + AudioSource::MessageHandlers + ); + +// +//############################################################################# +//############################################################################# +// +AudioSource::AudioSource( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream, DefaultData) +{ + AudioResource *audio_resource; + AudioLocation *audio_location; + AudioSourcePriority priority; + AudioSourceMixPresence mix_presence; + AudioControlValue volume_mix_level; + AudioPitchCents pitch_mix_offset; + AudioControlValue brightness_mix_level; + Logical has_compression_curve; + Scalar seconds; + AudioTime compression_duration; + Logical use_brightness_scale; + Logical use_attack_time_scale; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource); + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_location); + MemoryStream_Read(stream, &priority); + MemoryStream_Read(stream, &mix_presence); + MemoryStream_Read(stream, &volume_mix_level); + MemoryStream_Read(stream, &pitch_mix_offset); + MemoryStream_Read(stream, &brightness_mix_level); + MemoryStream_Read(stream, &has_compression_curve); + MemoryStream_Read(stream, &seconds); + compression_duration = seconds; + MemoryStream_Read(stream, &use_brightness_scale); + MemoryStream_Read(stream, &use_attack_time_scale); + + AudioSourceX( + audio_resource, + audio_location, + entity, + priority, + mix_presence, + volume_mix_level, + pitch_mix_offset, + brightness_mix_level, + has_compression_curve, + compression_duration, + use_brightness_scale, + use_attack_time_scale + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + CString audio_resource_name("resource"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_resource_name); + + CString audio_location_name("location"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_location_name); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, priority); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, mix_presence); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, volume_mix_level); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioPitchCents, pitch_mix_offset); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, brightness_mix_level); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, has_compression_curve); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, compression_duration); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_brightness_scale); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_attack_time_scale); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AudioSourceX( + AudioResource *audio_resource, + AudioLocation *audio_location, + Entity *entity, + AudioSourcePriority priority, + AudioSourceMixPresence mix_presence, + AudioControlValue volume_mix_level, + AudioPitchCents pitch_mix_offset, + AudioControlValue brightness_mix_level, + Logical has_compression_curve, + const AudioTime &compression_duration, + Logical use_brightness_scale, + Logical use_attack_time_scale + ) +{ + Check(audio_resource); + Check(audio_location); + Check(entity); + + audioLocation = audio_location; + audioResource = audio_resource; + + audioSourceState = StoppedAudioSourceState; + + attackVolumeScale = 1.0f; + useAttackTimeScale = use_attack_time_scale; + attackTimeScale = 0.0f; + + audioSourcePriority = priority; + + audioSourceMixPresence = mix_presence; + volumeCompressionScale = 1.0f; + + hasCompressionCurve = has_compression_curve; + compressionDuration = compression_duration; + + volumeMixScale = volume_mix_level; + pitchMixOffset = pitch_mix_offset; + useBrightnessScale = use_brightness_scale; + brightnessMixScale = brightness_mix_level; + + volumeScale = 1.0f; + pitchOffset = 0.0f; + brightnessScale = 1.0f; + + nextExecuteFrame = NullAudioFrameCount; + suspendFinishedFrame = NullAudioFrameCount; + + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioSource::~AudioSource() +{ + Verify(audioSourceState == StoppedAudioSourceState); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioSource::TestInstance() const +{ + AudioComponent::TestInstance(); + return True; +} + +// +// Resource methods +// + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::SetAudioResource(AudioResource *audio_resource) +{ + Check(this); + Check(audio_resource); + + Verify(audioSourceState == StoppedAudioSourceState); + Check(audioResource); + audioResource = audio_resource; +} + +// +// Current State/Status Accessors +// + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AssignAudioSourceState(AudioSourceState audio_source_state) +{ + Check(this); + + // + // Initialize the next start state if the source is now running + // + if (audio_source_state == RunningAudioSourceState) + { + AudioSourceStartState null_state; + nextStartState = null_state; + } + audioSourceState = audio_source_state; +} + +// +// Mixing & Logical compression methods +// + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioSource::CalculateSourceCompressionEffect() +{ + Check(this); + + // + // Get current volume level + // + AudioControlValue current_volume_level; + + current_volume_level = CalculateSourceVolumeScale(); + Verify(current_volume_level >= 0.0f && current_volume_level <= 1.0f); + + // + // Calculate the amount of this to apply to compression + // + if (hasCompressionCurve) + { + // + // scale = 1 / (1 + ((1/comp_dur) * duration)^2) + // + Scalar current_running_time = GetCurrentRunningTime(); + Scalar compression_duration = compressionDuration; + Scalar duration_factor; + Scalar denominator; + AudioControlValue compression_effect; + + Verify(!Small_Enough(compression_duration)); + duration_factor = + pow((1.0f/compression_duration) * current_running_time, 2.0); + // Warn(!(duration_factor > 0.0f)); + + denominator = 1.0f + duration_factor; + Verify(!Small_Enough(denominator)); + compression_effect = 1.0f / denominator; + Verify(compression_effect >= 0.0f && compression_effect <=1.0f); + + return compression_effect * current_volume_level; + } + return current_volume_level; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioSource::CalculateSourceVolumeScale() +{ + Check(this); + + // + // Execute the watchers that will update the volume related + // member parameters + // + ExecuteWatchers(); + + // + // Calculate the resulting volume scale + // + AudioControlValue + volume_scale; + + volume_scale = volumeScale * volumeMixScale * volumeCompressionScale; + Clamp(volume_scale, MinAudioVolume, MaxAudioVolume); + return volume_scale; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioSource::CalculateSourceBrightnessScale() +{ + Check(this); + + AudioControlValue brightness_mix_scale; + + brightness_mix_scale = brightnessScale * brightnessMixScale; + Clamp(brightness_mix_scale, MinAudioBrightness, MaxAudioBrightness); + + return brightness_mix_scale; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + switch (control_ID) + { + // + //---------------------------------------------------------------------- + // StartAudioControlID + //---------------------------------------------------------------------- + // + case StartAudioControlID: + { + StartMessage message(control_value); + + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->PostAudioRequestMessage( + this, + &message + ); + } + break; + + // + //---------------------------------------------------------------------- + // StopAudioControlID + //---------------------------------------------------------------------- + // + case StopAudioControlID: + { + StopMessage message; + + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->PostAudioRequestMessage( + this, + &message + ); + } + break; + + // + //---------------------------------------------------------------------- + // Misc... + //---------------------------------------------------------------------- + // + case VolumeAudioControlID: + VolumeAudioHandler(control_value); + break; + + case PitchAudioControlID: + PitchAudioHandler(control_value); + break; + + case BrightnessAudioControlID: + BrightnessAudioHandler(control_value); + break; + + case AttackVolumeAudioControlID: + AttackVolumeAudioHandler(control_value); + break; + + case AttackTimeAudioControlID: + AttackTimeAudioHandler(control_value); + break; + + case NoteAudioControlID: + NoteAudioHandler(control_value); + break; + + case DurationAudioControlID: + DurationAudioHandler(control_value); + break; + + case FlushMessagesAudioControlID: + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->FlushAudioMessages(this); + break; + + case NullAudioControlID: + case IdleAudioControlID: + break; + + default: + Fail("AudioSource::ReceiveControl - Should never reach here"); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::StartMessageHandler(StartMessage *message) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_START_HANDLER(); + + Check(this); + Check(message); + Verify(message->messageID == StartMessageID); + + // + //-------------------------------------------------------------------------- + // if double trigger condition exists + // then return + //-------------------------------------------------------------------------- + // + AudioTime double_trigger_cutoff(AudioDoubleTriggerCutoff); + + #if 0 + double_trigger_cutoff = AudioDoubleTriggerCutoff; + #endif + if ( + audioSourceState == RunningAudioSourceState && + GetCurrentRunningTime() <= double_trigger_cutoff + ) + { + #ifdef LAB_ONLY + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->doubleTriggerCount++; + #endif + CLEAR_AUDIO_RENDERER_START_HANDLER(); + CLEAR_AUDIO_RENDERER(); + return; + } + + // + //-------------------------------------------------------------------------- + // If the source is not stopped then stop it + //-------------------------------------------------------------------------- + // + if (audioSourceState != StoppedAudioSourceState) + { + StopMessage stop_message; + StopMessageHandler(&stop_message); + } + + // + //-------------------------------------------------------------------------- + // Verify that the state is stopped + // Copy the next start state into the current start state + // Calculate duration + //-------------------------------------------------------------------------- + // + Verify(audioSourceState == StoppedAudioSourceState); + currentStartState = nextStartState; + currentStartState.CalculateDuration(message->controlValue); + + // + //-------------------------------------------------------------------------- + // Implementation specific start request + //-------------------------------------------------------------------------- + // + StartMessageImplementation(); + + CLEAR_AUDIO_RENDERER_START_HANDLER(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +//############################################################################# +// +void +#if DEBUG_LEVEL>0 + AudioSource::StopMessageHandler(StopMessage *message) +#else + AudioSource::StopMessageHandler(StopMessage*) +#endif +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_STOP_HANDLER(); + + Check(this); + Check(message); + Verify(message->messageID == StopMessageID); + + // + // if the source is stopped + // then return + // + if (audioSourceState == StoppedAudioSourceState) + { + CLEAR_AUDIO_RENDERER_STOP_HANDLER(); + CLEAR_AUDIO_RENDERER(); + return; + } + + // + // Implementation specific stop request + // + StopMessageImplementation(); + + CLEAR_AUDIO_RENDERER_STOP_HANDLER(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::VolumeAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioVolume, MaxAudioVolume); + volumeScale = control_value / (MaxAudioVolume - MinAudioVolume); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::PitchAudioHandler(AudioControlValue control_value) +{ + Check(this); + pitchOffset = control_value; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::BrightnessAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioBrightness, MaxAudioBrightness); + brightnessScale = control_value / (MaxAudioBrightness - MinAudioBrightness); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AttackVolumeAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioAttack, MaxAudioAttack); + attackVolumeScale = control_value / (MaxAudioAttack - MinAudioAttack); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AttackTimeAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioAttack, MaxAudioAttack); + attackTimeScale = control_value / (MaxAudioAttack - MinAudioAttack); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::NoteAudioHandler(AudioControlValue control_value) +{ + Check(this); + nextStartState.SetNoteValue(control_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::DurationAudioHandler(AudioControlValue control_value) +{ + Check(this); + nextStartState.SetDurationValue(control_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::StartImplementation() +{ + currentStartState.Start(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::StopImplementation() +{ + Fail("AudioSource::StopImplementation - Should never reach here"); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::SuspendImplementation() +{ + StopImplementation(); + Check(application); + Check(application->GetAudioRenderer()); + Check(audioResource); + suspendFinishedFrame = + application->GetAudioRenderer()->GetAudioFrameCount() + + audioResource->GetSuspendDelay(); + #ifdef LAB_ONLY + application->GetAudioRenderer()->sourceSuspendCount++; + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::ResumeImplementation() +{ + StartImplementation(); + suspendFinishedFrame = NullAudioFrameCount; + #ifdef LAB_ONLY + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->sourceResumeCount++; + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::Execute() +{ + Check(this); + + // + // Execute source if this is the next execution frame + // + AudioRenderer + *audio_renderer; + + Check(application); + audio_renderer = application->GetAudioRenderer(); + Check(audio_renderer); + if (nextExecuteFrame <= audio_renderer->GetAudioFrameCount()) + { + nextExecuteFrame = + audio_renderer->GetAudioFrameCount() + DefaultAudioFrameDelay; + + // + // Update the sources spatial model + // Execute inherited method + // Execute this sources sound model + // + UpdateSpatialModel(audio_renderer->GetAudioHead()); + AudioComponent::Execute(); + ExecuteModel(False); + } +} + diff --git a/CODE/RP/MUNGA/AUDSRC.HPP b/CODE/RP/MUNGA/AUDSRC.HPP new file mode 100644 index 0000000..f5ccde1 --- /dev/null +++ b/CODE/RP/MUNGA/AUDSRC.HPP @@ -0,0 +1,699 @@ +//===========================================================================// +// File: audsrc.hpp // +// Project: MUNGA Brick: Audio manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDSRC_HPP) +# define AUDSRC_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + +# if !defined(AUDLOC_HPP) +# include +# endif + +# if !defined(AUDLVL_HPP) +# include +# endif + +# if !defined(AUDWGT_HPP) +# include +# endif + +# if !defined(AUDTIME_HPP) +# include +# endif + + //########################################################################## + //##################### AudioSourceStartState ######################## + //########################################################################## + + class AudioSourceStartState SIGNATURED + { + public: + AudioSourceStartState(); + ~AudioSourceStartState(); + + Logical + TestInstance() const; + + void + CalculateDuration(AudioControlValue control_value); + Logical + IsFinishedPlaying(); + AudioTime + GetCurrentRunningTime(); + + void + SetNoteValue(AudioControlValue note_value) + {noteValue = note_value;} + AudioControlValue + GetNoteValue() + {return noteValue;} + void + SetDurationValue(AudioControlValue duration_value); + void + Start() + {startTime = AudioTime::Now();} + + private: + AudioControlValue + noteValue; + + Logical + isDurationSet; + Logical + hasDuration; + Scalar + duration; + AudioTime + startTime; + AudioTime + endTime; + }; + + //~~~~~~~~~~~~~~~~~~~~~ AudioSourceStartState inlines ~~~~~~~~~~~~~~~~~~~~~~ + + inline Logical + AudioSourceStartState::IsFinishedPlaying() + { + Check(this); + if (hasDuration) + { + return (AudioTime::Now() > endTime); + } + return False; + } + + inline void + AudioSourceStartState::SetDurationValue(AudioControlValue duration_value) + { + Check(this); + isDurationSet = True; + duration = duration_value; + } + + inline AudioTime + AudioSourceStartState::GetCurrentRunningTime() + { + Check(this); + return (AudioTime::Now() - startTime); + } + + //########################################################################## + //######################### AudioSource ############################## + //########################################################################## + + class AudioSource__RequestMessage; + class AudioSource__StartMessage; + class AudioSource__StopMessage; + + class AudioSource: + public AudioComponent + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + AudioSource( + PlugStream *stream, + Entity *entity + ); + void + AudioSource::AudioSourceX( + AudioResource *audio_resource, + AudioLocation *audio_location, + Entity *entity, + AudioSourcePriority priority, + AudioSourceMixPresence mix_presence, + AudioControlValue volume_mix_level, + AudioPitchCents pitch_mix_offset, + AudioControlValue brightness_mix_level, + Logical has_compression_curve, + const AudioTime &compression_duration, + Logical use_brightness_scale, + Logical use_attack_time_scale + ); + ~AudioSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Location methods + // + public: + AudioLocation* + GetAudioLocation(); + void + UpdateSpatialModel(AudioHead *audio_head); + Scalar + GetDistanceToSource(); + Logical + IsAudioSourceClipped(AudioHead *audio_head); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Resource methods + // + public: + void + SetAudioResource(AudioResource *audio_resource); + AudioResource* + GetAudioResource(); + + AudioVoiceCount + GetAudioVoiceCount(); + AudioRenderType + GetAudioRenderType(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Current State/Status Accessors + // + public: + void + AssignAudioSourceState(AudioSourceState audio_source_state); + AudioSourceState + GetAudioSourceState(); + + Logical + IsFinishedPlaying(); + AudioTime + GetCurrentRunningTime(); + + AudioControlValue + GetCurrentNoteValue(); + AudioControlValue + CalculateSourceAttackVolumeScale(); + Logical + UseSourceAttackTime(); + AudioControlValue + CalculateSourceAttackTime(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Priority Accessors + // + public: + void + SetAudioSourcePriority(AudioSourcePriority audio_source_priority); + AudioSourcePriority + GetAudioSourcePriority(); + + AudioWeighting + CalculateAudioWeighting(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Mixing & Logical compression methods + // + public: + AudioSourceMixPresence + GetAudioSourceMixPresence(); + + void + SetVolumeCompressionScale(AudioControlValue compression_scale); + AudioControlValue + CalculateSourceCompressionEffect(); + + virtual AudioControlValue + CalculateSourceVolumeScale(); + virtual AudioPitchCents + CalculateSourcePitchOffset(); + Logical + UseSourceBrightnessScale(); + virtual AudioControlValue + CalculateSourceBrightnessScale(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Controller methods + // + public: + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + virtual void + VolumeAudioHandler(AudioControlValue); + virtual void + PitchAudioHandler(AudioControlValue); + virtual void + BrightnessAudioHandler(AudioControlValue); + virtual void + AttackVolumeAudioHandler(AudioControlValue); + virtual void + AttackTimeAudioHandler(AudioControlValue); + virtual void + NoteAudioHandler(AudioControlValue); + virtual void + DurationAudioHandler(AudioControlValue); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State implementations + // + public: + virtual void + StartImplementation(); + virtual void + StopImplementation(); + + virtual void + SuspendImplementation(); + virtual void + ResumeImplementation(); + + protected: + virtual void + StartMessageImplementation() {} + virtual void + StopMessageImplementation() {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Execution + // + public: + Logical + RequiresMaintenance(AudioHead *audio_head); + Logical + CanResume(AudioHead *audio_head); + void + Execute(); + + protected: + virtual void + ExecuteModel(Logical force_update) {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum { + StartMessageID = AudioComponent::NextMessageID, + StopMessageID, + NextMessageID + }; + + typedef AudioSource__RequestMessage + RequestMessage; + typedef AudioSource__StartMessage + StartMessage; + typedef AudioSource__StopMessage + StopMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void + StartMessageHandler(StartMessage *message); + void + StopMessageHandler(StopMessage *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + // + // Location data + // + AudioLocation + *audioLocation; + + // + // Resource data + // + AudioResource + *audioResource; + + // + // State/Status data + // + AudioSourceState + audioSourceState; + + AudioSourceStartState + nextStartState, + currentStartState; + + AudioControlValue + attackVolumeScale; + Logical + useAttackTimeScale; + AudioControlValue + attackTimeScale; + + // + // Priority data + // + AudioSourcePriority + audioSourcePriority; + + // + // Mixing and compression + // + AudioSourceMixPresence + audioSourceMixPresence; + AudioControlValue + volumeCompressionScale; + + Logical + hasCompressionCurve; + AudioTime + compressionDuration; + + AudioControlValue + volumeMixScale; + AudioPitchCents + pitchMixOffset; + Logical + useBrightnessScale; + AudioControlValue + brightnessMixScale; + + AudioControlValue + volumeScale; + AudioPitchCents + pitchOffset; + AudioControlValue + brightnessScale; + + // + // Execution + // + AudioFrameCount + nextExecuteFrame; + AudioFrameCount + suspendFinishedFrame; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSource inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // + // Location methods + // + + inline AudioLocation* + AudioSource::GetAudioLocation() + { + Check(this); + return audioLocation; + } + + inline void + AudioSource::UpdateSpatialModel(AudioHead *audio_head) + { + Check(this); + Check(audioLocation); + audioLocation->UpdateSpatialModel(audio_head); + } + + inline Scalar + AudioSource::GetDistanceToSource() + { + Check(this); + Check(audioLocation); + return audioLocation->GetDistanceToSource(); + } + + inline Logical + AudioSource::IsAudioSourceClipped(AudioHead *audio_head) + { + Check(this); + Check(audioLocation); + return audioLocation->IsAudioLocationClipped(audio_head); + } + + // + // Resource methods + // + + inline AudioResource* + AudioSource::GetAudioResource() + { + Check(this); + return audioResource; + } + + inline AudioVoiceCount + AudioSource::GetAudioVoiceCount() + { + Check(this); + Check(audioResource); + return audioResource->GetVoiceCount(); + } + + inline AudioRenderType + AudioSource::GetAudioRenderType() + { + Check(this); + Check(audioResource); + return audioResource->GetAudioRenderType(); + } + + // + // Current State/Status Accessors + // + + inline AudioSourceState + AudioSource::GetAudioSourceState() + { + Check(this); + return audioSourceState; + } + + inline Logical + AudioSource::IsFinishedPlaying() + { + Check(this); + return currentStartState.IsFinishedPlaying(); + } + + inline AudioTime + AudioSource::GetCurrentRunningTime() + { + Check(this); + Verify(audioSourceState == RunningAudioSourceState); + return currentStartState.GetCurrentRunningTime(); + } + + inline AudioControlValue + AudioSource::GetCurrentNoteValue() + { + Check(this); + return currentStartState.GetNoteValue(); + } + + inline AudioControlValue + AudioSource::CalculateSourceAttackVolumeScale() + { + Check(this); + return attackVolumeScale; + } + + inline Logical + AudioSource::UseSourceAttackTime() + { + Check(this); + return useAttackTimeScale; + } + + inline AudioControlValue + AudioSource::CalculateSourceAttackTime() + { + Check(this); + return attackTimeScale; + } + + // + // Priority Accessors + // + + inline void + AudioSource::SetAudioSourcePriority( + AudioSourcePriority audio_source_priority + ) + { + Check(this); + audioSourcePriority = audio_source_priority; + } + + inline AudioSourcePriority + AudioSource::GetAudioSourcePriority() + { + Check(this); + return audioSourcePriority; + } + + inline AudioWeighting + AudioSource::CalculateAudioWeighting() + { + Check(this); + AudioWeighting + audio_weight( + GetAudioSourcePriority(), + CalculateSourceVolumeScale() + ); + return audio_weight; + } + + // + // Mixing & Logical compression methods + // + + inline AudioSourceMixPresence + AudioSource::GetAudioSourceMixPresence() + { + Check(this); + return audioSourceMixPresence; + } + + inline void + AudioSource::SetVolumeCompressionScale( + AudioControlValue compression_level + ) + { + Check(this); + volumeCompressionScale = compression_level; + } + + inline AudioPitchCents + AudioSource::CalculateSourcePitchOffset() + { + Check(this); + return pitchMixOffset + pitchOffset; + } + + inline Logical + AudioSource::UseSourceBrightnessScale() + { + Check(this); + return useBrightnessScale; + } + + // + // Execute + // + + inline Logical + AudioSource::RequiresMaintenance(AudioHead *audio_head) + { + Check(this); + Check(audio_head); + return (nextExecuteFrame <= audio_head->GetAudioFrameCount()); + } + + inline Logical + AudioSource::CanResume(AudioHead *audio_head) + { + Check(this); + Check(audio_head); + return (suspendFinishedFrame <= audio_head->GetAudioFrameCount()); + } + + //~~~~~~~~~~~~~~~~~~~~~~ AudioSource__RequestMessage ~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioSource__RequestMessage: + public Receiver::Message + { + public: + AudioSource__RequestMessage( + Receiver::MessageID id, + size_t message_length, + AudioControlID control_ID, + AudioControlValue control_value + ); + + AudioControlID + controlID; + AudioControlValue + controlValue; + }; + + inline AudioSource__RequestMessage::AudioSource__RequestMessage( + Receiver::MessageID message_ID, + size_t message_length, + AudioControlID control_ID, + AudioControlValue control_value + ): + Receiver::Message( + message_ID, + message_length + ) + { + controlID = control_ID; + controlValue = control_value; + } + + //~~~~~~~~~~~~~~~~~~~~~~ AudioSource__StartMessage ~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioSource__StartMessage: + public AudioSource::RequestMessage + { + public: + AudioSource__StartMessage(AudioControlValue control_value); + }; + + inline AudioSource__StartMessage::AudioSource__StartMessage( + AudioControlValue control_value + ): + AudioSource::RequestMessage( + AudioSource::StartMessageID, + sizeof(AudioSource__StartMessage), + StartAudioControlID, + control_value + ) + { + } + + //~~~~~~~~~~~~~~~~~~~~~~ AudioSource__StopMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioSource__StopMessage: + public AudioSource::RequestMessage + { + public: + AudioSource__StopMessage(); + }; + + inline AudioSource__StopMessage::AudioSource__StopMessage(): + AudioSource::RequestMessage( + AudioSource::StopMessageID, + sizeof(AudioSource__StopMessage), + StopAudioControlID, + 0.0f + ) + { + } + +#endif diff --git a/CODE/RP/MUNGA/AUDTIME.CPP b/CODE/RP/MUNGA/AUDTIME.CPP new file mode 100644 index 0000000..9084326 --- /dev/null +++ b/CODE/RP/MUNGA/AUDTIME.CPP @@ -0,0 +1,83 @@ +//===========================================================================// +// File: audtime.cpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: Interface declarations for AudioTim // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/08/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDTIME_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(AUDREND_HPP) + #include +#endif + +//############################################################################# +//############################# AudioTime ############################### +//############################################################################# + +const AudioTime + AudioTime::Null; + +// +//############################################################################# +//############################################################################# +// +Logical + AudioTime::TestInstance() const +{ + return True; +} + +// +//############################################################################# +//############################################################################# +// +AudioTime + AudioTime::Now() +{ + Check(application); + Check(application->GetAudioRenderer()); + return AudioTime(application->GetAudioRenderer()->GetAudioFrameCount()); +} + +// +//############################################################################# +//############################################################################# +// +AudioFrameCount + AudioTime::Seconds_To_Frames(Scalar seconds) const +{ + Check(application); + Check(application->GetAudioRenderer()); + return + (seconds * application->GetAudioRenderer()->GetCalibrationRate() + 0.5f); +} + +// +//############################################################################# +//############################################################################# +// +Scalar + AudioTime::Frames_To_Seconds(AudioFrameCount frames) const +{ + Check(application); + Check(application->GetAudioRenderer()); + return + ((Scalar)frames / application->GetAudioRenderer()->GetCalibrationRate()); +} + diff --git a/CODE/RP/MUNGA/AUDTIME.HPP b/CODE/RP/MUNGA/AUDTIME.HPP new file mode 100644 index 0000000..70990f9 --- /dev/null +++ b/CODE/RP/MUNGA/AUDTIME.HPP @@ -0,0 +1,279 @@ +//===========================================================================// +// File: audtime.hpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: Interface declarations for AudioTim // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/08/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDTIME_HPP) +# define AUDTIME_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + + //########################################################################## + //########################## AudioTime ############################### + //########################################################################## + + class AudioTime SIGNATURED + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + AudioTime(); + AudioTime(const AudioTime&); + AudioTime(Scalar seconds); + AudioTime(AudioFrameCount frame_count); + ~AudioTime(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Assignment + // + public: + AudioTime& + operator=(const AudioTime&); + AudioTime& + operator=(Scalar seconds); + AudioTime& + operator=(AudioFrameCount frame_count); + + operator Scalar() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Logical Operators + // + public: + Logical + operator<(const AudioTime&) const; + Logical + operator<=(const AudioTime&) const; + Logical + operator>(const AudioTime&) const; + Logical + operator>=(const AudioTime&) const; + Logical + operator==(const AudioTime&) const; + Logical + operator!=(const AudioTime&) const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Addition Operators + // + public: + operator AudioFrameCount() const; + + AudioTime + operator+(const AudioTime&) const; + AudioTime + operator-(const AudioTime&) const; + + AudioTime& + operator+=(const AudioTime &t); + AudioTime& + operator-=(const AudioTime &t); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public Constants + // + public: + static const AudioTime + Null; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Current Time + // + public: + static AudioTime + Now(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Methods + // + private: + AudioFrameCount + Seconds_To_Frames(Scalar seconds) const; + Scalar + Frames_To_Seconds(AudioFrameCount frames) const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + AudioFrameCount + frameCount; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioTime inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // + // Construction, Destruction, and Testing + // + inline AudioTime::AudioTime(): + frameCount(NullAudioFrameCount) + { + } + + inline AudioTime::AudioTime(const AudioTime &audio_time): + frameCount(audio_time.frameCount) + { + } + + inline AudioTime::AudioTime(Scalar seconds) + { + frameCount = Seconds_To_Frames(seconds); + } + + inline AudioTime::AudioTime(AudioFrameCount frame_count): + frameCount(frame_count) + { + } + + inline AudioTime::~AudioTime() + { + } + + // + // Assignment + // + inline AudioTime& + AudioTime::operator=(const AudioTime &audio_time) + { + Check(this); + Check(&audio_time); + frameCount = audio_time.frameCount; + return *this; + } + + inline AudioTime& + AudioTime::operator=(Scalar seconds) + { + Check(this); + frameCount = Seconds_To_Frames(seconds); + return *this; + } + + inline AudioTime& + AudioTime::operator=(AudioFrameCount frame_count) + { + Check(this); + frameCount = frame_count; + return *this; + } + + inline + AudioTime::operator Scalar() const + { + Check(this); + return Frames_To_Seconds(frameCount); + } + + // + // Logical Operators + // + inline Logical + AudioTime::operator<(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return frameCount < audio_time.frameCount; + } + + inline Logical + AudioTime::operator<=(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return frameCount <= audio_time.frameCount; + } + + inline Logical + AudioTime::operator>(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return frameCount > audio_time.frameCount; + } + + inline Logical + AudioTime::operator>=(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return frameCount >= audio_time.frameCount; + } + + inline Logical + AudioTime::operator==(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return frameCount == audio_time.frameCount; + } + + inline Logical + AudioTime::operator!=(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return frameCount != audio_time.frameCount; + } + + // + // Addition Operators + // + inline AudioTime::operator AudioFrameCount() const + { + Check(this); + return frameCount; + } + + inline AudioTime + AudioTime::operator+(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return AudioTime(frameCount + audio_time.frameCount); + } + + inline AudioTime + AudioTime::operator-(const AudioTime &audio_time) const + { + Check(this); + Check(&audio_time); + return AudioTime(frameCount - audio_time.frameCount); + } + + inline AudioTime& + AudioTime::operator+=(const AudioTime &audio_time) + { + Check(this); + Check(&audio_time); + frameCount += audio_time.frameCount; + return *this; + } + + inline AudioTime& + AudioTime::operator-=(const AudioTime &audio_time) + { + Check(this); + Check(&audio_time); + frameCount -= audio_time.frameCount; + return *this; + } + +#endif diff --git a/CODE/RP/MUNGA/AUDTOOLS.CPP b/CODE/RP/MUNGA/AUDTOOLS.CPP new file mode 100644 index 0000000..641b38b --- /dev/null +++ b/CODE/RP/MUNGA/AUDTOOLS.CPP @@ -0,0 +1,160 @@ +//===========================================================================// +// File: l4audres.cpp // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/10/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDTOOLS_HPP) +# include +#endif + +#include +#include +#include + +#if !defined(AUDIO_HPP) +# include +#endif + +#if !defined(BOXSOLID_HPP) +# include +#endif + +//############################################################################# +//###################### AudioCreateSymbols ############################# +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioCreateSymbols::AudioCreateSymbols() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioCreateSymbols::~AudioCreateSymbols() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCreateSymbols::MakeFileReadWrite(const CString &file_name) +{ + if (access(file_name, 0) == 0) + { + int amode = S_IREAD|S_IWRITE; + #if DEBUG_LEVEL>0 + int ret = + #endif + chmod(file_name, amode); + Verify(ret == 0); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCreateSymbols::Execute() +{ + // + // Make file read/write + // + CString file_name("audio\\symbols.scp"); + + MakeFileReadWrite(file_name); + + // + // Open the file for writing + // + ofstream symbol_file(file_name, ios::out); + + Verify(symbol_file); + symbol_file << "[macro]\n"; + + // + // Audio + // + WriteEntryStream(symbol_file); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCreateSymbols::WriteEntryStream(ofstream &symbol_file) +{ + #define WRITE_ENTRY(name)\ + {\ + Verify(symbol_file);\ + symbol_file << #name;\ + symbol_file << "=";\ + symbol_file << name;\ + symbol_file << "\n";\ + } + + // + // Solids + // + WRITE_ENTRY(BoxedSolid::StoneMaterial); + WRITE_ENTRY(BoxedSolid::GravelMaterial); + WRITE_ENTRY(BoxedSolid::ConcreteMaterial); + WRITE_ENTRY(BoxedSolid::WoodMaterial); + WRITE_ENTRY(BoxedSolid::RockMaterial); + WRITE_ENTRY(BoxedSolid::OurCraftMaterial); + WRITE_ENTRY(BoxedSolid::OtherCraftMaterial); + + // + // Audio + // + WRITE_ENTRY(TransientAudioRenderType); + WRITE_ENTRY(SustainedAudioRenderType); + + WRITE_ENTRY(MinAudioSourcePriority); + WRITE_ENTRY(LowAudioSourcePriority); + WRITE_ENTRY(MedAudioSourcePriority); + WRITE_ENTRY(HighAudioSourcePriority); + WRITE_ENTRY(MaxAudioSourcePriority); + + WRITE_ENTRY(MinAudioSourceMixPresence); + WRITE_ENTRY(LowAudioSourceMixPresence); + WRITE_ENTRY(MedAudioSourceMixPresence); + WRITE_ENTRY(HighAudioSourceMixPresence); + WRITE_ENTRY(MaxAudioSourceMixPresence); + WRITE_ENTRY(ManualAudioSourceMixPresence); + + WRITE_ENTRY(NullAudioControlID); + WRITE_ENTRY(NoteAudioControlID); + WRITE_ENTRY(AttackVolumeAudioControlID); + WRITE_ENTRY(AttackTimeAudioControlID); + WRITE_ENTRY(DurationAudioControlID); + WRITE_ENTRY(VolumeAudioControlID); + WRITE_ENTRY(PitchAudioControlID); + WRITE_ENTRY(BrightnessAudioControlID); + WRITE_ENTRY(StartAudioControlID); + WRITE_ENTRY(StopAudioControlID); + WRITE_ENTRY(IdleAudioControlID); + WRITE_ENTRY(FlushMessagesAudioControlID); + WRITE_ENTRY(TempoAudioControlID); +} + diff --git a/CODE/RP/MUNGA/AUDTOOLS.HPP b/CODE/RP/MUNGA/AUDTOOLS.HPP new file mode 100644 index 0000000..37e76f5 --- /dev/null +++ b/CODE/RP/MUNGA/AUDTOOLS.HPP @@ -0,0 +1,51 @@ +//===========================================================================// +// File: audtools.hpp // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/10/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDTOOLS_HPP) +# define AUDTOOLS_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(CSTR_HPP) +# include +# endif + + //########################################################################## + //##################### AudioCreateSymbols ########################### + //########################################################################## + + class AudioCreateSymbols + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + AudioCreateSymbols(); + ~AudioCreateSymbols(); + + void Execute(); + + private: + static void + MakeFileReadWrite(const CString &file_name); + + protected: + virtual void + WriteEntryStream(ofstream &symbol_file); + }; + +#endif + diff --git a/CODE/RP/MUNGA/AUDWGT.CPP b/CODE/RP/MUNGA/AUDWGT.CPP new file mode 100644 index 0000000..83d72d9 --- /dev/null +++ b/CODE/RP/MUNGA/AUDWGT.CPP @@ -0,0 +1,38 @@ +//===========================================================================// +// File: audwgt.cpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: Implementation for audio weighting // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/02/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDWGT_HPP) +# include +#endif + +//############################################################################# +//########################## AudioWeighting ############################# +//############################################################################# + +const AudioWeighting + AudioWeighting::Null; + +// +//############################################################################# +//############################################################################# +// +Logical + AudioWeighting::TestInstance() const +{ + return True; +} + diff --git a/CODE/RP/MUNGA/AUDWGT.HPP b/CODE/RP/MUNGA/AUDWGT.HPP new file mode 100644 index 0000000..0217da0 --- /dev/null +++ b/CODE/RP/MUNGA/AUDWGT.HPP @@ -0,0 +1,164 @@ +//===========================================================================// +// File: audwgt.hpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: Interface specification for audio weighting // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/02/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDWGT_HPP) + #define AUDWGT_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + + //########################################################################## + //######################## AudioWeighting ############################ + //########################################################################## + + class AudioWeighting SIGNATURED + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + AudioWeighting(); + AudioWeighting(const AudioWeighting&); + AudioWeighting( + AudioSourcePriority audio_priority, + AudioControlValue audio_volume + ); + + AudioWeighting& + operator=(const AudioWeighting&); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Logical Operators + // + public: + Logical + operator<(const AudioWeighting&) const; + Logical + operator<=(const AudioWeighting&) const; + Logical + operator>(const AudioWeighting&) const; + Logical + operator>=(const AudioWeighting&) const; + Logical + operator==(const AudioWeighting&) const; + Logical + operator!=(const AudioWeighting&) const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public Constants + // + public: + static const AudioWeighting + Null; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + Scalar + weight; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioWeighting inlines ~~~~~~~~~~~~~~~~~~~~~~~ + + inline AudioWeighting::AudioWeighting(): + weight(0.0f) + { + } + + inline AudioWeighting::AudioWeighting(const AudioWeighting &audio_weighting): + weight(audio_weighting.weight) + { + } + + inline AudioWeighting::AudioWeighting( + AudioSourcePriority audio_priority, + AudioControlValue audio_volume + ) + { + Verify( + (Enumeration)audio_priority >= 0 && + (Enumeration)audio_priority < AUDIO_SOURCE_PRIORITY_COUNT + ); + Verify( + (Enumeration)audio_priority >= (Enumeration)MinAudioSourcePriority && + (Enumeration)audio_priority <= (Enumeration)MaxAudioSourcePriority + ); + Verify( + audio_volume >= 0.0f && + audio_volume <= 1.0f + ); + weight = 0.0f -(Scalar)audio_priority - audio_volume; + } + + inline AudioWeighting& + AudioWeighting::operator=(const AudioWeighting &audio_weighting) + { + Check(this); + weight = audio_weighting.weight; + return *this; + } + + inline Logical + AudioWeighting::operator<(const AudioWeighting &audio_weighting) const + { + Check(this); + return weight < audio_weighting.weight; + } + + inline Logical + AudioWeighting::operator<=(const AudioWeighting &audio_weighting) const + { + Check(this); + return weight <= audio_weighting.weight; + } + + inline Logical + AudioWeighting::operator>(const AudioWeighting &audio_weighting) const + { + Check(this); + return weight > audio_weighting.weight; + } + + inline Logical + AudioWeighting::operator>=(const AudioWeighting &audio_weighting) const + { + Check(this); + return weight >= audio_weighting.weight; + } + + inline Logical + AudioWeighting::operator==(const AudioWeighting &audio_weighting) const + { + Check(this); + return Close_Enough(weight, audio_weighting.weight, 0.01f); + } + + inline Logical + AudioWeighting::operator!=(const AudioWeighting &audio_weighting) const + { + Check(this); + return !Close_Enough(weight, audio_weighting.weight, 0.01f); + } + +#endif + diff --git a/CODE/RP/MUNGA/AUDWTHR.CPP b/CODE/RP/MUNGA/AUDWTHR.CPP new file mode 100644 index 0000000..54b4f6e --- /dev/null +++ b/CODE/RP/MUNGA/AUDWTHR.CPP @@ -0,0 +1,1072 @@ +//===========================================================================// +// File: audwthr.hh // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/31/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AUDWTHR_HPP) +# include +#endif + +#if !defined(OBJSTRM_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +//############################################################################# +//########################### AudioIdleWatcher ########################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioIdleWatcher::AudioIdleWatcher( + PlugStream *stream, + Entity *entity +): + Component(stream), + audioComponentSocket(this) +{ + AudioComponent *audio_component; + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + AudioIdleWatcherX(audio_component, entity); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::AudioIdleWatcherX( + AudioComponent *audio_component, + Entity *entity + ) +{ + Check(audio_component); + Check(entity); + audioComponentSocket.Add(audio_component); + entity->AddAudioWatcher(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioIdleWatcher::~AudioIdleWatcher() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Component::BuildFromPage(stream, name_list, class_ID, object_ID); + + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioIdleWatcher::TestInstance() const +{ + Component::TestInstance(); + Check(&audioComponentSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::ReleaseLinkHandler( + Socket *socket, + Plug *plug + ) +{ + if (socket == &audioComponentSocket) + { + Check(&audioComponentSocket); + Check(socket); + Unregister_Object(this); + delete this; + } + else + { + Component::ReleaseLinkHandler(socket, plug); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::Execute() +{ + Check(this); + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + IdleAudioControlID, + 0.0f + ); +} + +//############################################################################# +//############################## AudioMotionTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioMotionTrigger::AudioMotionTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + MemoryStream_Read(stream, &motionType); + MemoryStream_Read(stream, &motionValue); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioMotionTrigger::~AudioMotionTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioMotionTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_type); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_value); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioMotionTrigger::ExtractInterestingValue(const Motion *attribute_ptr) +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->linearMotion.x; + case YMotionValue: + return attribute_ptr->linearMotion.y; + case ZMotionValue: + return attribute_ptr->linearMotion.z; + case LengthMotionValue: + return attribute_ptr->linearMotion.Length(); + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->angularMotion.x; + case YMotionValue: + return attribute_ptr->angularMotion.y; + case ZMotionValue: + return attribute_ptr->angularMotion.z; + case LengthMotionValue: + return attribute_ptr->angularMotion.Length(); + } + break; + } + + Fail("AudioMotionTrigger::ExtractInterestingValue - Should never reach here"); + return 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioMotionTrigger::DumpValue(const Motion *attribute_ptr) +#else +void + AudioMotionTrigger::DumpValue(const Motion*) +#endif +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->linearMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->linearMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->linearMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->linearMotion.Length()); + break; + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->angularMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->angularMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->angularMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->angularMotion.Length()); + break; + } + break; + } +} + +//############################################################################# +//############################## AudioMotionScale ####################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioMotionScale::AudioMotionScale( + PlugStream *stream, + Entity *entity +): + AudioScaleOf(stream, entity) +{ + MemoryStream_Read(stream, &motionType); + MemoryStream_Read(stream, &motionValue); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioMotionScale::~AudioMotionScale() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioMotionScale::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioScaleOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_type); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_value); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioMotionScale::ExtractInterestingValue(const Motion *attribute_ptr) +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->linearMotion.x; + case YMotionValue: + return attribute_ptr->linearMotion.y; + case ZMotionValue: + return attribute_ptr->linearMotion.z; + case LengthMotionValue: + return attribute_ptr->linearMotion.Length(); + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->angularMotion.x; + case YMotionValue: + return attribute_ptr->angularMotion.y; + case ZMotionValue: + return attribute_ptr->angularMotion.z; + case LengthMotionValue: + return attribute_ptr->angularMotion.Length(); + } + break; + } + + Fail("AudioMotionScale::ExtractInterestingValue - Should never reach here"); + return 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioMotionScale::DumpValue(const Motion *attribute_ptr) +#else +void + AudioMotionScale::DumpValue(const Motion*) +#endif +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->linearMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->linearMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->linearMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->linearMotion.Length()); + break; + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->angularMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->angularMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->angularMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->angularMotion.Length()); + break; + } + break; + } +} + +//############################################################################# +//############################## AudioHingeScale ######################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioHingeScale::AudioHingeScale( + PlugStream *stream, + Entity *entity +): + AudioScaleOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioHingeScale::~AudioHingeScale() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioHingeScale::ExtractInterestingValue(const Hinge *attribute_ptr) +{ + Check(this); + Check(attribute_ptr); + return attribute_ptr->rotationAmount; +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioHingeScale::DumpValue(const Hinge *attribute_ptr) +#else +void + AudioHingeScale::DumpValue(const Hinge*) +#endif +{ + Check(this); + Check(attribute_ptr); + Dump(attribute_ptr->rotationAmount); +} + +//############################################################################# +//############################## AudioScalarTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioScalarTrigger::AudioScalarTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioScalarTrigger::~AudioScalarTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioScalarTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioScalarTrigger::ExtractInterestingValue(const Scalar *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//####################### AudioScalarDeltaTrigger ####################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioScalarDeltaTrigger::AudioScalarDeltaTrigger( + PlugStream *stream, + Entity *entity +): + AudioDeltaOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioScalarDeltaTrigger::~AudioScalarDeltaTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioScalarDeltaTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioDeltaOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +//############################################################################# +//############################## AudioScalarScale ####################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioScalarScale::AudioScalarScale( + PlugStream *stream, + Entity *entity +): + AudioScaleOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioScalarScale::~AudioScalarScale() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioScalarScale::ExtractInterestingValue(const Scalar *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//######################### AudioLogicalTrigger ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioLogicalTrigger::AudioLogicalTrigger( + PlugStream *stream, + Entity *entity +): + AudioMatchOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioLogicalTrigger::~AudioLogicalTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLogicalTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioMatchOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +int + AudioLogicalTrigger::ExtractInterestingValue(const Logical *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//######################### AudioEnumerationTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationTrigger::AudioEnumerationTrigger( + PlugStream *stream, + Entity *entity +): + AudioMatchOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationTrigger::~AudioEnumerationTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioEnumerationTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioMatchOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +int + AudioEnumerationTrigger::ExtractInterestingValue(const Enumeration *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//###################### AudioEnumerationDeltaTrigger ################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationDeltaTrigger::AudioEnumerationDeltaTrigger( + PlugStream *stream, + Entity *entity +): + AudioDeltaOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationDeltaTrigger::~AudioEnumerationDeltaTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioEnumerationDeltaTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioDeltaOf::BuildFromPage( + stream, + name_list, + class_ID, + object_ID + ); +} + +//############################################################################# +//############################# AudioIntegerTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioIntegerTrigger::AudioIntegerTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioIntegerTrigger::~AudioIntegerTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIntegerTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioIntegerTrigger::ExtractInterestingValue(const int *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//###################### AudioControlsButtonTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioControlsButtonTrigger::AudioControlsButtonTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlsButtonTrigger::~AudioControlsButtonTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlsButtonTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage( + stream, + name_list, + class_ID, + object_ID + ); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioControlsButtonTrigger::ExtractInterestingValue( + const ControlsButton *attribute_ptr + ) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//########################### AudioStateWatcher ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioStateWatcher::AudioStateWatcher( + PlugStream *stream, + Entity *entity +): + AudioWatcherOf(stream, entity) +{ + Check_Pointer(attributePointer); + Cast_Object(StateIndicator*, attributePointer)->AddAudioWatcher(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioStateWatcher::~AudioStateWatcher() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateWatcher::SendNotificationOfChange() +{ + Check(this); + + StateIndicator *state_indicator = GetCurrentPointer(); + + Check(state_indicator); + StateChanged( + state_indicator->GetOldState(), + state_indicator->GetState() + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateWatcher::StateChanged( + Enumeration, + Enumeration + ) +{ + Fail("AudioStateWatcher::StateChanged - Should never reach here"); +} + +//############################################################################# +//############################## AudioStateTrigger ###################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioStateTrigger::AudioStateTrigger( + PlugStream *stream, + Entity *entity +): + AudioStateWatcher(stream, entity) +{ + MemoryStream_Read(stream, &triggerState); + MemoryStream_Read(stream, &inverseTrigger); + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + MemoryStream_Read(stream, &excludeTransition); + MemoryStream_Read(stream, &excludeState); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioStateTrigger::~AudioStateTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioStateWatcher::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Write standard fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, trigger_state); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, inverse_trigger); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value); + + // + // Write optional fields + // + Logical exclude_transition = False; + Enumeration exclude_state = 0; + + if ((name_list)->FindData("exclude_state") != NULL) + { + exclude_transition = True; + Check_Pointer((name_list)->FindData("exclude_state")); + Convert_From_Ascii( + (const char *)(name_list)->FindData("exclude_state"), + &exclude_state + ); + } + MemoryStream_Write(stream, &exclude_transition); + MemoryStream_Write(stream, &exclude_state); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateTrigger::StateChanged( + Enumeration old_state, + Enumeration new_state + ) +{ + Check(this); + + // + // If the exclude switch is on then check for the transition + // + if (excludeTransition) + { + if ( + !inverseTrigger && + new_state == triggerState && + old_state == excludeState + ) + { + return; + } + if ( + inverseTrigger && + old_state == triggerState && + new_state == excludeState + ) + { + return; + } + } + + // + // Check for the trigger state + // + if ( + (!inverseTrigger && new_state == triggerState) || + (inverseTrigger && old_state == triggerState) + ) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + controlValue + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlID, + controlValue + ); + #endif + } +} + + diff --git a/CODE/RP/MUNGA/AUDWTHR.HPP b/CODE/RP/MUNGA/AUDWTHR.HPP new file mode 100644 index 0000000..13ae6ca --- /dev/null +++ b/CODE/RP/MUNGA/AUDWTHR.HPP @@ -0,0 +1,1593 @@ +//===========================================================================// +// File: audwthr.hh // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/31/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AUDWTHR_HPP) +# define AUDWTHR_HPP + +# if !defined(WATCHER_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(CONTROLS_HPP) +# include +# endif + +# if !defined(MOTION_HPP) +# include +# endif + + //########################################################################## + //######################## AudioIdleWatcher ########################## + //########################################################################## + + class AudioIdleWatcher: + public Component + { + public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor, Testing + //----------------------------------------------------------------------- + // + AudioIdleWatcher( + PlugStream *stream, + Entity *entity + ); + void + AudioIdleWatcherX( + AudioComponent *audio_component, + Entity *entity + ); + ~AudioIdleWatcher(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // ReleaseLinkHandler + //----------------------------------------------------------------------- + // + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + void + Execute(); + + protected: + // + //----------------------------------------------------------------------- + // Protected data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + }; + + //########################################################################## + //########################### AudioWatcherOf ######################### + //########################################################################## + + template class AudioWatcherOf: + public AttributeWatcherOf + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioWatcherOf( + PlugStream *stream, + Entity *entity + ); + ~AudioWatcherOf(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // ReleaseLinkHandler + //-------------------------------------------------------------------- + // + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + + protected: + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ AudioWatcherOf templates ~~~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioWatcherOf::AudioWatcherOf( + PlugStream *stream, + Entity *entity + ): + AttributeWatcherOf(stream, entity), + audioComponentSocket(this) + { + // + // Get audio component + // + AudioComponent *audio_component; + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + Check(audio_component); + audioComponentSocket.Add(audio_component); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioWatcherOf::~AudioWatcherOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioWatcherOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) + { + AttributeWatcherOf::BuildFromPage( + stream, name_list, class_ID, object_ID + ); + + // + // Store audio_component object ID + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID( + stream, name_list, audio_component_name + ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template Logical + AudioWatcherOf::TestInstance() const + { + AttributeWatcherOf::TestInstance(); + Check(&audioComponentSocket); + return True; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioWatcherOf::ReleaseLinkHandler( + Socket *socket, + Plug *plug + ) + { + if (socket == &audioComponentSocket) + { + Check(&audioComponentSocket); + Check(socket); + Unregister_Object(this); + delete this; + } + else + { + AttributeWatcherOf::ReleaseLinkHandler(socket, plug); + } + } + + //########################################################################## + //########################### AudioTriggerOf ######################### + //########################################################################## + + template class AudioTriggerOf: + public AudioWatcherOf + { + public: + // + //-------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------- + // + AudioTriggerOf( + PlugStream *stream, + Entity *entity + ); + ~AudioTriggerOf(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //-------------------------------------------------------------------- + // SendNotificationOfChange + //-------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + virtual AudioControlValue + ExtractInterestingValue(const T *attribute_ptr); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Scalar + attributeValueThreshold; + Logical + inverseTrigger; + AudioControlID + controlIDOn, + controlIDOff; + AudioControlValue + controlValueOn, + controlValueOff; + Logical + triggerOn; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioTriggerOf templates ~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioTriggerOf::AudioTriggerOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) + { + Check(simulation); + simulation->AddAudioWatcher(this); + + // + // Get other fields + // + MemoryStream_Read(stream, &attributeValueThreshold); + MemoryStream_Read(stream, &inverseTrigger); + + MemoryStream_Read(stream, &controlIDOn); + MemoryStream_Read(stream, &controlIDOff); + + MemoryStream_Read(stream, &controlValueOn); + MemoryStream_Read(stream, &controlValueOff); + + triggerOn = False; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioTriggerOf::~AudioTriggerOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioTriggerOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) + { + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store other fields + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, attribute_value_threshold + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Logical, inverse_trigger + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID_on + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID_off + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_on + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_off + ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioTriggerOf::SendNotificationOfChange() + { + // + // Get current value + // + T *attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + Scalar current_value = ExtractInterestingValue(attribute_ptr); + + if (triggerOn) + { + if ( + (!inverseTrigger && current_value <= attributeValueThreshold) || + (inverseTrigger && current_value >= attributeValueThreshold) + ) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlIDOff, + controlValueOff + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlIDOff, + controlValueOff + ); + #endif + triggerOn = False; + } + } + else + { + if ( + (!inverseTrigger && current_value > attributeValueThreshold) || + (inverseTrigger && current_value < attributeValueThreshold) + ) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlIDOn, + controlValueOn + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlIDOn, + controlValueOn + ); + #endif + triggerOn = True; + } + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template AudioControlValue + AudioTriggerOf::ExtractInterestingValue(const T*) + { + Fail("AudioTriggerOf::ExtractInterestingValue - Should never reach here"); + return 0; + } + + //########################################################################## + //########################### AudioScaleOf ########################### + //########################################################################## + + template class AudioScaleOf: + public AudioWatcherOf + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor + //-------------------------------------------------------------------- + // + AudioScaleOf( + PlugStream *stream, + Entity *entity + ); + ~AudioScaleOf(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //-------------------------------------------------------------------- + // SendNotificationOfChange + //-------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + virtual AudioControlValue + ExtractInterestingValue(const T *attribute_ptr); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Scalar + attributeValueBoundary1, + attributeValueBoundary2; + AudioControlID + controlID; + AudioControlValue + controlValueBoundary1, + controlValueBoundary2; + Scalar + exponent; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioScaleOf templates ~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioScaleOf::AudioScaleOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) + { + // + // Get audio component + // + AudioComponent *audio_component = audioComponentSocket.GetCurrent(); + Check(audio_component); + audio_component->AddWatcher(this); + + // + // Get other fields + // + MemoryStream_Read(stream, &attributeValueBoundary1); + MemoryStream_Read(stream, &attributeValueBoundary2); + + MemoryStream_Read(stream, &controlID); + + MemoryStream_Read(stream, &controlValueBoundary1); + MemoryStream_Read(stream, &controlValueBoundary2); + MemoryStream_Read(stream, &exponent); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioScaleOf::~AudioScaleOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioScaleOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) + { + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store other fields + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Scalar, attribute_value_boundary1 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Scalar, attribute_value_boundary2 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_boundary1 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_boundary2 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Scalar, exponent + ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioScaleOf::SendNotificationOfChange() + { + // + // Get current value + // + T *attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + Scalar current_value = ExtractInterestingValue(attribute_ptr); + + // + // Clamp value within range + // + Scalar min_attribute_boundary = + Min(attributeValueBoundary1, attributeValueBoundary2); + Scalar max_attribute_boundary = + Max(attributeValueBoundary1, attributeValueBoundary2); + + Clamp(current_value, min_attribute_boundary, max_attribute_boundary); + Verify( + current_value >= min_attribute_boundary && + current_value <= max_attribute_boundary + ); + + // + // Calculate scale + // + Verify(!Small_Enough(attributeValueBoundary2 - attributeValueBoundary1)); + Scalar current_scale = + (current_value - attributeValueBoundary1) / + (attributeValueBoundary2 - attributeValueBoundary1); + Verify(current_scale >= -1.0f && current_scale <= 1.0f); + + // + // Apply exponent + // + if (exponent != 1.0f) + { + Scalar old_scale = current_scale; // HACK - for debugging + + current_scale = pow(old_scale, exponent); + + #if DEBUG_LEVEL>0 + if (!(current_scale >= -1.0f && current_scale <= 1.0f)) + { + Dump(old_scale); + Dump(exponent); + Dump(current_scale); + } + #endif + } + Verify(current_scale >= -1.0f && current_scale <= 1.0f); + + // + // Calculate control value + // + AudioControlValue control_value = + current_scale * (controlValueBoundary2 - controlValueBoundary1) + + controlValueBoundary1; + + #if DEBUG_LEVEL>0 + AudioControlValue min_control_boundary = + Min(controlValueBoundary1, controlValueBoundary2); + AudioControlValue max_control_boundary = + Max(controlValueBoundary1, controlValueBoundary2); + + Verify( + control_value >= min_control_boundary && + control_value <= max_control_boundary + ); + #endif + + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + control_value + ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template AudioControlValue + AudioScaleOf::ExtractInterestingValue(const T*) + { + Fail("AudioScaleOf::ExtractInterestingValue - Should never reach here"); + return 0; + } + + //########################################################################## + //########################## AudioMatchOf ############################ + //########################################################################## + + template class AudioMatchOf: + public AudioWatcherOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioMatchOf( + PlugStream *stream, + Entity *entity + ); + ~AudioMatchOf(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // SendNotificationOfChange + //----------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + virtual int + ExtractInterestingValue(const T *attribute_ptr); + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + int + attributeMatchValue; + AudioControlID + controlID; + AudioControlValue + controlValue; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioMatchOf templates ~~~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioMatchOf::AudioMatchOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) + { + Check(simulation); + simulation->AddAudioWatcher(this); + + // + // Get other fields + // + MemoryStream_Read(stream, &attributeMatchValue); + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioMatchOf::~AudioMatchOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioMatchOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) + { + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store other fields + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, int, attribute_match_value + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value + ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioMatchOf::SendNotificationOfChange() + { + // + // Get current value + // + T *attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + int current_value = ExtractInterestingValue(attribute_ptr); + + if (current_value == attributeMatchValue) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + controlValue + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlID, + controlValue + ); + #endif + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template int + AudioMatchOf::ExtractInterestingValue(const T*) + { + Fail("AudioMatchOf::ExtractInterestingValue - Should never reach here"); + return 0; + } + + //########################################################################## + //########################## AudioDeltaOf ############################ + //########################################################################## + + template class AudioDeltaOf: + public AudioWatcherOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioDeltaOf( + PlugStream *stream, + Entity *entity + ); + ~AudioDeltaOf(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // SendNotificationOfChange + //----------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + T + lastValue; + T + deltaTrigger; + AudioControlID + controlID; + AudioControlValue + controlValue; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioDeltaOf templates ~~~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioDeltaOf::AudioDeltaOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) + { + Check(simulation); + simulation->AddAudioWatcher(this); + + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + MemoryStream_Read(stream, &deltaTrigger); + + lastValue = GetCurrentValue(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AudioDeltaOf::~AudioDeltaOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioDeltaOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) + { + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // control_ID, control_value + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value + ); + + // + // delta_value + // + T delta_trigger = SMALL; + + if (name_list->FindData("delta_trigger") != NULL) + { + Convert_From_Ascii( + (const char *)name_list->FindData("delta_trigger"), + &delta_trigger + ); + } + MemoryStream_Write(stream, &delta_trigger); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AudioDeltaOf::SendNotificationOfChange() + { + T *attribute_ptr; + T delta_change; + + attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + delta_change = *attribute_ptr - lastValue; + + if (Abs(delta_change) >= deltaTrigger) + { + lastValue = *attribute_ptr; + + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + controlValue + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlID, + controlValue + ); + #endif + } + } + + //########################################################################## + //########################### AudioMotionTrigger ##################### + //########################################################################## + + enum MotionType + { + LinearMotionType = 0, + AngularMotionType = 1 + }; + + inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + MotionType *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const MotionType *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + + enum MotionValue + { + XMotionValue = 0, + YMotionValue = 1, + ZMotionValue = 2, + LengthMotionValue = 3 + }; + + inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + MotionValue *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const MotionValue *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + + class AudioMotionTrigger: + public AudioTriggerOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioMotionTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioMotionTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Motion *attribute_ptr); + + private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const Motion *attribute_ptr); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + MotionType + motionType; + MotionValue + motionValue; + }; + + //########################################################################## + //########################### AudioMotionScale ####################### + //########################################################################## + + class AudioMotionScale: + public AudioScaleOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioMotionScale( + PlugStream *stream, + Entity *entity + ); + ~AudioMotionScale(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Motion *attribute_ptr); + + private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const Motion *attribute_ptr); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + MotionType + motionType; + MotionValue + motionValue; + }; + + //########################################################################## + //########################### AudioHingeScale ######################### + //########################################################################## + + class AudioHingeScale: + public AudioScaleOf + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioHingeScale( + PlugStream *stream, + Entity *entity + ); + ~AudioHingeScale(); + + protected: + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Hinge *attribute_ptr); + + private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const Hinge *attribute_ptr); + }; + + //########################################################################## + //########################### AudioScalarTrigger ##################### + //########################################################################## + + class AudioScalarTrigger: + public AudioTriggerOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioScalarTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioScalarTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Scalar *attribute_ptr); + }; + + //########################################################################## + //###################### AudioScalarDeltaTrigger ##################### + //########################################################################## + + class AudioScalarDeltaTrigger: + public AudioDeltaOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioScalarDeltaTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioScalarDeltaTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + }; + + //########################################################################## + //########################### AudioScalarScale ######################## + //########################################################################## + + class AudioScalarScale: + public AudioScaleOf + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioScalarScale( + PlugStream *stream, + Entity *entity + ); + ~AudioScalarScale(); + + protected: + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Scalar *attribute_ptr); + }; + + //########################################################################## + //######################## AudioLogicalTrigger ####################### + //########################################################################## + + class AudioLogicalTrigger: + public AudioMatchOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioLogicalTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioLogicalTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + int + ExtractInterestingValue(const Logical *attribute_ptr); + }; + + //########################################################################## + //###################### AudioEnumerationTrigger ##################### + //########################################################################## + + class AudioEnumerationTrigger: + public AudioMatchOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioEnumerationTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioEnumerationTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + int + ExtractInterestingValue(const Enumeration *attribute_ptr); + }; + + //########################################################################## + //################### AudioEnumerationDeltaTrigger ################### + //########################################################################## + + class AudioEnumerationDeltaTrigger: + public AudioDeltaOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioEnumerationDeltaTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioEnumerationDeltaTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + }; + + //########################################################################## + //####################### AudioIntegerTrigger ######################## + //########################################################################## + + class AudioIntegerTrigger: + public AudioTriggerOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioIntegerTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioIntegerTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const int *attribute_ptr); + }; + + //########################################################################## + //################### AudioControlsButtonTrigger ##################### + //########################################################################## + + class AudioControlsButtonTrigger: + public AudioTriggerOf + { + public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioControlsButtonTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioControlsButtonTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const ControlsButton *attribute_ptr); + }; + + //########################################################################## + //######################## AudioStateWatcher ######################### + //########################################################################## + + class AudioStateWatcher: + public AudioWatcherOf + { + public: + // + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + // + ~AudioStateWatcher(); + + protected: + // + //-------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------- + // + AudioStateWatcher( + PlugStream *stream, + Entity *entity + ); + + // + //-------------------------------------------------------------------- + // SendNotificationOfChange + //-------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //-------------------------------------------------------------------- + // StateChanged + //-------------------------------------------------------------------- + // + virtual void + StateChanged( + Enumeration old_state, + Enumeration new_state + ); + }; + + //########################################################################## + //########################### AudioStateTrigger ###################### + //########################################################################## + + class AudioStateTrigger: + public AudioStateWatcher + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor + //-------------------------------------------------------------------- + // + AudioStateTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioStateTrigger(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //-------------------------------------------------------------------- + // StateChanged + //-------------------------------------------------------------------- + // + void + StateChanged( + Enumeration old_state, + Enumeration new_state + ); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Enumeration + triggerState; + Logical + inverseTrigger; + AudioControlID + controlID; + AudioControlValue + controlValue; + Logical + excludeTransition; + Enumeration + excludeState; + }; + +#endif + + diff --git a/CODE/RP/MUNGA/AVERAGE.CPP b/CODE/RP/MUNGA/AVERAGE.CPP new file mode 100644 index 0000000..97e3dcc --- /dev/null +++ b/CODE/RP/MUNGA/AVERAGE.CPP @@ -0,0 +1,21 @@ +//===========================================================================// +// File: average.cpp // +// Project: MUNGA Brick: Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(AVERAGE_HPP) +# include +#endif + diff --git a/CODE/RP/MUNGA/AVERAGE.HPP b/CODE/RP/MUNGA/AVERAGE.HPP new file mode 100644 index 0000000..08704ad --- /dev/null +++ b/CODE/RP/MUNGA/AVERAGE.HPP @@ -0,0 +1,317 @@ +//===========================================================================// +// File: average.hpp // +// Project: MUNGA Brick: Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(AVERAGE_HPP) +# define AVERAGE_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + //########################################################################## + //########################### AverageOf ############################## + //########################################################################## + + template class AverageOf SIGNATURED + { + public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor, Testing + //----------------------------------------------------------------------- + // + AverageOf(); + AverageOf( + size_t size, + T initial=(T)0 + ); + ~AverageOf(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // SetSize + //----------------------------------------------------------------------- + // + void + SetSize( + size_t size, + T initial=(T)0 + ); + + // + //----------------------------------------------------------------------- + // Add + //----------------------------------------------------------------------- + // + void + Add(T value); + + // + //----------------------------------------------------------------------- + // CalculateAverage + //----------------------------------------------------------------------- + // + T + CalculateAverage(); + + // + //----------------------------------------------------------------------- + // CalculateOlympicAverage + //----------------------------------------------------------------------- + // + T + CalculateOlympicAverage(); + + // + //----------------------------------------------------------------------- + // Calculate Trend of Average + //----------------------------------------------------------------------- + // + Scalar + CalculateTrend(); + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + size_t size; + size_t next; + T *array; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AverageOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AverageOf::AverageOf() + { + array = NULL; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AverageOf::AverageOf( + size_t the_size, + T initial + ) + { + array = NULL; + SetSize(the_size, initial); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AverageOf::SetSize( + size_t the_size, + T initial + ) + { + if (array != NULL) + { + Unregister_Pointer(array); + delete[] array; + } + + size = the_size; + array = new T[size]; + Register_Pointer(array); + next = 0; + + for (size_t i = 0; i < size; i++) + { + Check_Pointer(array); + Verify(i < size); + array[i] = initial; + Check_Fpu(); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AverageOf::~AverageOf() + { + Unregister_Pointer(array); + delete[] array; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template Logical + AverageOf::TestInstance() const + { + Check_Pointer(array); + Verify(next < size); + return True; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AverageOf::Add(T value) + { + Check(this); + Check_Pointer(array); + Verify(next < size); + array[next] = value; + ++next; + if (next >= size) + { + Verify(next == size); + next = 0; + } + Check_Fpu(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template T + AverageOf::CalculateAverage() + { + Check(this); + size_t i; + T accumulate; + + for (i = 0, accumulate = (T)0; i < size; i++) + { + Check_Pointer(array); + Verify(i < size); + accumulate += array[i]; + Check_Fpu(); + } + + Verify(!Small_Enough((T)size)); + return (accumulate / (T)size); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template T + AverageOf::CalculateOlympicAverage() + { + Check(this); + size_t i; + T accumulate, min_value, max_value; + + Verify(0 < size); + min_value = array[0]; + max_value = array[0]; + Check_Fpu(); + + for (i = 0, accumulate = (T)0; i < size; i++) + { + Check_Pointer(array); + Verify(i < size); + accumulate += array[i]; + Check_Fpu(); + + min_value = Min(array[i], min_value); + max_value = Max(array[i], max_value); + Check_Fpu(); + } + accumulate -= min_value; + accumulate -= max_value; + Check_Fpu(); + + Verify(!Small_Enough((T)(size - 2))); + return (accumulate / (T)(size - 2)); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template Scalar + AverageOf::CalculateTrend() + { + Check(this); + size_t i; + Scalar f = 0.0f; + Scalar fx = 0.0f; + Scalar x1 = size; + Scalar x2 = x1*x1/2.0f; + Scalar x3 = x2 + x1*x1*x1/3.0f + x1/6.0f; + x2 += x1/2.0f; + + i = next; + Scalar t = 1.0f; + do + { + f += array[i]; + fx += t*array[i]; + t += 1.0f; + if (++i == size) + { + i = 0; + } + } while (i != next); + return (x1*fx - x2*f) / (x1*x3 - x2*x2); + } + + //########################################################################## + //######################## StaticAverageOf ########################### + //########################################################################## + + template class StaticAverageOf SIGNATURED + { + public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor, Testing + //----------------------------------------------------------------------- + // + StaticAverageOf() + {size = (T)0; total = (T)0;} + ~StaticAverageOf() + {} + + Logical + TestInstance() const + {return True;} + + // + //----------------------------------------------------------------------- + // Add + //----------------------------------------------------------------------- + // + void + Add(T value) + {Check(this); size++; total += value;} + + // + //----------------------------------------------------------------------- + // CalculateAverage + //----------------------------------------------------------------------- + // + T + CalculateAverage() + {Check(this); return (size == 0) ? ((T)0) : (total / (T)size);} + + // + //----------------------------------------------------------------------- + // GetSize + //----------------------------------------------------------------------- + // + size_t + GetSize() + {Check(this); return size;} + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + size_t size; + T total; + }; + +#endif diff --git a/CODE/RP/MUNGA/BNDGBOX.CPP b/CODE/RP/MUNGA/BNDGBOX.CPP new file mode 100644 index 0000000..c6f5235 --- /dev/null +++ b/CODE/RP/MUNGA/BNDGBOX.CPP @@ -0,0 +1,458 @@ +//===========================================================================// +// File: bndgbox.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box based spatialization // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/08/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BNDGBOX_HPP) +# include +#endif + +#if !defined(ORIGIN_HPP) + #include +#endif + +#if !defined(LINE_HPP) + #include +#endif + +//############################################################################# +//############################## BoundingBox ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox::BoundingBox(const ExtentBox &extents): + ExtentBox(extents) +{ + Check_Pointer(this); + Check(&extents); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox::BoundingBox() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void + BoundingBox::PlaceBoundingBox(const Origin& origin) +{ + Check(this); + Check(&origin); + + Dump(origin); + + minX += origin.linearPosition.x; + maxX += origin.linearPosition.x; + minY += origin.linearPosition.y; + maxY += origin.linearPosition.y; + minZ += origin.linearPosition.z; + maxZ += origin.linearPosition.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox::~BoundingBox() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::Intersects(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + if (ExtentBox::Intersects(extents)) + { + ExtentBox slice; + slice.Intersect(*this, extents); + return IntersectsBounded(slice); + } + else + { + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::Intersects( + const ExtentBox &extents, + ExtentBox *slice + ) +{ + Check(this); + Check(&extents); + Check_Pointer(slice); + + if (ExtentBox::Intersects(extents)) + { + slice->Intersect(*this, extents); + return IntersectsBounded(*slice); + } + else + { + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::Contains(const Point3D &point) +{ + Check(this); + Check(&point); + + if (ExtentBox::Contains(point)) + { + return ContainsBounded(point); + } + else + { + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoundingBox::FindDistanceBelow(const Point3D &point) +{ + Check(this); + Check(&point); + + if ( + minX <= point.x && maxX >= point.x && minY <= point.y + && minZ <= point.z && maxZ >= point.z + ) + { + return FindDistanceBelowBounded(point); + } + else + { + return -1.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::HitBy(Line *line) +{ + Check(this); + Check(line); + + Scalar + enter, + leave, + perpendicular, + drift, + distance; + + // + //-------------------- + // Set up for the test + //-------------------- + // + Logical entered = False; + Logical left = False; + for (int i=0; i<6; ++i) + { + // + //-------------------------------------------------------------------- + // Figure out what axis we are dealing with, then based upon the + // direction of the face, find out the distance from the origin to the + // place against the normal, and find out how fast the perpendicular + // distance changes with a unit movement along the line + //-------------------------------------------------------------------- + // + int face = i; + int axis = face >> 1; + if (face&1) + { + perpendicular = line->origin[axis] - (*this)[face]; + drift = line->direction[axis]; + } + else + { + perpendicular = (*this)[face] - line->origin[axis]; + drift = -line->direction[axis]; + } + + // + //------------------------------------------------------------------- + // If the line is parallel to the face, figure out whether or not the + // line origin lies within the face's half-space + //------------------------------------------------------------------- + // + if (Small_Enough(drift)) + { + if (perpendicular > 0.0f) + { + return False; + } + else + { + continue; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + distance = -perpendicular / drift; + if (drift < 0.0f) + { + if (!entered) + { + entered = True; + enter = distance; + } + else if (distance > enter) + { + enter = distance; + } + if (enter > line->length) + { + return False; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + else + { + if (!left) + { + left = True; + leave = distance; + } + else if (distance < leave) + { + leave = distance; + } + if (leave < 0.0f) + { + return False; + } + } + } + + // + //----------------------------------------------------------------------- + // If we exit the loop, then make sure that we actually hit the interior, + // and let the box figure out if the what happens inside it + //----------------------------------------------------------------------- + // + if (enter <= leave) + { + return HitByBounded(line, enter, leave); + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical +#if DEBUG_LEVEL>0 + BoundingBox::IntersectsBounded(const ExtentBox &extents) +#else + BoundingBox::IntersectsBounded(const ExtentBox &) +#endif +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical +#if DEBUG_LEVEL>0 + BoundingBox::ContainsBounded(const Point3D &point) +#else + BoundingBox::ContainsBounded(const Point3D &) +#endif +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoundingBox::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + Scalar result = point.y - maxY; + return Max(result, 0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::HitByBounded( + Line *line, + Scalar enters, +#if DEBUG_LEVEL>0 + Scalar leaves +#else + Scalar +#endif + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::TestInstance() const +{ + return True; +} + +//############################################################################# +//######################### BoundingBoxCollision ######################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxCollision::TestInstance() const +{ + return True; +} + +//############################################################################# +//####################### BoundingBoxCollisionList ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxCollisionList::BoundingBoxCollisionList(int max_length) +{ + listStart = new BoundingBoxCollision[max_length]; + Register_Pointer(listStart); + maxCollisions = max_length; + Reset(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxCollisionList::AddCollisionToList( + BoundingBox *tree_volume, + const ExtentBox &slice + ) +{ + Check(tree_volume); + Check(&slice); + Check(this); + Check_Pointer(nextCollision); + Verify(collisionsLeft); + + nextCollision->treeVolume = tree_volume; + nextCollision->collisionSlice = slice; + ++nextCollision; + --collisionsLeft; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxCollisionList::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################### TaggedBoundingBox ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TaggedBoundingBox::TaggedBoundingBox(void *tag) +{ + tagPointer = tag; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TaggedBoundingBox::TaggedBoundingBox( + const ExtentBox &extents, + void *tag +): + BoundingBox(extents) +{ + tagPointer = tag; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TaggedBoundingBox::~TaggedBoundingBox() +{ +} + +#if defined(TEST_CLASS) +# include "bndgbox.tcp" +#endif + diff --git a/CODE/RP/MUNGA/BNDGBOX.HPP b/CODE/RP/MUNGA/BNDGBOX.HPP new file mode 100644 index 0000000..cea57cb --- /dev/null +++ b/CODE/RP/MUNGA/BNDGBOX.HPP @@ -0,0 +1,214 @@ +//===========================================================================// +// File: bndgbox.hh // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Interface specification of bounding-box based spatialization // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/08/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BNDGBOX_HPP) +# define BNDGBOX_HPP + +# if !defined(EXTNTBOX_HPP) +# include +# endif + + class Line; + class Point3D; + class Origin; + class BoundingBoxTreeNode; + class BoundingBoxList; + class BoundingBoxCollision; + + //########################################################################## + //########################### BoundingBox ############################ + //########################################################################## + + class BoundingBox: + public ExtentBox + { + friend class BoundingBoxTreeNode; + friend class BoundingBoxList; + + public: + BoundingBox(); + BoundingBox(const ExtentBox &extents); + virtual ~BoundingBox(); + + Logical + Intersects(const ExtentBox &extents); + Logical + Intersects( + const ExtentBox &extents, + ExtentBox *slice + ); + Logical + Contains(const Point3D &point); + Scalar + FindDistanceBelow(const Point3D &point); + Logical + HitBy(Line *line); + + void + PlaceBoundingBox(const Origin& origin); + + protected: + virtual Logical + IntersectsBounded(const ExtentBox &extents); + virtual Logical + ContainsBounded(const Point3D &point); + virtual Scalar + FindDistanceBelowBounded(const Point3D &point); + virtual Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + public: + static Logical + TestClass(); + virtual Logical + TestInstance() const; + }; + + //########################################################################## + //###################### BoundingBoxCollision ######################## + //########################################################################## + + class BoundingBoxCollision SIGNATURED + { + public: + BoundingBox + *treeVolume; + ExtentBox + collisionSlice; + + BoundingBox* + GetTreeVolume() + {Check(this); return treeVolume;} + Logical + TestInstance() const; + }; + + //########################################################################## + //#################### BoundingBoxCollisionList ###################### + //########################################################################## + + class BoundingBoxCollisionList SIGNATURED + { + friend class BoundingBoxTreeNode; + friend class BoundingBoxList; + + protected: + BoundingBoxCollision + *listStart, + *nextCollision; + int + maxCollisions, + collisionsLeft; + + public: + BoundingBoxCollisionList(int max_length); + ~BoundingBoxCollisionList() + {Check(this); Unregister_Pointer(listStart); delete[] listStart;} + void + Reset() + {nextCollision = listStart; collisionsLeft = maxCollisions;} + + void + AddCollisionToList( + BoundingBox *tree_volume, + const ExtentBox &slice + ); + + BoundingBoxCollision& + operator[](int index) + { + Check(this); Verify((unsigned)index < maxCollisions); + return listStart[index]; + } + int + GetCollisionCount() + {Check(this); return maxCollisions - collisionsLeft;} + int + GetCollisionsLeft() + {Check(this); return collisionsLeft;} + + Logical + TestInstance() const; + }; + + //########################################################################## + //######################## TaggedBoundingBox ######################### + //########################################################################## + + class TaggedBoundingBox: + public BoundingBox + { + public: + void* + GetTagPointer() + {Check(this); return tagPointer;} + + protected: + TaggedBoundingBox(void *tag = NULL); + TaggedBoundingBox( + const ExtentBox &extents, + void *tag = NULL + ); + ~TaggedBoundingBox(); + + void *tagPointer; + }; + + //########################################################################## + //####################### TaggedBoundingBoxOf ######################## + //########################################################################## + + template class TaggedBoundingBoxOf: + public TaggedBoundingBox + { + public: + TaggedBoundingBoxOf(T *tag); + TaggedBoundingBoxOf( + const ExtentBox &extents, + T *tag = NULL + ); + ~TaggedBoundingBoxOf(); + + T* + GetTagPointer() + {return (T*)tagPointer;} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ TaggedBoundingBoxOf templates ~~~~~~~~~~~~~~~~~~~ + + template + TaggedBoundingBoxOf::TaggedBoundingBoxOf(T *tag): + TaggedBoundingBox(tag) + { + } + + template + TaggedBoundingBoxOf::TaggedBoundingBoxOf( + const ExtentBox &extents, + T *tag + ): + TaggedBoundingBox(extents, tag) + { + } + + template + TaggedBoundingBoxOf::~TaggedBoundingBoxOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/BOXCONE.CPP b/CODE/RP/MUNGA/BOXCONE.CPP new file mode 100644 index 0000000..7beb33e --- /dev/null +++ b/CODE/RP/MUNGA/BOXCONE.CPP @@ -0,0 +1,484 @@ +//===========================================================================// +// File: boxsolid.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(LINE_HPP) +# include +#endif + +//############################################################################# +//############################### BoxedCone ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedCone::BoxedCone( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, ConeType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedCone::~BoxedCone() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //------------------------------------------------------------------------ + // Find the center point in the XZ plane of the cone, and find the biggest + // radius of the cone by measuring in the X axis, along with its height + //------------------------------------------------------------------------ + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = minY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Verify(!Small_Enough(radius)); + + // + //-------------------------------------------------------------------------- + // Convert the closest point in the slice to the coordinates of the cone, + // putting the apex of the cone at the origin, then make sure that the point + // isn't in one of the corners of the box + //-------------------------------------------------------------------------- + // + Vector3D nearest(center); + extents.Constrain(&nearest); + center.y = maxY; + nearest.Subtract(center,nearest); + Scalar r = nearest.x*nearest.x + nearest.z*nearest.z; + if (r > radius*radius) + { + return False; + } + + // + //-------------------------------------------------------------------------- + // Compute the distance from the axis, and then see if the slope of the line + // from the cone apex to the test point is less than the slope of the cone + //-------------------------------------------------------------------------- + // + r = Sqrt(r); + Scalar height = maxY - minY; + return r*height <= nearest.y*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Find the center point in the XZ plane of the cone, and find the biggest + // radius of the cone by measuring in the X axis, along with its height + //------------------------------------------------------------------------ + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = maxY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Verify(!Small_Enough(radius)); + + // + //-------------------------------------------------------------------------- + // Convert the closest point in the slice to the coordinates of the cone, + // putting the apex of the cone at the origin, then make sure that the point + // isn't in one of the corners of the box + //-------------------------------------------------------------------------- + // + Vector3D nearest; + nearest.Subtract(center, point); + Scalar r = nearest.x*nearest.x + nearest.z*nearest.z; + if (r > radius*radius) + { + return False; + } + + // + //-------------------------------------------------------------------------- + // Compute the distance from the axis, and then see if the slope of the line + // from the cone apex to the test point is less than the slope of the cone + //-------------------------------------------------------------------------- + // + r = Sqrt(r); + Scalar height = maxY - minY; + return r*height <= nearest.y*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedCone::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Find the center point in the XZ plane of the cone, and find the biggest + // radius of the cone by measuring in the X axis, along with its height + //------------------------------------------------------------------------ + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = maxY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Verify(!Small_Enough(radius)); + + // + //-------------------------------------------------------------------------- + // Convert the closest point in the slice to the coordinates of the cone, + // putting the apex of the cone at the origin, then make sure that the point + // isn't in one of the corners of the box + //-------------------------------------------------------------------------- + // + Vector3D nearest; + nearest.Subtract(point, center); + Scalar r = nearest.x*nearest.x + nearest.z*nearest.z; + if (r > radius*radius) + { + return -1.0f; + } + + // + //-------------------------------------------------------------------------- + // Compute the distance from the axis, and then see if the slope of the line + // from the cone apex to the test point is less than the slope of the cone + //-------------------------------------------------------------------------- + // + r = Sqrt(r); + Scalar height = maxY - minY; + nearest.y += r*(height/radius); + return Max(nearest.y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// This function is a helper function used in the derivation for the terms of +// the quadratic equation to find t when colliding a line and a cone. I'm not +// real clear on the physical representation of this kind of dot product +// +static Scalar + Special_Cone_Dot_Product( + const Vector3D &v1, + const Vector3D &v2, + Scalar squared_tan + ) +{ + return v1.x*v2.x - squared_tan*v1.y*v2.y + v1.z*v2.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //-------------------------------------------------------------------------- + // Find out the size of the box, and set up the height and maximum radius of + // the cone, along with the squared tangent of the spread angle + //-------------------------------------------------------------------------- + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = maxY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Scalar height = maxY - minY; + Verify(!Small_Enough(height)); + Scalar squared_tan = radius*radius/(height*height); + + // + //------------------------------------------------------------------------- + // Find the line between the point of the cone and the origin of our line, + // then set up the conditions for the quadratic equation. The following + // equation sets up a*t^2 + b*t + c = 0. The terms a, b, and c are derived + // by solving the following equations for t: + // + // p == line->origin + line->direction * t + // r == p - cone->apex + // r.x^2 + r.z^2 == tan^2(cone_angle)*r.y^2 + // + // The special cone dot product function is a handy way to reduce the + // complexity of the problem + //------------------------------------------------------------------------- + // + Vector3D v; + v.Subtract(line->origin,center); + + // + //-------------------------------------------------------------------------- + // If the line diverges from the axis at the same angle as the spread angle, + // we need to find the closest point on the line to the axis. We then drop + // a vertical plane containing the line through the cone at this point, thus + // generating a hyperbola. We then solve the hyperbola vs. line equation to + // get our intersection point + //-------------------------------------------------------------------------- + // + Scalar a = + Special_Cone_Dot_Product(line->direction, line->direction, squared_tan); + if (Small_Enough(a)) + { + } + + // + //----------------------------------------------- + // Otherwise, continue solving the first equation + //----------------------------------------------- + // + else + { + Scalar b = + 2.0f * Special_Cone_Dot_Product(v, line->direction, squared_tan); + Scalar c = Special_Cone_Dot_Product(v, v, squared_tan); + + // + //----------------------------------------------------------------------- + // Now, use the quadratic equation to determine where the two points + // intersect the cone. If there is no solution, than the line missed the + // cone + //----------------------------------------------------------------------- + // + Verify(!Small_Enough(a)); + Scalar t = -b / (2.0f * a); + Scalar i = b*b - 4.0f*a*c; + + if (i < 0.0f) + { + return False; + } + + // + //---------------------------------------------------------------------- + // If the interval is zero, then the line hits the cone in one spot only + // (a tangential hit). Check to see if hits the lower half of the conic + // equation (our cone) + //---------------------------------------------------------------------- + // + if (Small_Enough(i)) + { + Scalar y = v.y + line->direction.y * t; + if (y > 0.0f) + { + return False; + } + + // + //---------------------------------------------------------------- + // It hit the lower cone, so see if it was entering or leaving the + // cone + //---------------------------------------------------------------- + // + if (line->direction.y > 0.0f) + { + // + //------------------------------------------------------------- + // The line is leaving the cone, so see if we need to reset the + // leaving distance + //------------------------------------------------------------- + // + if (t < leaves) + { + leaves = t; + } + } + + // + //------------------------------------------------------------ + // The line is entering the cone, so see if we need to set the + // entering distance + //------------------------------------------------------------ + // + else if (t > enters) + { + enters = t; + } + + // + //------------------------------------------------------------------- + // See if we still have a collision with the cone, and if so, set the + // new line length + //------------------------------------------------------------------- + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //---------------------------------------------------------------------- + // If the interval is non-zero, then the conic section was struck in two + // places. Find out the lengths to those places and the y values for + // those points + //---------------------------------------------------------------------- + // + i = Sqrt(i) / (2.0f * a); + Scalar t1,t2; + if (i > 0.0f) + { + t1 = t - i; + t2 = t + i; + } + else + { + t1 = t + i; + t2 = t - i; + } + Scalar y1 = v.y + line->direction.y * t1; + Scalar y2 = v.y + line->direction.y * t2; + + // + //---------------------------------------------------------------------- + // There are four combinations of the signs of the y values. Each has a + // different effect on missing/hitting, entering or leaving distances. + // First check to see if only the upper conic was hit + //---------------------------------------------------------------------- + // + if (y1 > 0.0f) + { + if (y2 > 0.0f) + { + return False; + } + + // + //----------------------------------------------------------------- + // The ray is entering our conic, so set the distance appropriately + //----------------------------------------------------------------- + // + if (t2 > enters) + { + enters = t2; + } + } + + // + //---------------------------------------------------------------------- + // See if the ray is leaving the lower conic, and if so, set the leaving + // distance accordingly + //---------------------------------------------------------------------- + // + else + { + if (y2 > 0.0f) + { + if (t1 < leaves) + { + leaves = t1; + } + } + + // + //-------------------------------------------------------------------- + // Both spots are in the lower conic, so set both leaving and entering + // distances + //-------------------------------------------------------------------- + // + else + { + if (t1 > enters) + { + enters = t1; + } + if (t2 < leaves) + { + leaves = t2; + } + } + } + + // + //----------------------------------------------------------------------- + // See if we still have a collision with the cone, and if so, set the new + // line length + //----------------------------------------------------------------------- + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + line->length = Max(enters, 0.0f); + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::TestInstance() const +{ + return solidType == ConeType; +} + diff --git a/CODE/RP/MUNGA/BOXDISKS.CPP b/CODE/RP/MUNGA/BOXDISKS.CPP new file mode 100644 index 0000000..ecc3b92 --- /dev/null +++ b/CODE/RP/MUNGA/BOXDISKS.CPP @@ -0,0 +1,1796 @@ +//===========================================================================// +// File: boxdisks.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(LINE_HPP) +# include +#endif + +#if !defined(PLANE_HPP) +# include +#endif + +//############################################################################# +//########################## BoxedXAxisCylinder ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedXAxisCylinder::BoxedXAxisCylinder( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, XAxisCylinderType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedXAxisCylinder::~BoxedXAxisCylinder() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //--------------------------------------------------------------------- + // Find the center point in the YZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the Y axis. The X value will + // automatically be within the cylinder if Y & Z are + //--------------------------------------------------------------------- + // + Scalar y = (minY + maxY) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxY - y; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + Scalar y2 = y; + Scalar z2 = z; + Clamp(y2, extents.minY, extents.maxY); + Clamp(z2, extents.minZ, extents.maxZ); + y2 -= y; + z2 -= z; + return y2*y2 + z2*z2 <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the YZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the Y axis. The X value will + // automatically be within the cylinder if Y & Z are + //--------------------------------------------------------------------- + // + Scalar y = (minY + maxY) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxY - y; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + y -= point.y; + z -= point.z; + return y*y + z*z <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedXAxisCylinder::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxZ - z; + + // + //-------------------------------------------------------------------------- + // figure out the thickness of cylinder slice where a plane perpendicular to + // X drops through the cylinder and the test point + //-------------------------------------------------------------------------- + // + z = point.z - z; + Scalar y = radius - Sqrt(radius*radius - z*z); + if (point.y > maxY - y) + { + return point.y - maxY + y; + } + else if (point.y < minY + y) + { + return -1.0f; + } + else + { + return 0.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + Scalar y = (minY + maxY) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxY - y; + + Scalar a = + line->direction.y*line->direction.y + + line->direction.z*line->direction.z; + + // + //-------------------------------------------------------------------------- + // If the line is parallel to the cylinder, see if it hits the bottom/top of + // the cylinder in the X-Z plane. If it does, it hits the cylinder when it + // hits the box, otherwise it misses altogether + //-------------------------------------------------------------------------- + // + if (Small_Enough(a)) + { + y -= line->origin.y; + z -= line->origin.z; + if (y*y + z*z > radius*radius) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //----------------------------------------------------------------------- + // The line is not parallel to the cylinder, so solve the equation giving + // the intersection of the line with the cylinder using the quadratic + // equation + //----------------------------------------------------------------------- + // + y = line->origin.y - y; + z = line->origin.z - z; + + Scalar b = 2.0f * (line->direction.y*y + line->direction.z*z); + Scalar c = y*y + z*z - radius*radius; + Scalar i = b*b - 4.0f*a*c; + + if (i < SMALL) + { + return False; + } + + // + //------------------------------------------------------------------------- + // If the line does hit the cylinder, update the enter/leaving distances to + // take the cylinder surface into account + //------------------------------------------------------------------------- + // + Verify(a > SMALL); + Scalar ratio = Sqrt(a)/(a*a); + i = Sqrt(i); + b *= -ratio; + i *= ratio; + Scalar enter = (b - i) * 0.5f; + if (enter > enters) + { + enters = enter; + } + + Scalar leave = enter + i; + if (leave < leaves) + { + leaves = leave; + } + + // + //------------------------------------------------------------------------ + // If we have pushed the entering distance after the leaving distance, the + // cylinder was missed, otherwise it is hit at the new entering distance + //------------------------------------------------------------------------ + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::TestInstance() const +{ + return solidType == XAxisCylinderType; +} + +//############################################################################# +//########################## BoxedYAxisCylinder ######################### +//############################################################################# + +enum { + Min_X_Bit = 0x01, + Max_X_Bit = 0x02, + X_Bits = Min_X_Bit|Max_X_Bit, + Min_Y_Bit = 0x04, + Max_Y_Bit = 0x08, + Y_Bits = Min_Y_Bit|Max_Y_Bit, + Min_Z_Bit = 0x10, + Max_Z_Bit = 0x20, + Z_Bits = Min_Z_Bit|Max_Z_Bit, + X_Axis_Bit = 0x04, + Y_Axis_Bit = 0x02, + Z_Axis_Bit = 0x01 +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedYAxisCylinder::BoxedYAxisCylinder( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, YAxisCylinderType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedYAxisCylinder::~BoxedYAxisCylinder() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::VerifyCollision(BoxedSolidCollision &collision) +{ + Check(this); + Check(&collision); + + Verify(minX <= collision.collisionSlice.minX); + Verify(maxX >= collision.collisionSlice.maxX); + Verify(minY <= collision.collisionSlice.minY); + Verify(maxY >= collision.collisionSlice.maxY); + Verify(minZ <= collision.collisionSlice.minZ); + Verify(maxZ >= collision.collisionSlice.maxZ); + + Scalar + x, + z, + their_x, + their_z, + radius, + their_radius; + + BoxedSolid* solid = collision.GetTreeVolume(); + + // + //-------------------------------------------------------------------------- + // See which type of collision we are going to have to verify, and branch to + // it + //-------------------------------------------------------------------------- + // + switch (solid->solidType) + { + + // + //------------------------------------------------------------------------- + // When colliding with a ramp or horizontal cylinder, go ahead and have the + // collision slice assume it is from a block. The error thus generated is + // actually very small and not really noticed by anyone + //------------------------------------------------------------------------- + // + case BlockType: + case SphereType: + case ReducibleBlockType: + case RampFacingNegativeZType: + case RampFacingNegativeXType: + case RampFacingPositiveZType: + case RampFacingPositiveXType: + case InvertedRampFacingNegativeZType: + case InvertedRampFacingNegativeXType: + case InvertedRampFacingPositiveZType: + case InvertedRampFacingPositiveXType: + case WedgeFacingNegativeZAndPositiveXType: + case WedgeFacingNegativeZAndNegativeXType: + case WedgeFacingPositiveZAndNegativeXType: + case WedgeFacingPositiveZAndPositiveXType: + case XAxisCylinderType: + case ZAxisCylinderType: + case RightHandedTileType: + case LeftHandedTileType: + return IntersectsBounded(collision.collisionSlice); + + // + //-------------------------------------------------------------------------- + // When colliding with another upright cylinder, simply calculate the + // distance between the two center points and see if it is less than the sum + // of the two radii + //-------------------------------------------------------------------------- + // + case YAxisCylinderType: + x = (maxX + minX) * 0.5f; + z = (maxZ + minZ) * 0.5f; + radius = maxX - x; + + their_x = (solid->maxX + solid->minX) * 0.5f; + their_z = (solid->maxZ + solid->minZ) * 0.5f; + their_radius = solid->maxX - their_x; + + radius += their_radius; + x -= their_x; + z -= their_z; + + return radius*radius >= x*x + z*z; + + // + //------------------------------------------------------------------------ + // When colliding with a cone, we will base all the calculations on the + // assumption that the collision can be detected identically by a cylinder + // created by the the intersection of the bottom plane of this volume with + // the cone + //------------------------------------------------------------------------ + // + case ConeType: + x = (maxX + minX) * 0.5f; + z = (maxZ + minZ) * 0.5f; + radius = maxX - x; + + their_x = (solid->maxX + solid->minX) * 0.5f; + their_z = (solid->maxZ + solid->minZ) * 0.5f; + their_radius = solid->maxX - their_x; + their_radius *= (solid->maxY - minY) / (solid->maxY - solid->minY); + + radius += their_radius; + x -= their_x; + z -= their_z; + + return radius*radius >= x*x + z*z; + + // + //------------------------------ + // Fail on the unsupported types + //------------------------------ + // + default: + #if defined(LAB_ONLY) + DEBUG_STREAM << collision.GetTreeVolume()->solidType << endl; + Fail("Unsupported collision primative\n"); + #endif + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::ProcessCollision( + BoxedSolidCollision &collision, + const Vector3D &velocity, + BoxedSolidCollisionList *last_collisions, + Normal *normal, + Scalar *penetration + ) +{ + Check(this); + Check(&collision); + Check(&velocity); + Check_Pointer(normal); + Check_Pointer(penetration); + + Scalar + result, + len; + int + i, + ok=0, + axes, + axis, + face, + mask = 0, + opp_face, + temp; + BoxedSolid *solid = collision.GetTreeVolume(); + Vector3D + position; + + // + //----------------------------------------------------- + // First verify that the collision really should happen + //----------------------------------------------------- + // + if (Small_Enough(velocity.LengthSquared())) + { + return False; + } + if (!VerifyCollision(collision)) + { + return False; + } + + // + //------------------------------------------------------------------------ + // Look at each of the three coordinates of motion, and make sure that the + // collision slice is valid for at least one of them + //------------------------------------------------------------------------ + // + for (axis=X_Axis; axis<=Z_Axis; ++axis) + { + // + //------------------------------------------------------------------- + // Make sure we have actual velocity along this axis, then figure out + // which face to test + //------------------------------------------------------------------- + // + (*normal)[axis] = 0.0f; + mask <<= 1; + if (Small_Enough(velocity[axis])) + { + continue; + } + face = (axis<<1) + (velocity[axis]>0.0f); + opp_face = face ^ 1; + + // + //---------------------------------------------------------------------- + // Find out which faces of the cylinder's bounding box should be + // considered for purposes of the collision. Sides are only considered + // valid if the leading face of the collision slice matches the leading + // face of the disk. + //---------------------------------------------------------------------- + // + if ( + collision.collisionSlice[face] == (*this)[face] && + ( + (face&1) && (*this)[opp_face] < collision.collisionSlice[opp_face] + || + !(face&1) + && (*this)[opp_face] > collision.collisionSlice[opp_face] + ) + ) + mask |= 1; + } + + // + //----------------------------------------------------------------- + // Handle the actual collision based upon the type of model and the + // components involved in the collision + //----------------------------------------------------------------- + // + switch (solid->solidType) + { + + // + //-------------------------- + // Handle the Z facing Ramps + //-------------------------- + // + case RampFacingNegativeZType: + normal->y = solid->maxZ - solid->minZ; + normal->z = solid->maxY - solid->minY; + position.y = collision.collisionSlice.minY - solid->maxY; + position.z = collision.collisionSlice.minZ - solid->minZ; + + // + //-------------------------------------------------------------------- + // The normal y and z values are assumed at this point to point in the + // right direction although their lengths are screwed up + //-------------------------------------------------------------------- + // +Compute_X: + len = Sqrt(normal->y*normal->y + normal->z*normal->z); + Verify(!Small_Enough(len)); + normal->y /= len; + normal->z /= len; + Check_Fpu(); + + result = velocity.y*normal->y + velocity.z*normal->z; + if (result > -SMALL) + { + if (mask&X_Axis_Bit) + { + goto X_Only; + } + else + { + break; + } + } + *penetration = + fabs((position.y*normal->y + position.z*normal->z) / result); + Check_Fpu(); + + // + //----------------------------------------------------------------------- + // If the side of the ramp was involved in the collision, pick either the + // ramp or side to reflect off of based upon which opposes motion more + //----------------------------------------------------------------------- + // + if (mask&X_Axis_Bit) + { + // + //---------------------------------------------------------------- + // Compute plane equation and find the distance from the most + // penetrating slice point to the plane. If the ray comes out the + // ramp, we hit that, otherwise we hit the side + //---------------------------------------------------------------- + // + result = fabs((solid->maxX - solid->minX) / velocity.x); + Check_Fpu(); + if (result < *penetration) + { +X_Only: + normal->x = (velocity.x > 0.0f) ? -1.0f : 1.0f; + normal->y = 0.0f; + normal->z = 0.0f; + *penetration = result; + } + } + goto Reflect; + + case RampFacingPositiveZType: + normal->y = solid->maxZ - solid->minZ; + normal->z = solid->minY - solid->maxY; + position.y = collision.collisionSlice.minY - solid->maxY; + position.z = collision.collisionSlice.maxZ - solid->maxZ; + goto Compute_X; + + case InvertedRampFacingNegativeZType: + normal->y = solid->minZ - solid->maxZ; + normal->z = solid->maxY - solid->minY; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.z = collision.collisionSlice.minZ - solid->maxZ; + goto Compute_X; + + case InvertedRampFacingPositiveZType: + normal->y = solid->minZ - solid->maxZ; + normal->z = solid->minY - solid->maxY; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.z = collision.collisionSlice.maxZ - solid->minZ; + goto Compute_X; + + // + //-------------------------- + // Handle the X facing ramps + //-------------------------- + // + case RampFacingNegativeXType: + normal->x = solid->maxY - solid->minY; + normal->y = solid->maxX - solid->minX; + position.y = collision.collisionSlice.minY - solid->maxY; + position.x = collision.collisionSlice.minX - solid->minX; + + // + //-------------------------------------------------------------------- + // The normal x and y values are assumed at this point to point in the + // right direction although their lengths are screwed up + //-------------------------------------------------------------------- + // +Compute_Z: + len = Sqrt(normal->x*normal->x + normal->y*normal->y); + Verify(!Small_Enough(len)); + normal->x /= len; + normal->y /= len; + Check_Fpu(); + + result = velocity.y*normal->y + velocity.x*normal->x; + if (result > -SMALL) + { + if (mask&Z_Axis_Bit) + { + goto Z_Only; + } + else + { + break; + } + } + *penetration = + fabs((position.y*normal->y + position.x*normal->x) / result); + Check_Fpu(); + + // + //----------------------------------------------------------------------- + // If the side of the ramp was involved in the collision, pick either the + // ramp or side to reflect off of based upon which opposes motion more + //----------------------------------------------------------------------- + // + if (mask&Z_Axis_Bit) + { + // + //---------------------------------------------------------------- + // Compute plane equation and find the distance from the most + // penetrating slice point to the plane. If the ray comes out the + // ramp, we hit that, otherwise we hit the side + //---------------------------------------------------------------- + // + result = fabs((solid->maxZ - solid->minZ) / velocity.z); + Check_Fpu(); + if (result < *penetration) + { +Z_Only: + normal->x = 0.0f; + normal->y = 0.0f; + normal->z = (velocity.z > 0.0f) ? -1.0f : 1.0f; + *penetration = result; + } + } + goto Reflect; + + case RampFacingPositiveXType: + normal->x = solid->minY - solid->maxY; + normal->y = solid->maxX - solid->minX; + position.y = collision.collisionSlice.minY - solid->maxY; + position.x = collision.collisionSlice.maxX - solid->maxX; + goto Compute_Z; + + case InvertedRampFacingNegativeXType: + normal->x = solid->maxY - solid->minY; + normal->y = solid->minX - solid->maxX; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.x = collision.collisionSlice.minX - solid->maxX; + goto Compute_Z; + + case InvertedRampFacingPositiveXType: + normal->x = solid->minY - solid->maxY; + normal->y = solid->minX - solid->maxX; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.x = collision.collisionSlice.maxX - solid->minX; + goto Compute_Z; + + // + //------------------ + // Handle the wedges + //------------------ + // + case WedgeFacingNegativeZAndPositiveXType: + normal->x = solid->minZ - solid->maxZ; + normal->z = solid->maxX - solid->minX; + position.x = collision.collisionSlice.maxX - solid->minX; + position.z = collision.collisionSlice.minZ - solid->minZ; + + // + //-------------------------------------------------------------------- + // The normal x and z values are assumed at this point to point in the + // right direction although their lengths are screwed up + //-------------------------------------------------------------------- + // +Compute_Y: + len = Sqrt(normal->x*normal->x + normal->z*normal->z); + Verify(!Small_Enough(len)); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + + result = velocity.x*normal->x + velocity.z*normal->z; + if (result > -SMALL) + { + if (mask&Y_Axis_Bit) + { + goto Y_Only; + } + else + { + break; + } + } + *penetration = + fabs((position.x*normal->x + position.z*normal->z) / result); + Check_Fpu(); + + // + //----------------------------------------------------------------------- + // If the top of the wedge was involved in the collision, pick either the + // side or top to reflect off of based upon which opposes motion more + //----------------------------------------------------------------------- + // + if (mask&Y_Axis_Bit) + { + // + //---------------------------------------------------------------- + // Compute plane equation and find the distance from the most + // penetrating slice point to the plane. If the ray comes out the + // ramp, we hit that, otherwise we hit the side + //---------------------------------------------------------------- + // + result = fabs((solid->maxY - solid->minY) / velocity.y); + Check_Fpu(); + if (result < *penetration) + { +Y_Only: + normal->x = 0.0f; + normal->y = (velocity.y > 0.0f) ? -1.0f : 1.0f; + normal->z = 0.0f; + *penetration = result; + } + } + goto Reflect; + + case WedgeFacingNegativeZAndNegativeXType: + normal->x = solid->maxZ - solid->minZ; + normal->z = solid->maxX - solid->minX; + position.x = collision.collisionSlice.minX - solid->maxX; + position.z = collision.collisionSlice.minZ - solid->minZ; + goto Compute_Y; + + case WedgeFacingPositiveZAndNegativeXType: + normal->x = solid->maxZ - solid->minZ; + normal->z = solid->minX - solid->maxX; + position.x = collision.collisionSlice.minX - solid->minX; + position.z = collision.collisionSlice.maxZ - solid->minZ; + goto Compute_Y; + + case WedgeFacingPositiveZAndPositiveXType: + normal->x = solid->minZ - solid->maxZ; + normal->z = solid->minX - solid->maxX; + position.x = collision.collisionSlice.maxX - solid->maxX; + position.z = collision.collisionSlice.maxZ - solid->minZ; + goto Compute_Y; + + // + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + // + case XAxisCylinderType: + normal->y = minY + maxY - solid->minY - solid->maxY; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->y*normal->y + normal->z*normal->z; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->y /= len; + normal->z /= len; + Check_Fpu(); + *penetration = 1.0f; + goto Reflect; + + case ZAxisCylinderType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->y = minY + maxY - solid->minY - solid->maxY; + len = normal->x*normal->x + normal->y*normal->y; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->x /= len; + normal->y /= len; + Check_Fpu(); + *penetration = 1.0f; + goto Reflect; + + case YAxisCylinderType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->x*normal->x + normal->z*normal->z; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + *penetration = 1.0f; + + if (mask & Y_Axis_Bit) + { + len = (velocity.z > 0.0f) ? -1.0f : 1.0f; + if (len*velocity.y < velocity.x*normal->x + velocity.z*normal->z) + { + normal->x = 0.0f; + normal->y = len; + normal->z = 0.0f; + } + } + goto Reflect; + + // + //------------- + // Handle cones + //------------- + // + case ConeType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->x*normal->x + normal->z*normal->z; + *penetration = 1.0f; + if (Small_Enough(len)) + { + goto Reverse; + } + normal->y = + 0.5f * (solid->maxX - solid->minX) * Sqrt(len) + / (solid->maxY - solid->minY); + Check_Fpu(); + normal->Normalize(*normal); + goto Reflect; + + // + //--------------- + // Handle spheres + //--------------- + // + case SphereType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->y = minY + maxY - solid->minY - solid->maxY; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->x*normal->x + normal->y*normal->y + normal->z*normal->z; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->x /= len; + normal->y /= len; + normal->z /= len; + Check_Fpu(); + *penetration = 1.0f; + goto Reflect; + + // + //--------------------------------- + // Handle reflecting off of a block + //--------------------------------- + // + case BlockType: + case ReducibleBlockType: + + // + //--------------------------------------------------- + // Count the number of axes involved in the collision + //--------------------------------------------------- + // + temp = mask; + for (axes=0; temp; temp>>=1) + { + if (temp&1) + { + ++axes; + } + } + + // + //------------------------------------------------------ + // Handle as appropriate to the number of sides involved + //------------------------------------------------------ + // + switch (axes) + { + + // + //--------------------------------------------------------------------- + // If no sides were found to be involved in the collision, then we have + // a weird case where the disk has completely penetrated through the + // block + //--------------------------------------------------------------------- + // + case 0: + + // + //------------------------------------------------------------------- + // This is where we will check the current volume against our list of + // volumes hit last time. If we have not already hit this solid, + // reverse the motion as we have penetrated the object + //------------------------------------------------------------------- + // + i = 0; + if (last_collisions) + { + for (i=0; iGetCollisionCount(); ++i) + { + if ((*last_collisions)[i].GetTreeVolume() == solid) + { + break; + } + } + } + if (!last_collisions || i == last_collisions->GetCollisionCount()) + { +Reverse: + *penetration = 1.0f; + result = -1.0f / velocity.Length(); + Check_Fpu(); + normal->x = velocity.x*result; + normal->y = velocity.y*result; + normal->z = velocity.z*result; + ok = True; + break; + } + + // + //-------------------------------------------------------------------- + // Since this is not a fresh hit, check to see if any part of the + // colliding disk sticks out of the slice. If so, then we are heading + // out of the solid in that direction, so let the motion continue. + // WHAT IS THE VELOCITY TRIGGER FOR???? + //-------------------------------------------------------------------- + // + position.x = (maxX + minX) * 0.5f; + position.y = (maxY + minY) * 0.5f; + position.z = (maxZ + minZ) * 0.5f; + for (face=0; face<6; ++face) + { + i = face >> 1; + if (face&1) + { + if + ( + (*this)[face] > collision.collisionSlice[face] + && position[i] > collision.collisionSlice[face] + && velocity[i] < 5.0f + ) + break; + } + else if + ( + (*this)[face] < collision.collisionSlice[face] + && position[i] < collision.collisionSlice[face] + && velocity[i] > -5.0f + ) + break; + } + if (face != 6) + { + break; + } + + // + //------------------------------------------------------------------- + // Otherwise, generate a normal opposing motion towards the center of + // the solid. For each component, if it does not oppose motion, zero + // it out. This will give a better approximation of the brick + //------------------------------------------------------------------- + // + normal->x = position.x - (solid->minX + solid->maxX) * 0.5f; + normal->y = position.y - (solid->minY + solid->maxY) * 0.5f; + normal->z = position.z - (solid->minZ + solid->maxZ) * 0.5f; + for (i=0; i<3; ++i) + { + if ((*normal)[i]*velocity[i] >= 0.0) + { + (*normal)[i] = 0.0; + } + } + + // + //---------------------------------------------------------------- + // Normalize the vector, making sure we don't get killed by a zero + // case + //---------------------------------------------------------------- + // + result = normal->Length(); + if (!Small_Enough(result)) + { + normal->x /= result; + normal->y /= result; + normal->z /= result; + Check_Fpu(); + } + else + { + break; + } + *penetration = 1.0f; + goto Reflect; + + // + //----------------------------------------------------------------- + // If only one side is involved in the collision, reflect off of it + //----------------------------------------------------------------- + // + case 1: +Test_Corner: + position.x = 0.5f * (minX + maxX); + position.z = 0.5f * (minZ + maxZ); + switch (mask) + { + case X_Axis_Bit: + face = X_Axis << 1; + + // + //---------------------------------- + // Figure out the z bounce direction + //---------------------------------- + // + if (collision.collisionSlice.minZ > position.z) + { + normal->z = position.z - collision.collisionSlice.minZ; + } + else if (collision.collisionSlice.maxZ < position.z) + { + normal->z = position.z - collision.collisionSlice.maxZ; + } + + // + //---------------------------------- + // Figure out the x bounce direction + //---------------------------------- + // + len = maxX - position.x; + normal->x = len*len - normal->z*normal->z; + Verify(normal->x >= 0.0f); + normal->x = Sqrt(normal->x); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + if (velocity.x > 0.0f) + { + normal->x = -normal->x; + } + break; + + case Y_Axis_Bit: + face = Y_Axis << 1; + *penetration = + fabs( + ( + collision.collisionSlice[face] + - collision.collisionSlice[face^1] + ) / velocity[face>>1] + ); + Check_Fpu(); + goto Pick_Side; + + case Z_Axis_Bit: + face = Z_Axis << 1; + + // + //---------------------------------- + // Figure out the x bounce direction + //---------------------------------- + // + if (collision.collisionSlice.minX > position.x) + { + normal->x = position.x - collision.collisionSlice.minX; + } + else if (collision.collisionSlice.maxX < position.x) + { + normal->x = position.x - collision.collisionSlice.maxX; + } + + // + //---------------------------------- + // Figure out the z bounce direction + //---------------------------------- + // + len = maxX - position.x; + normal->z = len*len - normal->x*normal->x; + Verify(normal->z >= 0.0f); + normal->z = Sqrt(normal->z); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + if (velocity.z > 0.0f) + { + normal->z = -normal->z; + } + break; + } + *penetration = + fabs( + ( + collision.collisionSlice[face] + - collision.collisionSlice[face^1] + ) / velocity[face>>1] + ); + Check_Fpu(); + + // + //------------------------------------------------------------------- + // Check to make sure that the normal opposes velocity. If it + // doesn't look to see if this is the first hit on the object, and if + // so, reverse the velocity + //------------------------------------------------------------------- + // +Reflect: + Check(normal); + ok = *normal * velocity < 0.0f; + if (!ok) + { + i = 0; + if (last_collisions) + { + for (i=0; iGetCollisionCount(); ++i) + { + if ((*last_collisions)[i].GetTreeVolume() == solid) + { + break; + } + } + } + if (!last_collisions || i == last_collisions->GetCollisionCount()) + { + goto Reverse; + } + } + break; + + // + //--------------------------------------------------------------------- + // If two faces were involved, we hit an edge, so figure out which face + // we really hit and mask off the other face + //--------------------------------------------------------------------- + // + case 2: + switch (mask) + { + case X_Axis_Bit|Z_Axis_Bit: + position.x = + collision.collisionSlice.maxX - collision.collisionSlice.minX; + position.z = + collision.collisionSlice.maxZ - collision.collisionSlice.minZ; + mask ^= + (fabs(position.z*velocity.x) > fabs(position.x*velocity.z)) + ? Z_Axis_Bit : X_Axis_Bit; + break; + + case X_Axis_Bit|Y_Axis_Bit: + position.x = + collision.collisionSlice.maxX - collision.collisionSlice.minX; + position.y = + collision.collisionSlice.maxY - collision.collisionSlice.minY; + mask ^= + (fabs(position.y*velocity.x) > fabs(position.x*velocity.y)) + ? Y_Axis_Bit : X_Axis_Bit; + break; + + case Y_Axis_Bit|Z_Axis_Bit: + position.y = + collision.collisionSlice.maxY - collision.collisionSlice.minY; + position.z = + collision.collisionSlice.maxZ - collision.collisionSlice.minZ; + mask ^= + (fabs(position.y*velocity.z) > fabs(position.z*velocity.y)) + ? Y_Axis_Bit : Z_Axis_Bit; + break; + } + goto Test_Corner; + + + // + //----------------------------------------------------------------------- + // Otherwise, project the intruding vertex back along the velocity vector + // to try and find out which face to bounce off of + //----------------------------------------------------------------------- + // + default: + position.x = + collision.collisionSlice.maxX - collision.collisionSlice.minX; + position.y = + collision.collisionSlice.maxY - collision.collisionSlice.minY; + position.z = + collision.collisionSlice.maxZ - collision.collisionSlice.minZ; + + position.x = fabs(position.x/velocity.x); + position.y = fabs(position.y/velocity.y); + position.z = fabs(position.z/velocity.z); + + if (position.x < position.y) + { + face = (position.x < position.z) ? (X_Axis<<1) : (Z_Axis<<1); + } + else + { + face = (position.y < position.z) ? (Y_Axis<<1) : (Z_Axis<<1); + } + *penetration = position[face>>1]; + +Pick_Side: + if (velocity[face>>1] > 0.0f) + { + (*normal)[face>>1] = -1.0f; + } + else + { + (*normal)[face>>1] = 1.0f; + } + goto Reflect; + } + break; + + #if defined(LAB_ONLY) + default: + Fail("Unsupported collision type!...\n"); + break; + #endif + } + + if (ok) + { + Check(normal); + if (*penetration < 0.0f) + { + return False; + } + } + return ok; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + Scalar x2 = x; + Scalar z2 = z; + Clamp(x2, extents.minX, extents.maxX); + Clamp(z2, extents.minZ, extents.maxZ); + x2 -= x; + z2 -= z; + return x2*x2 + z2*z2 <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + x -= point.x; + z -= point.z; + return x*x + z*z <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedYAxisCylinder::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); //z); //GY + Verify(maxX >= point.x); //z); //GY + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + x -= point.x; + z -= point.z; + if (x*x + z*z > radius*radius) + { + return -1.0f; + } + + Scalar height = point.y - maxY; + return Abs(height); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + Scalar a = + line->direction.x*line->direction.x + + line->direction.z*line->direction.z; + + // + //-------------------------------------------------------------------------- + // If the line is parallel to the cylinder, see if it hits the bottom/top of + // the cylinder in the X-Z plane. If it does, it hits the cylinder when it + // hits the box, otherwise it misses altogether + //-------------------------------------------------------------------------- + // + if (Small_Enough(a)) + { + x -= line->origin.x; + z -= line->origin.z; + if (x*x + z*z > radius*radius) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //----------------------------------------------------------------------- + // The line is not parallel to the cylinder, so solve the equation giving + // the intersection of the line with the cylinder using the quadratic + // equation + //----------------------------------------------------------------------- + // + x = line->origin.x - x; + z = line->origin.z - z; + + Scalar b = 2.0f * (line->direction.x*x + line->direction.z*z); + Scalar c = x*x + z*z - radius*radius; + Scalar i = b*b - 4.0f*a*c; + + if (i < SMALL) + { + return False; + } + + // + //------------------------------------------------------------------------- + // If the line does hit the cylinder, update the enter/leaving distances to + // take the cylinder surface into account + //------------------------------------------------------------------------- + // + Verify(a > SMALL); + Scalar ratio = Sqrt(a)/(a*a); + i = Sqrt(i); + b *= -ratio; + i *= ratio; + Scalar enter = (b - i) * 0.5f; + if (enter > enters) + { + enters = enter; + } + + Scalar leave = enter + i; + if (leave < leaves) + { + leaves = leave; + } + + // + //------------------------------------------------------------------------ + // If we have pushed the entering distance after the leaving distance, the + // cylinder was missed, otherwise it is hit at the new entering distance + //------------------------------------------------------------------------ + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::TestInstance() const +{ + return solidType == YAxisCylinderType; +} + +//############################################################################# +//########################## BoxedZAxisCylinder ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedZAxisCylinder::BoxedZAxisCylinder( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, ZAxisCylinderType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedZAxisCylinder::~BoxedZAxisCylinder() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar y = (minY + maxY) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + Scalar x2 = x; + Scalar y2 = y; + Clamp(x2, extents.minX, extents.maxX); + Clamp(y2, extents.minY, extents.maxY); + x2 -= x; + y2 -= y; + return x2*x2 + y2*y2 <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar y = (minY + maxY) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + x -= point.x; + y -= point.y; + return x*x + y*y <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedZAxisCylinder::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x);//z); //GY + Verify(maxX >= point.x);//z); //GY + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar radius = maxX - x; + + // + //-------------------------------------------------------------------------- + // figure out the thickness of cylinder slice where a plane perpendicular to + // X drops through the cylinder and the test point + //-------------------------------------------------------------------------- + // + x = point.x - x; + Scalar y = radius - Sqrt(radius*radius - x*x); + if (point.y > maxY - y) + { + return point.y - maxY + y; + } + else if (point.y < minY + y) + { + return -1.0f; + } + else + { + return 0.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + Scalar x = (minX + maxX) * 0.5f; + Scalar y = (minY + maxY) * 0.5f; + Scalar radius = maxX - x; + + Scalar a = + line->direction.y*line->direction.y + + line->direction.x*line->direction.x; + + // + //-------------------------------------------------------------------------- + // If the line is parallel to the cylinder, see if it hits the bottom/top of + // the cylinder in the X-Z plane. If it does, it hits the cylinder when it + // hits the box, otherwise it misses altogether + //-------------------------------------------------------------------------- + // + if (Small_Enough(a)) + { + y -= line->origin.y; + x -= line->origin.x; + if (y*y + x*x > radius*radius) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //----------------------------------------------------------------------- + // The line is not parallel to the cylinder, so solve the equation giving + // the intersection of the line with the cylinder using the quadratic + // equation + //----------------------------------------------------------------------- + // + y = line->origin.y - y; + x = line->origin.x - x; + + Scalar b = 2.0f * (line->direction.y*y + line->direction.x*x); + Scalar c = y*y + x*x - radius*radius; + Scalar i = b*b - 4.0f*a*c; + + if (i < SMALL) + { + return False; + } + + // + //------------------------------------------------------------------------- + // If the line does hit the cylinder, update the enter/leaving distances to + // take the cylinder surface into account + //------------------------------------------------------------------------- + // + Verify(a > SMALL); + Scalar ratio = Sqrt(a)/(a*a); + i = Sqrt(i); + b *= -ratio; + i *= ratio; + Scalar enter = (b - i) * 0.5f; + if (enter > enters) + { + enters = enter; + } + + Scalar leave = enter + i; + if (leave < leaves) + { + leaves = leave; + } + + // + //------------------------------------------------------------------------ + // If we have pushed the entering distance after the leaving distance, the + // cylinder was missed, otherwise it is hit at the new entering distance + //------------------------------------------------------------------------ + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::TestInstance() const +{ + return solidType == ZAxisCylinderType; +} + diff --git a/CODE/RP/MUNGA/BOXIRAMP.CPP b/CODE/RP/MUNGA/BOXIRAMP.CPP new file mode 100644 index 0000000..f774edb --- /dev/null +++ b/CODE/RP/MUNGA/BOXIRAMP.CPP @@ -0,0 +1,930 @@ +//===========================================================================// +// File: boxsolid.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(PLANE_HPP) +# include +#endif + +extern Logical + BoxedRampContainsLine( + Line *line, + const Plane& plane, + Scalar enters, + Scalar leaves + ); + +//############################################################################# +//##################### BoxedInvertedRampFacingNegativeZ ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeZ::BoxedInvertedRampFacingNegativeZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingNegativeZType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeZ::~BoxedInvertedRampFacingNegativeZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.maxY - minY; + Scalar z = extents.minZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingNegativeZ::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (z*rise <= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = minZ - maxZ; + ramp.normal.z = maxY - minY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = maxY*ramp.normal.y + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::TestInstance() const +{ + return solidType == InvertedRampFacingNegativeZType; +} + +//############################################################################# +//##################### BoxedInvertedRampFacingPositiveZ ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveZ::BoxedInvertedRampFacingPositiveZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingPositiveZType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveZ::~BoxedInvertedRampFacingPositiveZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.maxY - minY; + Scalar z = extents.maxZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingPositiveZ::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (z*rise >= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = minZ - maxZ; + ramp.normal.z = minY - maxY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = minY*ramp.normal.y + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::TestInstance() const +{ + return solidType == InvertedRampFacingPositiveZType; +} + +//############################################################################# +//##################### BoxedInvertedRampFacingNegativeX ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeX::BoxedInvertedRampFacingNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingNegativeXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeX::~BoxedInvertedRampFacingNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - minX; + Scalar y = extents.maxY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingNegativeX::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (x*rise <= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = minX - maxX; + ramp.normal.x = maxY - minY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = minY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::TestInstance() const +{ + return solidType == InvertedRampFacingNegativeXType; +} + +//############################################################################# +//##################### BoxedInvertedRampFacingPositiveX ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveX::BoxedInvertedRampFacingPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingPositiveXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveX::~BoxedInvertedRampFacingPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - maxX; + Scalar y = extents.maxY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= x*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingPositiveX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (x*rise >= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = minX - maxX; + ramp.normal.x = minY - maxY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = maxY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::TestInstance() const +{ + return solidType == InvertedRampFacingPositiveXType; +} diff --git a/CODE/RP/MUNGA/BOXLIST.CPP b/CODE/RP/MUNGA/BOXLIST.CPP new file mode 100644 index 0000000..86744ea --- /dev/null +++ b/CODE/RP/MUNGA/BOXLIST.CPP @@ -0,0 +1,329 @@ +//===========================================================================// +// File: boxlist.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box based spatialization // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/08/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXLIST_HPP) +# include +#endif + +//############################################################################# +//######################### BoundingBoxListNode ######################### +//############################################################################# + +MemoryBlock + BoundingBoxListNode::AllocatedMemory( + sizeof(BoundingBoxListNode), + 500, + 50, + "BoundingBoxList Nodes" + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxListNode::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################### BoundingBoxList ########################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxList::BoundingBoxList() +{ + root = NULL; + nodeCount = 0; + scoreBoard = NULL; + boundingBoxIndex = NULL; + isXMajorAxis = True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxList::~BoundingBoxList() +{ + if (scoreBoard) + { + Unregister_Pointer(scoreBoard); + delete scoreBoard; + } + if (boundingBoxIndex) + { + Unregister_Pointer(boundingBoxIndex); + delete boundingBoxIndex; + } + EraseList(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Add( + BoundingBox* volume, + const ExtentBox &slice + ) +{ + Check(this); + Check(volume); + + ++nodeCount; + BoundingBoxListNode *node = new BoundingBoxListNode(volume, slice); + Register_Object(node); + node->previousNode = root; + root = node; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Remove(BoundingBox* volume) +{ + Check(this); + Check(volume); + + // + //-------------------------------------------------------------------------- + // Spin through all the boxes until we find the one we are after or until we + // run off the list + //-------------------------------------------------------------------------- + // + BoundingBoxListNode + *p = NULL, + *c = root; + while (c) + { + Check(c); + if (c->boundingBox == volume) + { + break; + } + p = c; + c = c->previousNode; + } + + // + //---------------------------------------------- + // Unlink the node from the list if it was found + //---------------------------------------------- + // + if (!c) + { + return; + } + + Check(c); + if (p) + { + Check(p); + p->previousNode = c->previousNode; + } + else + { + root = c->previousNode; + } + + // + //----------------- + // Delete this node + //----------------- + // + --nodeCount; + Unregister_Object(c); + delete c; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::EraseList() +{ + Check(this); + + // + //----------------------------- + // Delete each node in the list + //----------------------------- + // + BoundingBoxListNode *p = root; + while (p) + { + Check(p); + BoundingBoxListNode *q = p; + p = p->previousNode; + Unregister_Object(q); + delete q; + } + root = NULL; + nodeCount = 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxList::FindBoundingBoxContaining(const Point3D &point) +{ + Check(this); + Check(&point); + + // + //-------------------------------------------------------------------------- + // Spin through each of the boxes in reverse order until we find a box which + // contains the specified point. It will be default have priority over any + // boxes put in before it + //-------------------------------------------------------------------------- + // + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + if (box->Contains(point)) + { + return box; + } + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::FindBoundingBoxesContaining( + BoundingBox *volume, + BoundingBoxCollisionList &list + ) +{ + Check(this); + Check(volume); + Check(&list); + + // + //------------------------------------------------------------- + // Spin through each of the boxes in reverse order, looking for + // intesections between the test volume and the box list + //------------------------------------------------------------- + // + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + if (box->ExtentBox::Intersects(*volume)) + { + // + //---------------------------------------------------------------- + // Build the intersection slice, and make sure that it really does + // intersect the list box + //---------------------------------------------------------------- + // + ExtentBox slice; + slice.Intersect(*volume, *box); + if (box->IntersectsBounded(slice)) + { + + // + //------------------------------------------------------------ + // It intersects, so add this to the list. If we are out of + // collisions in the list, we are finished detecting, and just + // return + //------------------------------------------------------------ + // + Verify(list.collisionsLeft); + list.AddCollisionToList(box, slice); + if (!list.collisionsLeft) + { + return; + } + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxList::FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ) +{ + Check(this); + Check(&point); + Check_Pointer(height); + + // + //----------------------------------------------------------------------- + // Spin through each of the bounding boxes, keeping track of which box is + // hit after the shortest distance + //----------------------------------------------------------------------- + // + BoundingBox *best_box = NULL; + *height = -1.0f; + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + + Scalar h = box->FindDistanceBelow(point); + if (h != -1.0f) + { + if (!best_box || *height > h) + { + best_box = box; + *height = h; + } + } + } + return best_box; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxList::FindBoundingBoxHitBy(Line *line) +{ + // + //----------------------------------------------------------------------- + // Spin through each of the boxes, letting each box in turn clip the line + // lengths + //----------------------------------------------------------------------- + // + BoundingBox *best_box = NULL; + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + + Logical h = box->HitBy(line); + if (h) + { + best_box = box; + } + } + return best_box; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxList::TestInstance() const +{ + return True; +} diff --git a/CODE/RP/MUNGA/BOXLIST.HPP b/CODE/RP/MUNGA/BOXLIST.HPP new file mode 100644 index 0000000..807b956 --- /dev/null +++ b/CODE/RP/MUNGA/BOXLIST.HPP @@ -0,0 +1,173 @@ +//===========================================================================// +// File: bndgbox.hh // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Interface specification of bounding-box based spatialization // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/08/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BOXLIST_HPP) +# define BOXLIST_HPP + +# if !defined(BNDGBOX_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + + //########################################################################## + //####################### BoundingBoxListNode ######################## + //########################################################################## + + class BoundingBoxList; + class BoxedSolidList; + class BoundingBoxTree; + + class BoundingBoxListNode SIGNATURED + { + friend class BoundingBoxList; + friend class BoxedSolidList; + + //########################################################################## + // Memory Allocation + // + private: + static MemoryBlock + AllocatedMemory; + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + + //########################################################################## + // Construction and Destruction + // + protected: + BoundingBox + *boundingBox; + BoundingBoxListNode + *previousNode; + + BoundingBoxListNode( + BoundingBox *volume, + const ExtentBox &slice + ): + boundingBox(volume), + solidSlice(slice), + previousNode(NULL) + {Check_Pointer(this); Check(volume);} + ~BoundingBoxListNode() + {Check(this);} + + public: + ExtentBox + solidSlice; + BoundingBox* + GetBoundingBox() + {Check(this); return boundingBox;} + BoundingBoxListNode* + GetNextNode() + {Check(this); return previousNode;} + + //########################################################################## + // Test Support + // + public: + Logical + TestInstance() const; + }; + + //########################################################################## + //######################## BoundingBoxList ########################### + //########################################################################## + + class BoundingBoxList SIGNATURED + { + + //########################################################################## + // Construction and Destruction + // + protected: + BoundingBoxListNode + *root; + int + nodeCount; + int* + scoreBoard; + BoundingBox + **boundingBoxIndex; + Logical + isXMajorAxis; + + public: + BoundingBoxList(); + ~BoundingBoxList(); + + void + Add( + BoundingBox* volume, + const ExtentBox &slice + ); + void + Remove(BoundingBox* volume); + void + EraseList(); + + BoundingBoxListNode* + GetRoot() + {Check(this); return root;} + + //########################################################################## + // Tree Traversal Functions + // + public: + BoundingBox* + FindBoundingBoxContaining(const Point3D &point); + + void + FindBoundingBoxesContaining( + BoundingBox *volume, + BoundingBoxCollisionList &list + ); + + BoundingBox* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ); + + BoundingBox* + FindBoundingBoxHitBy(Line *line); + + void + Reduce(); + void + SortForTree(); + + protected: + void + Sort( + BoundingBoxList &active_solids, + ExtentBox &clipping_box, + BoundingBoxTree &tree_so_far + ); + + //########################################################################## + // Test Support + // + public: + Logical + TestInstance() const; + }; + +#endif diff --git a/CODE/RP/MUNGA/BOXRAMP.CPP b/CODE/RP/MUNGA/BOXRAMP.CPP new file mode 100644 index 0000000..ecdbb98 --- /dev/null +++ b/CODE/RP/MUNGA/BOXRAMP.CPP @@ -0,0 +1,947 @@ +//===========================================================================// +// File: boxsolid.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(PLANE_HPP) +# include +#endif + +#if !defined(LINE_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampContainsLine( + Line *line, + const Plane& plane, + Scalar enters, + Scalar leaves + ) +{ + // + //------------------------------------------------------------------------ + // Find the perpendicular distance from the origin of the ray to the ramp, + // and find the direction of the ray relative to the ramp + //------------------------------------------------------------------------ + // + Scalar distance = plane.DistanceTo(line->origin); + Scalar drift = line->direction*plane.normal; + + // + //-------------------------------------------------------------------------- + // If the ray is going out of the ramp and the origin of the + // ray is in the half-space that the plane's normal points to + //-------------------------------------------------------------------------- + // + if (drift > 0 && distance > 0) + { + return False; + } + + // + //-------------------------------------------------------------------------- + // If the ray is parallel to the ramp, the ray will hit if the origin of the + // ray is not in the half-space that the plane's normal points to + //-------------------------------------------------------------------------- + // + if (!drift) + { + if (distance <= 0.0f) + { + line->length = Max(enters, 0.0f); + return True; + } + return False; + } + + // + //-------------------------------------------------------------------- + // Otherwise, if the plane faces the ray, check to see how far the ray + // travels before hitting it + //-------------------------------------------------------------------- + // + if (drift < 0.0f) + { + distance /= -drift; + + // + //----------------------------------------------------------------------- + // If the ray strikes the plane after all other facing surfaces, then the + // ray enters the solid through this plane. So check to make sure that + // the ray does not miss the plane as clipped by the other surfaces, and + // if it hits, return this distance as the projection length. If the ray + // enters the ramp through an edge face of the bounding box, set the line + // length to the entering value calculated for the box + //----------------------------------------------------------------------- + // + if (distance > enters) + { + if (distance > leaves || distance > line->length) + { + return False; + } + enters = distance; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //------------------------------------------------------------------------ + // If the plane faces away from the ray, check to see how far the ray + // travels before exiting it, and ensure this is not before the ray enters + // the object + //------------------------------------------------------------------------ + // + distance /= -drift; + if (distance >= enters) + { + line->length = Max(enters, 0.0f); + return True; + } + return False; +} + +//############################################################################# +//######################### BoxedRampFacingNegativeZ #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeZ::BoxedRampFacingNegativeZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingNegativeZType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeZ::~BoxedRampFacingNegativeZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.minY - minY; + Scalar z = extents.minZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingNegativeZ::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*z; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = maxZ - minZ; + ramp.normal.z = maxY - minY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = maxY*ramp.normal.y + minZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::TestInstance() const +{ + return solidType == RampFacingNegativeZType; +} + +//############################################################################# +//######################### BoxedRampFacingPositiveZ #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveZ::BoxedRampFacingPositiveZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingPositiveZType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveZ::~BoxedRampFacingPositiveZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.minY - minY; + Scalar z = extents.maxZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingPositiveZ::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*z; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = maxZ - minZ; + ramp.normal.z = minY - maxY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = minY*ramp.normal.y + minZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::TestInstance() const +{ + return solidType == RampFacingPositiveZType; +} + +//############################################################################# +//######################### BoxedRampFacingNegativeX #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeX::BoxedRampFacingNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingNegativeXType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeX::~BoxedRampFacingNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - maxX; + Scalar y = extents.minY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingNegativeX::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*x; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = maxX - minX; + ramp.normal.x = maxY - minY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = maxY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::TestInstance() const +{ + return solidType == RampFacingNegativeXType; +} + +//############################################################################# +//######################### BoxedRampFacingPositiveX #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveX::BoxedRampFacingPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingPositiveXType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveX::~BoxedRampFacingPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - minX; + Scalar y = extents.minY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= x*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingPositiveX::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*x; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = maxX - minX; + ramp.normal.x = minY - maxY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = minY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::TestInstance() const +{ + return solidType == RampFacingPositiveXType; +} + diff --git a/CODE/RP/MUNGA/BOXSOLID.CPP b/CODE/RP/MUNGA/BOXSOLID.CPP new file mode 100644 index 0000000..21a6119 --- /dev/null +++ b/CODE/RP/MUNGA/BOXSOLID.CPP @@ -0,0 +1,1439 @@ +//===========================================================================// +// File: boxsolid.cpp // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(ORIGIN_HPP) +# include +#endif + +#if !defined(LINMTRX_HPP) +# include +#endif + +#if !defined(LINE_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +//############################################################################# +//############################## BoxedSolid ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid::BoxedSolid( + const ExtentBox &extents, + BoxedSolid::Type type, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + TaggedBoundingBox(extents, owner) +{ + + Check_Pointer(this); + solidType = type; + materialType = material; + nextSolid = next_solid; + if (nextSolid) + { + Check(nextSolid); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid::BoxedSolid( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid +): + TaggedBoundingBox(extents, owner) +{ + Check_Pointer(this); + solidType = BlockType; + materialType = material; + nextSolid = next_solid; + if (nextSolid) + { + Check(nextSolid); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid::~BoxedSolid() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid * + BoxedSolid::MakeBoxedSolid( + BoxedSolidResource *boxed_solid_resource, + Simulation *owner, + BoxedSolid *next_solid + ) +{ + + BoxedSolid *boxed_solid; + + switch(boxed_solid_resource->solidType) + { + case BoxedSolid::BlockType: + boxed_solid = + new BoxedSolid( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::SphereType: + boxed_solid = + new BoxedSphere( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::ConeType: + boxed_solid = + new BoxedCone( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::ReducibleBlockType: + boxed_solid = + new BoxedReducibleBlock( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingNegativeZType: + boxed_solid = + new BoxedRampFacingNegativeZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingNegativeXType: + boxed_solid = + new BoxedRampFacingNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingPositiveZType: + boxed_solid = + new BoxedRampFacingPositiveZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingPositiveXType: + boxed_solid = + new BoxedRampFacingPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingNegativeZType: + boxed_solid = + new BoxedInvertedRampFacingNegativeZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingNegativeXType: + boxed_solid = + new BoxedInvertedRampFacingNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingPositiveZType: + boxed_solid = + new BoxedInvertedRampFacingPositiveZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingPositiveXType: + boxed_solid = + new BoxedInvertedRampFacingPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingNegativeZAndPositiveXType: + boxed_solid = + new BoxedWedgeFacingNegativeZAndPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingNegativeZAndNegativeXType: + boxed_solid = + new BoxedWedgeFacingNegativeZAndNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingPositiveZAndNegativeXType: + boxed_solid = + new BoxedWedgeFacingPositiveZAndNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingPositiveZAndPositiveXType: + boxed_solid = + new BoxedWedgeFacingPositiveZAndPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::XAxisCylinderType: + boxed_solid = + new BoxedXAxisCylinder( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::YAxisCylinderType: + boxed_solid = + new BoxedYAxisCylinder( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::ZAxisCylinderType: + boxed_solid = + new BoxedZAxisCylinder( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; +#if 0 + case BoxedSolid::RightHandedTileType: + { + TileResource *terrain = + (TileResource*)boxed_solid_resource; + boxed_solid = + new RightHandedTile( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid, + terrain->cornerHeight + ); + } + break; + case BoxedSolid::LeftHandedTileType: + { + TileResource *terrain = + (TileResource*)boxed_solid_resource; + boxed_solid = + new LeftHandedTile( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid, + terrain->cornerHeight + ); + } + break; +#endif + #if defined(LAB_ONLY) + default: + Dump(boxed_solid_resource->solidType); + Fail("Bad box type!"); + #endif + } + + Check(boxed_solid); + return boxed_solid; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical +#if DEBUG_LEVEL>0 + BoxedSolid::VerifyCollision(BoxedSolidCollision &collision) +#else + BoxedSolid::VerifyCollision(BoxedSolidCollision &) +#endif +{ + Check(this); + Check(&collision); + + Verify(minX <= collision.collisionSlice.minX); + Verify(maxX >= collision.collisionSlice.maxX); + Verify(minY <= collision.collisionSlice.minY); + Verify(maxY >= collision.collisionSlice.maxY); + Verify(minZ <= collision.collisionSlice.minZ); + Verify(maxZ >= collision.collisionSlice.maxZ); + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSolid::ProcessCollision( + BoxedSolidCollision &, + const Vector3D &, + BoxedSolidCollisionList *, + Normal *, + Scalar * + ) +{ + Fail("Unsupported mover collision type!\n"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +Logical + BoxedSolid::TestInstance() const +{ + return solidType == BlockType; +} + +//############################################################################# +//########################## BoxedSolidResource ######################### +//############################################################################# + +static const BoxedSolid::Type + Left_90[BoxedSolid::SolidTypeCount]= +{ + BoxedSolid::BlockType, BoxedSolid::SphereType, + BoxedSolid::ConeType, BoxedSolid::ReducibleBlockType, + + BoxedSolid::RampFacingNegativeXType, + BoxedSolid::RampFacingPositiveZType, + BoxedSolid::RampFacingPositiveXType, + BoxedSolid::RampFacingNegativeZType, + + BoxedSolid::InvertedRampFacingNegativeXType, + BoxedSolid::InvertedRampFacingPositiveZType, + BoxedSolid::InvertedRampFacingPositiveXType, + BoxedSolid::InvertedRampFacingNegativeZType, + + BoxedSolid::WedgeFacingNegativeZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndPositiveXType, + + BoxedSolid::ZAxisCylinderType, + BoxedSolid::YAxisCylinderType, + BoxedSolid::XAxisCylinderType, + + BoxedSolid::LeftHandedTileType, + BoxedSolid::RightHandedTileType +}; + +static const BoxedSolid::Type + Left_180[BoxedSolid::SolidTypeCount]= +{ + BoxedSolid::BlockType, BoxedSolid::SphereType, + BoxedSolid::ConeType, BoxedSolid::ReducibleBlockType, + + BoxedSolid::RampFacingPositiveZType, + BoxedSolid::RampFacingPositiveXType, + BoxedSolid::RampFacingNegativeZType, + BoxedSolid::RampFacingNegativeXType, + + BoxedSolid::InvertedRampFacingPositiveZType, + BoxedSolid::InvertedRampFacingPositiveXType, + BoxedSolid::InvertedRampFacingNegativeZType, + BoxedSolid::InvertedRampFacingNegativeXType, + + BoxedSolid::WedgeFacingPositiveZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndNegativeXType, + + BoxedSolid::XAxisCylinderType, + BoxedSolid::YAxisCylinderType, + BoxedSolid::ZAxisCylinderType, + + BoxedSolid::RightHandedTileType, + BoxedSolid::LeftHandedTileType +}; + +static const BoxedSolid::Type + Left_270[BoxedSolid::SolidTypeCount]= +{ + BoxedSolid::BlockType, BoxedSolid::SphereType, + BoxedSolid::ConeType, BoxedSolid::ReducibleBlockType, + + BoxedSolid::RampFacingPositiveXType, + BoxedSolid::RampFacingNegativeZType, + BoxedSolid::RampFacingNegativeXType, + BoxedSolid::RampFacingPositiveZType, + + BoxedSolid::InvertedRampFacingPositiveXType, + BoxedSolid::InvertedRampFacingNegativeZType, + BoxedSolid::InvertedRampFacingNegativeXType, + BoxedSolid::InvertedRampFacingPositiveZType, + + BoxedSolid::WedgeFacingPositiveZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndNegativeXType, + + BoxedSolid::ZAxisCylinderType, + BoxedSolid::YAxisCylinderType, + BoxedSolid::XAxisCylinderType, + + BoxedSolid::LeftHandedTileType, + BoxedSolid::RightHandedTileType +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoxedSolidResource::Instance( + const BoxedSolidResource &source, + const Origin& origin + ) +{ + materialType = source.materialType; + + // + //------------------- + // Handle no rotation + //------------------- + // + if (Close_Enough(origin.angularPosition.w, 1.0f)) + { + solidType = source.solidType; + solidExtents = source.solidExtents; + sliceExtents = source.sliceExtents; + } + + // + //------------------------------- + // Test for a 180 degree rotation + //------------------------------- + // + else if (Close_Enough(fabs(origin.angularPosition.y), 1.0f)) + { + solidType = Left_180[source.solidType]; + solidExtents.minX = -source.solidExtents.maxX; + solidExtents.maxX = -source.solidExtents.minX; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = -source.solidExtents.maxZ; + solidExtents.maxZ = -source.solidExtents.minZ; + sliceExtents.minX = -source.sliceExtents.maxX; + sliceExtents.maxX = -source.sliceExtents.minX; + sliceExtents.minY = source.sliceExtents.minY; + sliceExtents.maxY = source.sliceExtents.maxY; + sliceExtents.minZ = -source.sliceExtents.maxZ; + sliceExtents.maxZ = -source.sliceExtents.minZ; + } + + // + //--------------------------------- + // Handle a 90 degree left rotation + //--------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, origin.angularPosition.y)) + { + solidType = Left_90[source.solidType]; + solidExtents.minX = source.solidExtents.minZ; + solidExtents.maxX = source.solidExtents.maxZ; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = -source.solidExtents.maxX; + solidExtents.maxZ = -source.solidExtents.minX; + sliceExtents.minX = source.sliceExtents.minZ; + sliceExtents.maxX = source.sliceExtents.maxZ; + sliceExtents.minY = source.sliceExtents.minY; + sliceExtents.maxY = source.sliceExtents.maxY; + sliceExtents.minZ = -source.sliceExtents.maxX; + sliceExtents.maxZ = -source.sliceExtents.minX; + } + + // + //---------------------------------- + // Handle a 90 degree right rotation + //---------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, -origin.angularPosition.y)) + { + solidType = Left_270[source.solidType]; + solidExtents.minX = -source.solidExtents.maxZ; + solidExtents.maxX = -source.solidExtents.minZ; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = source.solidExtents.minX; + solidExtents.maxZ = source.solidExtents.maxX; + sliceExtents.minX = -source.sliceExtents.maxZ; + sliceExtents.maxX = -source.sliceExtents.minZ; + sliceExtents.minY = source.sliceExtents.minY; + sliceExtents.maxY = source.sliceExtents.maxY; + sliceExtents.minZ = source.sliceExtents.minX; + sliceExtents.maxZ = source.sliceExtents.maxX; + } + + // + //------------------------------------------------------------------------- + // Handle an arbitrary rotation. Make sure that only vertically symetrical + // solids get here + //------------------------------------------------------------------------- + // + else if ( + source.solidType == BoxedSolid::YAxisCylinderType + || source.solidType == BoxedSolid::ConeType + || source.solidType == BoxedSolid::SphereType + ) + { + solidType = source.solidType; + Verify(source.solidExtents.minX == source.sliceExtents.minX); + Verify(source.solidExtents.maxX == source.sliceExtents.maxX); + Verify(source.solidExtents.minY == source.sliceExtents.minY); + Verify(source.solidExtents.maxY == source.sliceExtents.maxY); + Verify(source.solidExtents.minZ == source.sliceExtents.minZ); + Verify(source.solidExtents.maxZ == source.sliceExtents.maxZ); + Vector3D center; + center.x = (source.solidExtents.minX + source.solidExtents.maxX) * 0.5f; + center.y = source.solidExtents.minY; + center.z = (source.solidExtents.minZ + source.solidExtents.maxZ) * 0.5f; + Scalar radius = center.x - source.solidExtents.minX; + LinearMatrix m; + m = origin.angularPosition; + Vector3D translated; + translated.Multiply(center, m); + + solidExtents.minX = translated.x - radius; + solidExtents.maxX = translated.x + radius; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = translated.z - radius; + solidExtents.maxZ = translated.z + radius; + sliceExtents = solidExtents; + } + + // + //---------------- + // Otherwise, barf + //---------------- + // + #if defined(LAB_ONLY) + else + { + Fail("Illegal solid for a non-90 degree rotation!\n"); + } + #endif + + solidExtents.minX += origin.linearPosition.x; + solidExtents.maxX += origin.linearPosition.x; + solidExtents.minY += origin.linearPosition.y; + solidExtents.maxY += origin.linearPosition.y; + solidExtents.minZ += origin.linearPosition.z; + solidExtents.maxZ += origin.linearPosition.z; + sliceExtents.minX += origin.linearPosition.x; + sliceExtents.maxX += origin.linearPosition.x; + sliceExtents.minY += origin.linearPosition.y; + sliceExtents.maxY += origin.linearPosition.y; + sliceExtents.minZ += origin.linearPosition.z; + sliceExtents.maxZ += origin.linearPosition.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + TileResource::Instance( + const TileResource &source, + const Origin& origin + ) +{ + BoxedSolidResource::Instance(source, origin); + + // + //------------------------------- + // Test for a 180 degree rotation + //------------------------------- + // + if (Close_Enough(fabs(origin.angularPosition.y), 1.0f)) + { + cornerHeight[0] = source.cornerHeight[3]; + cornerHeight[1] = source.cornerHeight[2]; + cornerHeight[2] = source.cornerHeight[1]; + cornerHeight[3] = source.cornerHeight[0]; + } + + // + //--------------------------------- + // Handle a 90 degree left rotation + //--------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, origin.angularPosition.y)) + { + cornerHeight[0] = source.cornerHeight[1]; + cornerHeight[1] = source.cornerHeight[3]; + cornerHeight[2] = source.cornerHeight[0]; + cornerHeight[3] = source.cornerHeight[2]; + } + + // + //---------------------------------- + // Handle a 90 degree right rotation + //---------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, -origin.angularPosition.y)) + { + cornerHeight[0] = source.cornerHeight[2]; + cornerHeight[1] = source.cornerHeight[0]; + cornerHeight[2] = source.cornerHeight[3]; + cornerHeight[3] = source.cornerHeight[1]; + } +} + +//############################################################################# + +ResourceDescription::ResourceID + BoxedSolidResource::CreateBoxedSolidStream( + const char *entry_data, + ResourceFile *file, + const ResourceDirectories *resource_directories, + Logical convert_boxes + ) +{ + char *filename = + MakePathedFilename(resource_directories->collisionDirectory, entry_data); + Register_Pointer(filename); + + NotationFile *collision_file = new NotationFile(filename); + Unregister_Pointer(filename); + delete filename; + Register_Object(collision_file); + + + ResourceDescription::ResourceID collision_ID; + + if (collision_file->PageCount()) + { +// LAB_ONLY |= collision_file->IsMarkedLabOnly(); + + BoxedSolidList *box_solid_list = new BoxedSolidList; + Register_Object(box_solid_list); + + int size = box_solid_list->AddBoxedSolids(collision_file); + + BoxedSolidResource *boxed_solid_resource = + new BoxedSolidResource[size]; + Register_Pointer(boxed_solid_resource); + + int j = 0; + + + BoundingBoxListNode *p; + + for (p = box_solid_list->GetRoot(); p; p = p->GetNextNode()) + { + Verify(j < size); + Check(p); + BoxedSolid *box = (BoxedSolid *)p->GetBoundingBox(); + Check(box); + + boxed_solid_resource[j].materialType = box->materialType; + + if ((box->solidType == BoxedSolid::BlockType) && (convert_boxes)) + { + boxed_solid_resource[j].solidType = BoxedSolid::ReducibleBlockType; + } + else + { + boxed_solid_resource[j].solidType = box->solidType; + } + + boxed_solid_resource[j].solidExtents = *box; + boxed_solid_resource[j].sliceExtents = p->solidSlice; + boxed_solid_resource[j].recordLength = sizeof(boxed_solid_resource[j]); + + ++j; + } + + for (p = box_solid_list->GetRoot(); p; p = p->GetNextNode()) + { + + Check(p); + BoxedSolid *box = (BoxedSolid *)p->GetBoundingBox(); + Check(box); + + Unregister_Object(box); + delete(box); + + } + + ResourceDescription *res_description = file->FindResourceDescription(entry_data, + ResourceDescription::BoxedSolidStreamResourceType); + + if(res_description == NULL) + { + collision_ID = + file->AddResource( + entry_data, + ResourceDescription::BoxedSolidStreamResourceType, + 1, + ResourceDescription::Preload, + boxed_solid_resource, + size * sizeof(BoxedSolidResource) + )->resourceID; + } + else + { + collision_ID = res_description->resourceID; + } + + Unregister_Pointer(boxed_solid_resource); + delete boxed_solid_resource; + + Unregister_Object(box_solid_list); + delete box_solid_list; + + } + else + { + //---------------------------------------------- + // display warning that collision file is empty + //---------------------------------------------- + DEBUG_STREAM << "** Collision file '" << entry_data << + "' empty or not found. **" << endl; + //---------------------------------------------- + // continue to show all missing collision files + //---------------------------------------------- + } + + Unregister_Object(collision_file); + delete collision_file; + + return collision_ID; +} +//############################################################################# +//########################## BoxedSolidCollision ######################## +//############################################################################# + +static const int + Cant_Occlude[BoxedSolid::SolidTypeCount]= +{ + 0, 1<<(X_Axis|Y_Axis|Z_Axis), 1<<(X_Axis|Z_Axis), 0, + 1<solidType] & (1<solidType != second->solidType + ) + { + continue; + } + + // + //---------------------------------------------------------------------- + // Figure out what face to check against, and make sure that the face of + // the possibly occluding slice is nearer than the other slice + //---------------------------------------------------------------------- + // + int face = (axis<<1) + (velocity[axis] < 0.0f); + int opposite_face = face^1; + if (face&1) + { + if (first->solidType == BoxedSolid::BlockType) + { + if (collisionSlice[face] <= collision.collisionSlice[face]) + { + continue; + } + } + else if ( + collisionSlice[opposite_face] < collision.collisionSlice[face] + ) + { + continue; + } + } + else + { + if (first->solidType == BoxedSolid::BlockType) + { + if (collisionSlice[face] >= collision.collisionSlice[face]) + { + continue; + } + } + else if ( + collisionSlice[opposite_face] > collision.collisionSlice[face] + ) + { + continue; + } + } + + // + //------------------------------------------------------------------ + // Check the faces on the other axes to make sure that the occluding + // object at least covers the extent of the occluded object + //------------------------------------------------------------------ + // + for (face=0; face<6; ++face) + { + if ((face>>1) == axis) + { + continue; + } + if (face&1) + { + if (collisionSlice[face] < collision.collisionSlice[face]) + { + break; + } + } + else if (collisionSlice[face] > collision.collisionSlice[face]) + { + break; + } + } + + // + //----------------------------------------------------------------------- + // If everything checked out, then List[i] occludes List[j]. Stretch the + // definition of List[i] to include the slice occluded if necessary + //----------------------------------------------------------------------- + // + if (face == 6) + { + face = axis<<1; + if (velocity[axis] > 0.0f) + { + ++face; + collisionSlice[face] = + Max(collisionSlice[face], collision.collisionSlice[face]); + } + else + { + collisionSlice[face] = + Min(collisionSlice[face], collision.collisionSlice[face]); + } + return True; + } + } + return False; +} + +//############################################################################# +//######################## BoxedSolidCollisionList ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoxedSolidCollisionList::ReduceCollisionList(const Vector3D &velocity) +{ + Check(this); + Check(&velocity); + + int + i,j; + + // + //-------------------------------------------------------------------------- + // Fuse the collision slices together into the largest possible chunks based + // upon the collision model of each of the involved slices. Repeat until no + // fusings were made in the last pass or only one collision slice remains + //-------------------------------------------------------------------------- + // + Logical again = True; + int collisions = GetCollisionCount(); + phantomCollisions = 0; + while (again && collisions>1) + { + again = False; + + // + //-------------------------------------------------------------------- + // Check each collision slice against the remaining slices in the list + //-------------------------------------------------------------------- + // + for (i=0; iGetTreeVolume()->solidType + != second->GetTreeVolume()->solidType + ) + { + continue; + } + + // + //---------------------------------------------------- + // Make sure that the faces on two sets of sides match + //---------------------------------------------------- + // + + int matches = 0; + int face = -1; + for (int side=0; side<6; side += 2) + { + if ( + first->collisionSlice[side] == second->collisionSlice[side] + && first->collisionSlice[side+1] + == second->collisionSlice[side+1] + ) + { + ++matches; + } + else if (face<0) + { + face = side; + } + } + if (matches != 2) + { + continue; + } + + // + //---------------------------------------------------------------- + // Check to make sure that the two slices have an opposing face in + // common, which will allow the slices to be fused + //---------------------------------------------------------------- + // + if ( + first->collisionSlice[face] != second->collisionSlice[face+1] + && first->collisionSlice[face+1] + != second->collisionSlice[face] + ) + { + continue; + } + + // + //---------------------------------------------------------------- + // Find the face to fuse, then find out which solid description to + // use based upon the velocity vector + //---------------------------------------------------------------- + // + if (first->collisionSlice[face+1] == second->collisionSlice[face]) + { + ++face; + } + BoxedSolid *original = NULL; + if ( + first->GetTreeVolume() != second->GetTreeVolume() + && second->Occludes(*first, velocity) + ) + { + original = first->GetTreeVolume(); + first->treeVolume = second->GetTreeVolume(); + } + + // + //------------------------- + // Fuse the blocks together + //------------------------- + // + first->collisionSlice[face] = second->collisionSlice[face]; + + // + //----------------------------------------------- + // Erase the second slice from the collision list + //----------------------------------------------- + // + for (int k=j+1; k1) + { + // + //-------------------------- + // Erase the occlusion table + //-------------------------- + // + Logical* occluded = new Logical[collisions]; + Register_Pointer(occluded); + BoxedSolid **volumes = new BoxedSolid* [collisions]; + Register_Pointer(volumes); + for (i=0; ij) + { + listStart[j] = listStart[i]; + } + ++j; + } + else + { + volumes[++occludeds] = (BoxedSolid*)listStart[i].treeVolume; + } + } + i = 0; + while (j= point.x && minY <= point.y + && minZ <= point.z && maxZ >= point.z + ) + { + Scalar result = point.y - maxY; + return Max(result, 0.0f); + } + else + { + return -1.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedReducibleBlock::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Scalar + perpendicular, + drift, + distance; + + // + //-------------------- + // Set up for the test + //-------------------- + // + for (int i=0; i<6; ++i) + { + // + //-------------------------------------------------------------------- + // Figure out what axis we are dealing with, then based upon the + // direction of the face, find out the distance from the origin to the + // place against the normal, and find out how fast the perpendicular + // distance changes with a unit movement along the line + //-------------------------------------------------------------------- + // + int face = i; + int axis = face >> 1; + if (face&1) + { + perpendicular = line->origin[axis] - (*this)[face]; + drift = line->direction[axis]; + } + else + { + perpendicular = (*this)[face] - line->origin[axis]; + drift = -line->direction[axis]; + } + + // + //------------------------------------------------------------------- + // If the line is parallel to the face, figure out whether or not the + // line origin lies within the face's half-space + //------------------------------------------------------------------- + // + if (Small_Enough(drift)) + { + if (perpendicular > 0.0f) + { + return False; + } + else + { + continue; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + distance = -perpendicular / drift; + if (drift < 0.0f) + { + if (distance > enters) + { + enters = distance; + } + if (enters > line->length) + { + return False; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + else + { + if (distance < leaves) + { + leaves = distance; + } + if (leaves < 0.0f) + { + return False; + } + } + } + + // + //----------------------------------------------------------------------- + // If we exit the loop, then make sure that we actually hit the interior, + // and let the box figure out if the what happens inside it + //----------------------------------------------------------------------- + // + if (enters <= leaves) + { + line->length = Max(enters, 0.0f); + return True; + } + else + { + return False; + } +} + +//############################################################################# +//########################### BoxedSolidList ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +int + BoxedSolidList::AddBoxedSolids(NotationFile *notation_file) +{ + char page_name[50]; + int solidnumber = 0; + int type; + + BoxedSolidResource boxed_solid_resource; + BoxedSolid *boxed_solid; + + + if (!notation_file->GetEntry("COLLISION", "count", &solidnumber)) + { + DEBUG_STREAM << "No 'COLLISION' entry!!!!!" << endl; + Exit(AbortExitCodeID); + } + + for (int j=0; j < solidnumber; ++j) + { + sprintf(page_name, "volume %d", j); + + if (!notation_file->GetEntry(page_name, "TypeNumber", &type)) + { + DEBUG_STREAM << "No solid at collision number : " << j << endl; + Exit(AbortExitCodeID); + } + boxed_solid_resource.solidType = (BoxedSolid::Type)type; + + if (!notation_file->GetEntry(page_name, "MaterialNumber", &type)) + { + DEBUG_STREAM << "No material at collision number : " << j << endl; + Exit(AbortExitCodeID); + } + + boxed_solid_resource.materialType = (BoxedSolid::Material)type; + + int errorvalue = 0; + + errorvalue |= !notation_file->GetEntry(page_name, "extminX", &(boxed_solid_resource.solidExtents.minX)); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxX", &(boxed_solid_resource.solidExtents.maxX)); + errorvalue |= !notation_file->GetEntry(page_name, "extminY", &(boxed_solid_resource.solidExtents.minY)); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxY", &(boxed_solid_resource.solidExtents.maxY)); + errorvalue |= !notation_file->GetEntry(page_name, "extminZ", &(boxed_solid_resource.solidExtents.minZ)); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxZ", &(boxed_solid_resource.solidExtents.maxZ)); + + if ( errorvalue ) + { + DEBUG_STREAM << "Collision number : " << j + << " does not have valid extents\n"; + Exit(AbortExitCodeID); + } + + errorvalue = 0; + errorvalue |= !notation_file->GetEntry(page_name, "slcminX", &(boxed_solid_resource.sliceExtents.minX)); + errorvalue |= !notation_file->GetEntry(page_name, "slcmaxX", &(boxed_solid_resource.sliceExtents.maxX)); + errorvalue |= !notation_file->GetEntry(page_name, "slcminY", &(boxed_solid_resource.sliceExtents.minY)); + errorvalue |= !notation_file->GetEntry(page_name, "slcmaxY", &(boxed_solid_resource.sliceExtents.maxY)); + errorvalue |= !notation_file->GetEntry(page_name, "slcminZ", &(boxed_solid_resource.sliceExtents.minZ)); + errorvalue |= !notation_file->GetEntry(page_name, "slcmaxZ", &(boxed_solid_resource.sliceExtents.maxZ)); + + if ( errorvalue ) + { + DEBUG_STREAM << "Collision number : " << j + << " does not have valid slice extents\n"; + Exit(AbortExitCodeID); + } + + + boxed_solid = + BoxedSolid::MakeBoxedSolid(&boxed_solid_resource, NULL, NULL); + + Register_Object(boxed_solid); + + Add(boxed_solid, boxed_solid_resource.sliceExtents); + } + + return solidnumber; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + + +#if defined(TEST_CLASS) +# include "boxsolid.tcp" +#endif + diff --git a/CODE/RP/MUNGA/BOXSOLID.HPP b/CODE/RP/MUNGA/BOXSOLID.HPP new file mode 100644 index 0000000..44ad751 --- /dev/null +++ b/CODE/RP/MUNGA/BOXSOLID.HPP @@ -0,0 +1,1004 @@ +//===========================================================================// +// File: boxsolid.hh // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Interface specification of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BOXSOLID_HPP) +# define BOXSOLID_HPP + +# if !defined(BNDGBOX_HPP) +# include +# endif + +# if !defined(BOXTREE_HPP) +# include +# endif + +# if !defined(BOXLIST_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + + struct BoxedSolidResource; + class BoxedSolidCollision; + class BoxedSolidCollisionList; + class Simulation; + class NotationFile; + class Normal; + + //########################################################################## + //########################### BoxedSolid ############################# + //########################################################################## + + class BoxedSolid: + public TaggedBoundingBox + { + public: + enum Type { + BlockType=0, + SphereType=1, + ConeType=2, + ReducibleBlockType=3, + RampType=4, + RampFacingNegativeZType=4, + RampFacingNegativeXType, + RampFacingPositiveZType, + RampFacingPositiveXType, + InvertedRampType=8, + InvertedRampFacingNegativeZType=8, + InvertedRampFacingNegativeXType, + InvertedRampFacingPositiveZType, + InvertedRampFacingPositiveXType, + WedgeType=12, + WedgeFacingNegativeZAndPositiveXType=12, + WedgeFacingNegativeZAndNegativeXType, + WedgeFacingPositiveZAndNegativeXType, + WedgeFacingPositiveZAndPositiveXType, + XAxisCylinderType=16, + YAxisCylinderType=17, + ZAxisCylinderType=18, + RightHandedTileType=19, + LeftHandedTileType=20, + SolidTypeCount + } + solidType; + + enum Material { + StoneMaterial = 0, + GravelMaterial, + ConcreteMaterial, + SteelMaterial, + WoodMaterial, + RockMaterial, + OurCraftMaterial, + OtherCraftMaterial, + MaterialCount + } + materialType; + + BoxedSolid( + const ExtentBox &extents, + Type type, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + BoxedSolid( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedSolid(); + + static BoxedSolid* + MakeBoxedSolid( + BoxedSolidResource *resource, + Simulation *owner, + BoxedSolid *next_solid + ); + + virtual Logical + VerifyCollision(BoxedSolidCollision &collision); + virtual Logical + ProcessCollision( + BoxedSolidCollision &collision, + const Vector3D &velocity, + BoxedSolidCollisionList *last_collisions, + Normal *normal, + Scalar *penetration + ); + + Logical + TestInstance() const; + static Logical + TestClass(); + + Simulation* + GetOwningSimulation() + {Check(this); return (Simulation*)GetTagPointer();} + BoxedSolid* + GetNextSolid() + {Check(this); return nextSolid;} + + protected: + BoxedSolid + *nextSolid; + }; + + //########################################################################## + //####################### BoxedSolidCollision ######################## + //########################################################################## + + class BoxedSolidCollision: + public BoundingBoxCollision + { + public: + BoxedSolid* + GetTreeVolume() + {Check(this); return (BoxedSolid*)treeVolume;} + Logical + Occludes( + BoxedSolidCollision &collision, + const Vector3D &velocity + ); + }; + + //########################################################################## + //##################### BoxedSolidCollisionList ###################### + //########################################################################## + + class BoxedSolidCollisionList: + public BoundingBoxCollisionList + { + protected: + int phantomCollisions; + + public: + BoxedSolidCollisionList(int max_length = 10): + BoundingBoxCollisionList(max_length) + {Reset();} + void + Reset() + {phantomCollisions = 0; BoundingBoxCollisionList::Reset();} + + BoxedSolidCollision& + operator[](int index) + { + Check(this); Verify((unsigned)index < maxCollisions); + return ((BoxedSolidCollision*)listStart)[index]; + } + int + GetRealCollisions() + {Check(this); return GetCollisionCount() - phantomCollisions;} + + void + ReduceCollisionList(const Vector3D &velocity); + }; + + //########################################################################## + //####################### BoxedSolidResource ######################### + //########################################################################## + + struct BoxedSolidResource + { + size_t recordLength; + ExtentBox + solidExtents, + sliceExtents; + BoxedSolid::Type solidType; + BoxedSolid::Material materialType; + + void + Instance( + const BoxedSolidResource &source, + const Origin& origin + ); + + static ResourceDescription::ResourceID + CreateBoxedSolidStream( + const char *entry_data, + ResourceFile *file, + const ResourceDirectories *resource_directories, + Logical convert_boxes = False + ); + }; + + //########################################################################## + //########################### BoxedSphere ############################ + //########################################################################## + + class BoxedSphere: + public BoxedSolid + { + public: + BoxedSphere( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedSphere(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //############################ BoxedCone ############################# + //########################################################################## + + class BoxedCone: + public BoxedSolid + { + public: + BoxedCone( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedCone(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //####################### BoxedReducibleBlock ######################## + //########################################################################## + + class BoxedReducibleBlock: + public BoxedSolid + { + public: + BoxedReducibleBlock( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedReducibleBlock(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //###################### BoxedRampFacingNegativeZ #################### + //########################################################################## + + class BoxedRampFacingNegativeZ: + public BoxedSolid + { + public: + BoxedRampFacingNegativeZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingNegativeZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //#################### BoxedRampFacingPositiveX ###################### + //########################################################################## + + class BoxedRampFacingPositiveX: + public BoxedSolid + { + public: + BoxedRampFacingPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //#################### BoxedRampFacingPositiveZ ###################### + //########################################################################## + + class BoxedRampFacingPositiveZ: + public BoxedSolid + { + public: + BoxedRampFacingPositiveZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingPositiveZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //#################### BoxedRampFacingNegativeX ###################### + //########################################################################## + + class BoxedRampFacingNegativeX: + public BoxedSolid + { + public: + BoxedRampFacingNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //################## BoxedInvertedRampFacingNegativeZ ################ + //########################################################################## + + class BoxedInvertedRampFacingNegativeZ: + public BoxedSolid + { + public: + BoxedInvertedRampFacingNegativeZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingNegativeZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //################## BoxedInvertedRampFacingNegativeX ################ + //########################################################################## + + class BoxedInvertedRampFacingNegativeX: + public BoxedSolid + { + public: + BoxedInvertedRampFacingNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //################## BoxedInvertedRampFacingPositiveZ ################ + //########################################################################## + + class BoxedInvertedRampFacingPositiveZ: + public BoxedSolid + { + public: + BoxedInvertedRampFacingPositiveZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingPositiveZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //################## BoxedInvertedRampFacingPositiveX ################ + //########################################################################## + + class BoxedInvertedRampFacingPositiveX: + public BoxedSolid + { + public: + BoxedInvertedRampFacingPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //############## BoxedWedgeFacingNegativeZAndPositiveX ############### + //########################################################################## + + class BoxedWedgeFacingNegativeZAndPositiveX: + public BoxedSolid + { + public: + BoxedWedgeFacingNegativeZAndPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingNegativeZAndPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //############## BoxedWedgeFacingPositiveZAndPositiveX ############### + //########################################################################## + + class BoxedWedgeFacingPositiveZAndPositiveX: + public BoxedSolid + { + public: + BoxedWedgeFacingPositiveZAndPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingPositiveZAndPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //############## BoxedWedgeFacingPositiveZAndNegativeX ############### + //########################################################################## + + class BoxedWedgeFacingPositiveZAndNegativeX: + public BoxedSolid + { + public: + BoxedWedgeFacingPositiveZAndNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingPositiveZAndNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //############## BoxedWedgeFacingNegativeZAndNegativeX ############### + //########################################################################## + + class BoxedWedgeFacingNegativeZAndNegativeX: + public BoxedSolid + { + public: + BoxedWedgeFacingNegativeZAndNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingNegativeZAndNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //####################### BoxedXAxisCylinder ######################### + //########################################################################## + + class BoxedXAxisCylinder: + public BoxedSolid + { + public: + BoxedXAxisCylinder( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedXAxisCylinder(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //####################### BoxedYAxisCylinder ######################### + //########################################################################## + + class BoxedYAxisCylinder: + public BoxedSolid + { + public: + BoxedYAxisCylinder( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedYAxisCylinder(); + + Logical + VerifyCollision(BoxedSolidCollision &collision); + Logical + ProcessCollision( + BoxedSolidCollision &collision, + const Vector3D &velocity, + BoxedSolidCollisionList *last_collisions, + Normal *normal, + Scalar *penetration + ); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //####################### BoxedZAxisCylinder ######################### + //########################################################################## + + class BoxedZAxisCylinder: + public BoxedSolid + { + public: + BoxedZAxisCylinder( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedZAxisCylinder(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //##################### RightHandedTile ####################### + //########################################################################## + + class RightHandedTile: + public BoxedSolid + { + public: + RightHandedTile( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *cornerHeights, + Type type=RightHandedTileType + ); + ~RightHandedTile(); + + Scalar + cornerHeight[4]; + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //######################## LeftHandedTile ######################### + //########################################################################## + + class LeftHandedTile: + public RightHandedTile + { + public: + LeftHandedTile( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *cornerHeights + ); + ~LeftHandedTile(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; + }; + + //########################################################################## + //####################### TerrainTileResource ######################## + //########################################################################## + + struct TileResource: + public BoxedSolidResource + { + Scalar + cornerHeight[4]; + + void + Instance( + const TileResource &source, + const Origin& origin + ); + }; + + //########################################################################## + //######################## BoxedSolidTree ############################ + //########################################################################## + + class BoxedSolidTree: + public BoundingBoxTree + { + + //########################################################################## + // Construction and Destruction + // + public: + BoxedSolidTree() + {} + ~BoxedSolidTree() + {} + + //########################################################################## + // Tree Traversal Functions + // + public: + BoxedSolid* + FindBoundingBoxContaining(const Point3D &point) + { + return + (BoxedSolid*) + BoundingBoxTree::FindBoundingBoxContaining(point); + } + + BoxedSolid* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ) + { + return + (BoxedSolid*) + BoundingBoxTree::FindBoundingBoxUnder(point, height); + } + + BoxedSolid* + FindBoundingBoxHitBy(Line *line) + {return (BoxedSolid*)BoundingBoxTree::FindBoundingBoxHitBy(line);} + }; + + //########################################################################## + //######################## BoxedSolidList ############################ + //########################################################################## + + class BoxedSolidList: + public BoundingBoxList + { + //########################################################################## + // Construction and Destruction + // + public: + BoxedSolidList() {} + ~BoxedSolidList() {} + + //########################################################################## + // Tree Traversal Functions + // + public: + int + AddBoxedSolids(NotationFile *notation_file); + + BoxedSolid* + FindBoundingBoxContaining(const Point3D &point) + { + return + (BoxedSolid*) + BoundingBoxList::FindBoundingBoxContaining(point); + } + + BoxedSolid* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ) + { + return + (BoxedSolid*) + BoundingBoxList::FindBoundingBoxUnder(point, height); + } + + BoxedSolid* + FindBoundingBoxHitBy(Line *line) + {return (BoxedSolid*)BoundingBoxList::FindBoundingBoxHitBy(line);} + + void + Reduce(); + }; + +#endif diff --git a/CODE/RP/MUNGA/BOXSOLID.TCP b/CODE/RP/MUNGA/BOXSOLID.TCP new file mode 100644 index 0000000..9d77369 --- /dev/null +++ b/CODE/RP/MUNGA/BOXSOLID.TCP @@ -0,0 +1,378 @@ + +#include +#include +#include +#include + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSolid::TestClass() +{ +//ofstream testout("gene.dat",ios::app); //GY + Tell("Start BoxedSolid::TestClass()..\n"); + BoxedSolidTree tree; + BoxedSolidList list; + Point3D test_point; + + ExtentBox eb; + BoxedSolid* solids[TEST_CLASS]; + + BoxedSolid *list_ptr; + BoxedSolid *tree_ptr; + + // + //------------------------------------------------------------ + // Create a bunch of boxes to test, and add them into the tree + //------------------------------------------------------------ + // + int i; + for (i=0; iminX + solids[i]->maxX) * 0.5f; + test_point.y = (solids[i]->minY + solids[i]->maxY) * 0.5f; + test_point.z = (solids[i]->minZ + solids[i]->maxZ) * 0.5f; + + tree_ptr = tree.FindBoundingBoxContaining(test_point); + list_ptr = list.FindBoundingBoxContaining(test_point); + Test(tree_ptr == list_ptr); + } + + // + //--------------------------------------------------- + // Now test a bunch of random points against the tree + //--------------------------------------------------- + // + for (i=0; i +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(VECTOR3D_HPP) +# include +#endif + +//############################################################################# +//########################### BoxedSolidList ############################ +//############################################################################# + +enum { + X_Axis_Bit = 1, + Y_Axis_Bit = 2, + Z_Axis_Bit = 4 +}; + +enum { + Min_Side = 0x001, + Inside = 0x002, + Max_Side = 0x004, + Both_Sides = Min_Side|Max_Side, + Shift = 3, + X_Shift = 2 * Shift, + Min_X_Side = Min_Side << X_Shift, + Inside_X = Inside << X_Shift, + Max_X_Side = Max_Side << X_Shift, + X_Mask = Min_X_Side|Inside_X|Max_X_Side, + Y_Shift = Shift, + Min_Y_Side = Min_Side << Y_Shift, + Inside_Y = Inside << Y_Shift, + Max_Y_Side = Max_Side << Y_Shift, + Y_Mask = Min_Y_Side|Inside_Y|Max_Y_Side, + Z_Shift = 0, + Min_Z_Side = Min_Side << Z_Shift, + Inside_Z = Inside << Z_Shift, + Max_Z_Side = Max_Side << Z_Shift, + Z_Mask = Min_Z_Side|Inside_Z|Max_Z_Side +}; + +int + Legal_To_Fuse[BoxedSolid::SolidTypeCount]= +{ + X_Axis_Bit|Y_Axis_Bit|Z_Axis_Bit, 0, 0, 0, + X_Axis_Bit, Z_Axis_Bit, X_Axis_Bit, Z_Axis_Bit, + X_Axis_Bit, Z_Axis_Bit, X_Axis_Bit, Z_Axis_Bit, + Y_Axis_Bit, Y_Axis_Bit, Y_Axis_Bit, Y_Axis_Bit, + X_Axis_Bit, Y_Axis_Bit, Z_Axis_Bit +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Reduce() +{ + Check(this); + + BoundingBoxListNode + *i, *j, *previous; + + // + //-------------------------------------------------------------------------- + // Fuse the collision slices together into the largest possible chunks based + // upon the collision model of each of the involved slices. Repeat until no + // fusings were made in the last pass or only one collision slice remains + //-------------------------------------------------------------------------- + // + Logical again = True; + while (again) + { + again = False; + + // + //-------------------------------------------------------------------- + // Check each collision slice against the remaining slices in the list + //-------------------------------------------------------------------- + // + for (i=root; i; i = i->previousNode) + { + Check(i); + previous = i; + j = i->previousNode; + while (j) + { + Check(j); + // + //------------------------------------------------------------- + // If the model types are different, these two slices cannot be + // fused + //------------------------------------------------------------- + // + BoundingBox *first = i->boundingBox; + BoundingBox *second = j->boundingBox; + + // + //---------------------------------------------------- + // Make sure that the faces on two sets of sides match + //---------------------------------------------------- + // + int matches = 0; + int face = -1; + for (int side=0; side<6; side += 2) + { + if ( + (*first)[side] == (*second)[side] + && (*first)[side+1] == (*second)[side+1] + ) + { + ++matches; + } + else if (face<0) + { + face = side; + } + } + if (matches != 2) + { +Next_Solid: + previous = j; + j = j->previousNode; + continue; + } + + // + //---------------------------------------------------------------- + // Check to make sure that the two solids have an opposing face in + // common, which will allow the solids to be fused + //---------------------------------------------------------------- + // + if ( + (*first)[face] != (*second)[face+1] + && (*first)[face+1] != (*second)[face] + ) + { + goto Next_Solid; + } + + // + //---------------------------------------------------- + // Find the face to fuse, and fuse the blocks together + //---------------------------------------------------- + // + if ((*first)[face+1] == (*second)[face]) + { + ++face; + } + (*first)[face] = (*second)[face]; + + // + //----------------------------------------------- + // Erase the second solid from the collision list + //----------------------------------------------- + // + --nodeCount; + if (previous) + { + previous->previousNode = j->previousNode; + Unregister_Object(j); + delete(j); + j = previous->previousNode; + } + else + { + root = j->previousNode; + Unregister_Object(j); + delete(j); + j = root; + } + again = True; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::SortForTree() +{ + Check(this); + + int + i, j; + BoundingBoxListNode + *p, *q; + + // + //----------------------------------------------------------------------- + // Find out how many collision solids are in the list, and figure out the + // total extent box so that we can set the traversal order correctly + //----------------------------------------------------------------------- + // + ExtentBox map_extents; + map_extents.minX = 65535.9999f; + map_extents.minY = 65535.9999f; + map_extents.minZ = 65535.9999f; + map_extents.maxX = -65535.9999f; + map_extents.maxY = -65535.9999f; + map_extents.maxZ = -65535.9999f; + for (p=root; p; p = p->previousNode) + { + Check(p); + if (p->boundingBox->minX < map_extents.minX) + { + map_extents.minX = p->boundingBox->minX; + } + if (p->boundingBox->maxX > map_extents.maxX) + { + map_extents.maxX = p->boundingBox->maxX; + } + + if (p->boundingBox->minY < map_extents.minY) + { + map_extents.minY = p->boundingBox->minY; + } + if (p->boundingBox->maxY > map_extents.maxY) + { + map_extents.maxY = p->boundingBox->maxY; + } + + if (p->boundingBox->minZ < map_extents.minZ) + { + map_extents.minZ = p->boundingBox->minZ; + } + if (p->boundingBox->maxZ > map_extents.maxZ) + { + map_extents.maxZ = p->boundingBox->maxZ; + } + } + if ( + map_extents.maxZ - map_extents.minZ + > map_extents.maxX - map_extents.minX + ) + { + isXMajorAxis = False; + } + + // + //---------------------------------------------------- + // Allocate a scoreboard and fill it with sorting info + //---------------------------------------------------- + // + Verify(!scoreBoard); + scoreBoard = new int[nodeCount * nodeCount]; + Register_Pointer(scoreBoard); + int *score = scoreBoard; + + boundingBoxIndex = new BoundingBox* [nodeCount]; + Register_Pointer(boundingBoxIndex); + + for (p=root,i=0; p; p = p->previousNode,++i) + { + Check(p); + BoundingBox *first = p->boundingBox; + boundingBoxIndex[i] = first; + for (q=root,j=0; q; q = q->previousNode,++j,++score) + { + + // + //------------------------------ + // Ignore scoring against itself + //------------------------------ + // + Check(q); + *score = 0; + if (p == q) + { + continue; + } + BoundingBox *second = q->boundingBox; + + // + //-------------------------------------------------------------------- + // Step through the three axes and set the flags showing how the + // second solid is split up by the first solid. Make sure that if the + // second solid completely covers the first that this inside bit is + // set correctly + //-------------------------------------------------------------------- + // + for (int axis = X_Axis; axis <= Z_Axis; --axis) + { + *score <<= Shift; + int face = axis << 1; + if ((*second)[face] < (*first)[face]) + { + *score |= Min_Side; + } + else if ((*second)[face] < (*first)[face+1]) + { + *score |= Inside; + } + if ((*second)[face+1] > (*first)[face+1]) + { + *score |= Max_Side; + } + else if ((*second)[face+1] > (*first)[face]) + { + *score |= Inside; + } + + if ((*score & Both_Sides) == Both_Sides) + { + *score |= Inside; + } + } + } + } + + // + //-------------------------------------------------------------------------- + // Create a new BoxedSolid list for results to go into, and a third in which + // to pass the active list + //-------------------------------------------------------------------------- + // + BoundingBoxList active; + active.root = root; + active.nodeCount = nodeCount; + root = NULL; + BoundingBoxTree tree_so_far; + + Sort( + active, + map_extents, + tree_so_far + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Sort( + BoundingBoxList &,//active, + ExtentBox &,//map_extents, + BoundingBoxTree &//tree_so_far + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoxedSolidList::Reduce() +{ + Check(this); + + BoundingBoxListNode + *i, *j, *previous; + + // + //-------------------------------------------------------------------------- + // Fuse the collision slices together into the largest possible chunks based + // upon the collision model of each of the involved slices. Repeat until no + // fusings were made in the last pass or only one collision slice remains + //-------------------------------------------------------------------------- + // + Logical again = True; + while (again) + { + again = False; + + // + //-------------------------------------------------------------------- + // Check each collision slice against the remaining slices in the list + //-------------------------------------------------------------------- + // + for (i=root; i; i = i->previousNode) + { + Check(i); + previous = i; + j = i->previousNode; + while (j) + { + Check(j); + // + //------------------------------------------------------------- + // If the model types are different, these two slices cannot be + // fused + //------------------------------------------------------------- + // + BoxedSolid *first = Cast_Object(BoxedSolid*, i->boundingBox); + BoxedSolid *second = Cast_Object(BoxedSolid*, j->boundingBox); + if (first->solidType != second->solidType) + { +Next_Solid: + previous = j; + j = j->previousNode; + continue; + } + + // + //---------------------------------------------------- + // Make sure that the faces on two sets of sides match + //---------------------------------------------------- + // + int matches = 0; + int face = -1; + for (int side=0; side<6; side += 2) + { + if ( + (*first)[side] == (*second)[side] + && (*first)[side+1] == (*second)[side+1] + ) + { + ++matches; + } + else if (face<0) + { + face = side; + } + } + if (matches != 2) + { + goto Next_Solid; + } + + // + //---------------------------------------------------------------- + // Check to make sure that the two solids have an opposing face in + // common, which will allow the solids to be fused + //---------------------------------------------------------------- + // + if ( + (*first)[face] != (*second)[face+1] + && (*first)[face+1] != (*second)[face] + ) + { + goto Next_Solid; + } + + // + //--------------------------------------------------------------- + // Make sure that this type of solid is legal to be fused in this + // direction + //--------------------------------------------------------------- + // + if (!(Legal_To_Fuse[first->solidType] & (face>>1))) + { + goto Next_Solid; + } + + // + //---------------------------------------------------- + // Find the face to fuse, and fuse the blocks together + //---------------------------------------------------- + // + if ((*first)[face+1] == (*second)[face]) + { + ++face; + } + (*first)[face] = (*second)[face]; + + // + //----------------------------------------------- + // Erase the second solid from the collision list + //----------------------------------------------- + // + if (previous) + { + previous->previousNode = j->previousNode; + Unregister_Object(j); + delete(j); + j = previous->previousNode; + } + else + { + root = j->previousNode; + Unregister_Object(j); + delete(j); + j = root; + } + again = True; + } + } + } +} + + diff --git a/CODE/RP/MUNGA/BOXSPHR.CPP b/CODE/RP/MUNGA/BOXSPHR.CPP new file mode 100644 index 0000000..64dce4f --- /dev/null +++ b/CODE/RP/MUNGA/BOXSPHR.CPP @@ -0,0 +1,260 @@ +//===========================================================================// +// File: boxsolid.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(ORIGIN_HPP) +# include +#endif + +#if !defined(LINMTRX_HPP) +# include +#endif + +#if !defined(LINE_HPP) +# include +#endif + +//############################################################################# +//############################## BoxedSphere ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSphere::BoxedSphere( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, SphereType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSphere::~BoxedSphere() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //-------------------------------------------------------------------------- + // Constrain the centerpoint of the sphere to be within the bounded extents. + // Then see if the constrained point is within the radius of the sphere. If + // so, it is an intersection + //-------------------------------------------------------------------------- + // + Point3D closest = center; + extents.Constrain(&closest); + closest -= center; + return radius*radius >= closest.LengthSquared(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //------------------------------------------------------------------------- + // translate the test point into the sphere's frame of reference and see if + // it is close enough + //------------------------------------------------------------------------- + // + center -= point; + return radius*radius >= center.LengthSquared(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedSphere::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the sphere, putting the center + // point of the sphere at the origin. Note that we are subtracting the + // point from the center point as opposed to the normal way. This will + // result in both X and Y being negated, but since we are squaring them, + // this will not matter + //----------------------------------------------------------------------- + // + Scalar x = center.x - point.x; + Scalar z = center.z - point.z; + Scalar h = radius*radius - x*x - z*z; + if (h < SMALL) + { + return -1.0f; + } + + // + //------------------------------------------------------------------- + // If the point is in the XZ shadow of the sphere, then the height is + // determined by the height of the sphere at that point + //------------------------------------------------------------------- + // + Scalar height = point.y - (center.y + Sqrt(h)); + return Abs(height); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //------------------------------------------------------------------------- + // Find the point of closest approach to the center of the sphere, and make + // sure that it is within the boundaries of the sphere + //------------------------------------------------------------------------- + // + Scalar midlen = line->LengthToClosestPointTo(center); + Point3D closest; + line->Project(midlen, &closest); + closest -= center; + Scalar v = radius*radius - closest.LengthSquared(); + if (v < 0.0f) + { + return False; + } + + // + //--------------------------------------------------------------------- + // Find the closest possible length of ray traversal before hitting the + // sphere + //--------------------------------------------------------------------- + // + v = Sqrt(v); + Scalar enter = midlen - v; + if (enter > enters) + { + enters = enter; + } + Scalar leave = midlen + v; + if (leave < leaves) + { + leaves = leave; + } + + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::TestInstance() const +{ + return solidType == SphereType; +} diff --git a/CODE/RP/MUNGA/BOXTILE.CPP b/CODE/RP/MUNGA/BOXTILE.CPP new file mode 100644 index 0000000..19d560a --- /dev/null +++ b/CODE/RP/MUNGA/BOXTILE.CPP @@ -0,0 +1,672 @@ +//===========================================================================// +// File: boxsolid.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(ORIGIN_HPP) +# include +#endif + +#if !defined(LINMTRX_HPP) +# include +#endif + +#if !defined(LINE_HPP) +# include +#endif + +#if !defined(PLANE_HPP) +# include +#endif + +#if !defined(VECTOR2D_HPP) +# include +#endif + +//############################################################################# +//######################### RightHandedTile ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RightHandedTile::RightHandedTile( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *corners, + Type type +): + BoxedSolid(extents, type, material, owner, next_solid) +{ + Check_Pointer(this); + for (int i=0; i= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //------------------------------------------------------------------- + // See if the box hits the upper-right triangle anywhere on its plane + //------------------------------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + + Plane plane1(p0, p1, p2); + if (plane1.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + + // + //------------------------------------------------------------------ + // See if the box hits the lower-left triangle anywhere on its plane + //------------------------------------------------------------------ + // + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + + Plane plane2(p0, p1, p2); + if (plane2.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RightHandedTile::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(maxY >= point.y); + return FindDistanceBelowBounded(point) <= 0.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + RightHandedTile::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------- + // Figure out which triangle the point will reside in + //--------------------------------------------------- + // + Scalar rise = maxX - minX; + Scalar run = maxZ - minZ; + Verify(rise > SMALL); + Verify(run > SMALL); + + Scalar dx = point.x - minX; + Scalar dz = point.z - minZ; + + // + //----------------------------------------------------------------- + // Set up the appropriate triangle based upon which have it lies in + //----------------------------------------------------------------- + // + Point3D p0,p1,p2; + if (dx*run > dz*rise) + { + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + } + else + { + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + } + + // + //--------------------------------------------------------------------- + // Make a plane out of the triangle, and have the plane solve for the Y + // coordinate + //--------------------------------------------------------------------- + // + Plane plane(p0, p1, p2); + Verify(!Small_Enough(plane.normal.y)); + Scalar height = point.y - plane.CalculateY(point.x, point.z); + Check_Fpu(); + return height; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +static Scalar + LineHitsTriangle( + Line *line, + const Point3D &p0, + const Point3D &p1, + const Point3D &p2, + Scalar *cosine + ) +{ + // + //-------------------------------------------------------------------------- + // Make the plane out of the three corner points, and figure out how far the + // ray must travel to reach this plane. Try some trivial rejections: + // parallel lines, lines starting outside the halfspace heading away from + // the plane, and lines starting outside the halfspace and heading towards + // the plane but are too far away + //-------------------------------------------------------------------------- + // + Plane plane(p0, p1, p2); + Scalar length = line->DistanceTo(plane, cosine); + if ( + Small_Enough(*cosine) + || *cosine > 0.0f && length < 0.0f + || *cosine < 0.0f && length > line->length + ) + { + return -1.0f; + } + + // + //-------------------------------------------------------- + // Project the impact point and triangle unto the XZ plane + //-------------------------------------------------------- + // + Point3D impact; + line->Project(length, &impact); + Vector2DOf proj(impact.x - p0.x, impact.z - p0.z); + Scalar x = p1.x - p0.x; + Scalar z = p2.z - p0.z; + + // + //------------------------------------------------------------------------- + // Make sure that the area of the triangle made with the test point and the + // first leg is not negative or greater than the area of the triangle made + // by the two legs. The area of the triangle is half the cross product of + // the legs of that triangle + //------------------------------------------------------------------------- + // + Scalar area_ratio = z*x; + Verify(!Small_Enough(area_ratio)); + area_ratio = x*proj.y / area_ratio; + Check_Fpu(); + if (area_ratio >= 0.0f && area_ratio <= 1.0f) + { + // + //---------------------------------------------------------------------- + // The area ratio represents the height of the test triangle relative to + // the given triangle. One edge of the value is represented by + // projecting the second leg a percentage equal to the ratio. The bounds + // of its variance is 1-area_ratio * the first leg of the triangle + //---------------------------------------------------------------------- + // + Scalar span = proj.x / x; + Check_Fpu(); + if (span >= 0.0f && span+area_ratio <= 1.0f) + { + return length; + } + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RightHandedTile::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //---------------------------------------------- + // See if the line hits the upper-right triangle + //---------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + + Scalar cosine; + Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //--------------------------------------------- + // See if the line hits the lower left triangle + //--------------------------------------------- + // + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + + length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //------------------------------------------- + // Neither triangle was entered, so we missed + //------------------------------------------- + // + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RightHandedTile::TestInstance() const +{ + return solidType == RightHandedTileType; +} + +//############################################################################# +//######################### LeftHandedTile ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +LeftHandedTile::LeftHandedTile( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *corners +): + RightHandedTile( + extents, + material, + owner, + next_solid, + corners, + LeftHandedTileType + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +LeftHandedTile::~LeftHandedTile() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LeftHandedTile::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //------------------------------------------------------------------- + // See if the box hits the upper-left triangle anywhere on its plane + //------------------------------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[2]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[1]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[0]; + p2.z = maxZ; + + Plane plane1(p0, p1, p2); + if (plane1.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + + // + //------------------------------------------------------------------ + // See if the box hits the lower-right triangle anywhere on its plane + //------------------------------------------------------------------ + // + p0.x = minX; + p0.y = cornerHeight[1]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[2]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[3]; + p2.z = minZ; + + Plane plane2(p0, p1, p2); + if (plane2.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + LeftHandedTile::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------- + // Figure out which triangle the point will reside in + //--------------------------------------------------- + // + Scalar rise = maxX - minX; + Scalar run = maxZ - minZ; + Verify(rise > SMALL); + Verify(run > SMALL); + + Scalar dx = point.x - minX; // HACK - needs to be set up for other diagonal + Scalar dz = point.z - minZ; + + // + //----------------------------------------------------------------- + // Set up the appropriate triangle based upon which have it lies in + //----------------------------------------------------------------- + // + Point3D p0,p1,p2; + if (dx*run > dz*rise) + { + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + } + else + { + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + } + + // + //--------------------------------------------------------------------- + // Make a plane out of the triangle, and have the plane solve for the Y + // coordinate + //--------------------------------------------------------------------- + // + Plane plane(p0, p1, p2); + Verify(!Small_Enough(plane.normal.y)); + Scalar height = point.y - plane.CalculateY(point.x, point.z); + Check_Fpu(); + return height; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LeftHandedTile::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //---------------------------------------------- + // See if the line hits the upper-right triangle + //---------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[2]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[1]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[0]; + p2.z = maxZ; + + Scalar cosine; + Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //--------------------------------------------- + // See if the line hits the lower left triangle + //--------------------------------------------- + // + p0.x = minX; + p0.y = cornerHeight[1]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[2]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[3]; + p2.z = minZ; + + length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //------------------------------------------- + // Neither triangle was entered, so we missed + //------------------------------------------- + // + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LeftHandedTile::TestInstance() const +{ + return solidType == LeftHandedTileType; +} diff --git a/CODE/RP/MUNGA/BOXTREE.CPP b/CODE/RP/MUNGA/BOXTREE.CPP new file mode 100644 index 0000000..83039c0 --- /dev/null +++ b/CODE/RP/MUNGA/BOXTREE.CPP @@ -0,0 +1,1365 @@ +//===========================================================================// +// File: boxtree.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box based spatialization // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/08/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXTREE_HPP) +# include +#endif + +#if !defined(POINT3D_HPP) +# include +#endif + +#if !defined(LINE_HPP) +# include +#endif + +//############################################################################# +//######################### BoundingBoxTreeNode ######################### +//############################################################################# + +MemoryBlock + BoundingBoxTreeNode::AllocatedMemory( + sizeof(BoundingBoxTreeNode), + 500, + 50, + "BoundingBoxTree Nodes" + ); + +int + BoundingBoxTreeNode::TraversalOrder[6]={4,5,0,1,2,3}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTreeNode::SetTraversalOrder( + int first, + int second, + int third + ) +{ + Verify((unsigned)first <= Z_Axis && first != second); + Verify((unsigned)second <= Z_Axis && second != third); + Verify((unsigned)third <= Z_Axis && third != first); + + TraversalOrder[0] = first << 1; + TraversalOrder[1] = TraversalOrder[0] + 1; + TraversalOrder[2] = second << 1; + TraversalOrder[3] = TraversalOrder[2] + 1; + TraversalOrder[4] = third << 1; + TraversalOrder[5] = TraversalOrder[4] + 1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxTreeNode::BoundingBoxTreeNode( + BoundingBox *volume, + const ExtentBox &extents +) +{ + Check_Pointer(this); + Check(&extents); + + nodeExtents = extents; + staticContents = volume; + innerNode = NULL; + for (int i=0; i nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] < nodeExtents[face]; + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (clipped_box[face] < nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] > nodeExtents[face]; + } + else + { + continue; + } + } + + // + //--------------------------------------------------------------------- + // If the new box is to be clipped, save the old value for the opposite + // face and replace it with this space's bounding face + //--------------------------------------------------------------------- + // + if (is_clipped) + { + save = clipped_box[opp_face]; + clipped_box[opp_face] = nodeExtents[face]; + } + + // + //----------------------------------------------------------------------- + // Make sure that we are not registering an empty slice of the new volume + //----------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + + // + //-------------------------------------------------------------------- + // If no spaces have been defined within the facing voxel, construct + // a new one out of the clipped box, otherwise call this routine again + // with the given voxel and the clipped box + //-------------------------------------------------------------------- + // + if (!nodeBranches[face]) + { + nodeBranches[face] = + new BoundingBoxTreeNode(volume, clipped_box); + Register_Object(nodeBranches[face]); + } + else + { + Check(nodeBranches[face]); + nodeBranches[face]->Add(volume, clipped_box); + } + } + + // + //--------------------------------------------------------------------- + // If no clipping was necessary for this voxel, then no portion of + // the box remains to be tested, so abort the loop. Otherwise, restore + // the opposing face of the new box, and clip the newly created + // voxel out of the new box + //--------------------------------------------------------------------- + // + if (!is_clipped) + return; + clipped_box[opp_face] = save; + clipped_box[face] = nodeExtents[face]; + } + + //----------------------------------------------------------------------- + // Make sure that we are not registering an empty slice of the new volume + //----------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + + // + //---------------------------------------------------------------------- + // The remaining portion of the box is inside our current space, so link + // it there + //---------------------------------------------------------------------- + // + if (!innerNode) + { + innerNode = new BoundingBoxTreeNode(volume, clipped_box); + Register_Object(innerNode); + } + else + { + Check(innerNode); + innerNode->Add(volume, clipped_box); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTreeNode::Remove( + BoundingBox *volume, + const ExtentBox &extents + ) +{ + Check(this); + Check(volume); + Check(&extents); + + // + //---------------------------------------------------------------------- + // If this node contains the desired volume, immediately NULL it out and + // return + //---------------------------------------------------------------------- + // + if (staticContents == volume) + { + staticContents = NULL; + return; + } + + // + //--------------------------------------------------- + // Make our copy of the new box for clipping purposes + //--------------------------------------------------- + // + ExtentBox clipped_box(extents); + + // + //------------------------------------------------------------------------ + // Check along each of the six faces, separately clipping off elements of + // the new box which do not lie within this voxel + //------------------------------------------------------------------------ + // + for (int i=0; i<6; ++i) + { + int + is_clipped; + Scalar + save; + + // + //------------------------------------------------------------------ + // Handle testing the maximum value side of the box. Make sure that + // volumes actually extend into the current voxel before they are + // clipped, preventing insertion of zero-thickness voxels + //------------------------------------------------------------------ + // + int face = TraversalOrder[i]; + int opp_face = face^1; + if (face&1) + { + if (clipped_box[face] > nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] < nodeExtents[face]; + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (clipped_box[face] < nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] > nodeExtents[face]; + } + else + { + continue; + } + } + + // + //--------------------------------------------------------------------- + // If the new box is to be clipped, save the old value for the opposite + // face and replace it with this space's bounding face + //--------------------------------------------------------------------- + // + if (is_clipped) + { + save = clipped_box[opp_face]; + clipped_box[opp_face] = nodeExtents[face]; + } + + // + //--------------------------------------------------------------------- + // Because the volume has already been added, branches must exist along + // all faces it gets clipped by unless it was an empty slice + //--------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + Check(nodeBranches[face]); + nodeBranches[face]->Remove(volume, clipped_box); + } + + // + //--------------------------------------------------------------------- + // If no clipping was necessary for this voxel, then no portion of + // the box remains to be tested, so abort the loop. Otherwise, restore + // the opposing face of the new box, and clip the newly created + // voxel out of the new box + //--------------------------------------------------------------------- + // + if (!is_clipped) + return; + clipped_box[opp_face] = save; + clipped_box[face] = nodeExtents[face]; + } + + // + //-------------------------------------------------------------------------- + // If we are not dealing with an empty slice of the volume, the remaining + // slice of the extents must have been entered as internal subspacing + //-------------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + Check(innerNode); + innerNode->Remove(volume, clipped_box); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxTreeNode* + BoundingBoxTreeNode::FindSmallestNodeContaining( + const ExtentBox &extents, + BoundingBoxTreeNode *parent + ) +{ + Check(&extents); + + // + //------------------------------------------------------------------------ + // Check along each of the six faces to see if this volume cuts any of the + // planes of the node, + //------------------------------------------------------------------------ + // + BoundingBoxTreeNode *branch = this; +Check_Node: + Check(branch); + for (int i=0; i<6; ++i) + { + // + //------------------------------------------------- + // Handle testing the maximum value side of the box + //------------------------------------------------- + // + int face = TraversalOrder[i]; + int opp_face = face^1; + if (face&1) + { + if (extents[face] > branch->nodeExtents[face]) + { + if (extents[opp_face] <= branch->nodeExtents[face]) + { + return (parent) ? parent : branch; + } + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (extents[face] < branch->nodeExtents[face]) + { + if (extents[opp_face] >= branch->nodeExtents[face]) + { + return (parent) ? parent : branch; + } + } + else + { + continue; + } + } + + // + //---------------------------------------------------- + // If no branch exists, then this is the smallest node + //---------------------------------------------------- + // + if (!branch->nodeBranches[face]) + { + return (parent) ? parent : branch; + } + branch = branch->nodeBranches[face]; + Check(branch); + goto Check_Node; + } + + // + //--------------------------------------------------------- + // If no inner space exists, then this is the smallest node + //--------------------------------------------------------- + // + if (!branch->innerNode) + { + return branch; + } + + // + //------------------------------------------------------------------------- + // Once we cross into an innerspace, we have to modify the behaviour of the + // previous, as a volume which is enclosed by the node could itself enclose + // the innerspace node, meaning that the parent node should be reported as + // the smallest node + //------------------------------------------------------------------------- + // + parent = branch; + branch = branch->innerNode; + Check(branch); + goto Check_Node; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxTreeNode* + BoundingBoxTreeNode::FindSmallestNodeContainingColumn( + const ExtentBox &extents + ) +{ + Check(&extents); + + // + //------------------------------------------------------------------------ + // Check along each of the six faces to see if this volume cuts any of the + // planes of the node, + //------------------------------------------------------------------------ + // + BoundingBoxTreeNode *branch = this; +Check_Node: + Check(this); + for (int i=0; i<4; ++i) + { + // + //------------------------------------------------- + // Handle testing the maximum value side of the box + //------------------------------------------------- + // + int face = TraversalOrder[i]; + int opp_face = face^1; + if (face&1) + { + if (extents[face] > branch->nodeExtents[face]) + { + if (extents[opp_face] <= branch->nodeExtents[face]) + { + return branch; + } + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (extents[face] < branch->nodeExtents[face]) + { + if (extents[opp_face] >= branch->nodeExtents[face]) + { + return branch; + } + } + else + { + continue; + } + } + + // + //---------------------------------------------------- + // If no branch exists, then this is the smallest node + //---------------------------------------------------- + // + if (!branch->nodeBranches[face]) + { + return branch; + } + branch = branch->nodeBranches[face]; + Check(branch); + goto Check_Node; + } + + return branch; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTreeNode::FindBoundingBoxContaining( + const Point3D &point, + BoundingBox *parent + ) +{ + Check(this); + Check(&point); + + // + //---------------------------------------------------- + // Set the content pointer to point at this root voxel + //---------------------------------------------------- + // + BoundingBoxTreeNode + *branch = this; + + // + //------------------------------------------------------------------------- + // Keep checking our voxel branches until the point lies inside the current + // voxel + //------------------------------------------------------------------------- + // +Check_Node: + Check(branch); + for (int i=0; i<6; ++i) + { + // + //------------------------------------------------------- + // Keep looking if the point is not beyond a given extent + //------------------------------------------------------- + // + int face = TraversalOrder[i]; + int axis = face >> 1; + if (face&1) + { + if (point[axis] <= branch->nodeExtents[face]) + { + continue; + } + } + else if (point[axis] >= branch->nodeExtents[face]) + { + continue; + } + + // + //----------------------------------------------------------------------- + // The point lies in a side's subspace, so make sure that the subspace on + // that side exists. If not, no voxel will contain the point so return + // the parent. If a facing subspace exists, set the branch pointer to + // that subspace, then check to see where the point is relative to that + // subspace + //----------------------------------------------------------------------- + // + if (!branch->nodeBranches[face]) + { + return parent; + } + branch = branch->nodeBranches[face]; + goto Check_Node; + } + + // + //------------------------------------------------------------------------- + // Since we exited the loop, we have to check inside the node to see if it + // has been subspaced. If so, restart the function again on the internal + // subspace, using the contents of this subspace as the new parent solid. + // + // Note that negative space will not be correctly handled for cases where + // the space being carved out does not fully occupy the zones it is in such + // as with a cylinder + //------------------------------------------------------------------------- + // + if (branch->innerNode) + { + if (branch->staticContents) + { + Check(branch->staticContents); + if (branch->staticContents->ContainsBounded(point)) + { + parent = branch->staticContents; + } + } + else + { + parent = NULL; + } + branch = branch->innerNode; + goto Check_Node; + } + + // + //---------------------------------------------------------------------- + // If our content pointer is NULL, then this node is considered negative + // space, and thus empty + //---------------------------------------------------------------------- + // + if (!branch->staticContents) + { + return NULL; + } + + // + //-------------------------------------------------------------------------- + // We are pointing at a real solid, so if it does in fact contain our point, + // go ahead a return the volume, otherwise return our parent volume + //-------------------------------------------------------------------------- + // + Check(branch->staticContents); + if (branch->staticContents->ContainsBounded(point)) + { + parent = branch->staticContents; + } + return parent; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTreeNode::FindBoundingBoxesContaining( + BoundingBox *volume, + const ExtentBox &slice, + BoundingBoxCollisionList &list + ) +{ + Check(this); + Check(volume); + Check(&slice); + Check(&list); + Verify(list.collisionsLeft>0); + + // + //--------------------------------------------------------------------- + // Check along each of the six faces, to see if any portion of the test + // volume lies within any of the subspace partitions + //--------------------------------------------------------------------- + // + ExtentBox clipped_box = slice; + for (int i=0; i<6; ++i) + { + int + is_clipped; + Scalar + save; + + // + //----------------------------------------------------------------------- + // Figure out the opposing face, then check to see if we are testing + // against a maximum face. If so, check to see if some part of the test + // volume protrudes into the defined subspace. If it does, figure out if + // some portion of the test volume remains to be checked, otherwise keep + // checking faces + //----------------------------------------------------------------------- + // + int face = TraversalOrder[i]; + int opp_face = face ^ 1; + if (face&1) + { + if (clipped_box[face] > nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] <= nodeExtents[face]; + } + else + { + continue; + } + } + + // + //----------------------------------------------------------------------- + // Otherwise, we are testing against a maximum face. If so, check to see + // if some part of the test volume protrudes into the defined subspace. + // If it does, figure out if some portion of the test volume remains to + // be checked, otherwise keep checking faces + //----------------------------------------------------------------------- + // + else + { + if (clipped_box[face] < nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] >= nodeExtents[face]; + } + else + { + continue; + } + } + + // + //------------------------------------------------------------------- + // If the test volume needs to be clipped, save the old value for the + // opposite face and replace it with this space's bounding face + //------------------------------------------------------------------- + // + if (is_clipped) + { + save = clipped_box[opp_face]; + clipped_box[opp_face] = nodeExtents[face]; + } + + // + //---------------------------------------------------------------------- + // If a facing node exists, call this routine again with it and the part + // of the test volume we just trimmed off + //---------------------------------------------------------------------- + // + if (nodeBranches[face]) + { + Check(nodeBranches[face]); + nodeBranches[face]->FindBoundingBoxesContaining( + volume, + clipped_box, + list + ); + } + + // + //----------------------------------------------------------------------- + // If no clipping was necessary for this subspace, or we found no entries + // remain in the collision list, we are done checking, so just return + //----------------------------------------------------------------------- + // + if (!is_clipped || !list.collisionsLeft) + { + return; + } + + // + //------------------------------------------------------------------ + // Otherwise, restore the opposing face of the new box, and clip the + // already tested slice out of the test volume + //------------------------------------------------------------------ + // + clipped_box[opp_face] = save; + clipped_box[face] = nodeExtents[face]; + } + + // + //------------------------------------------------------------------------- + // If we exited the loop, then we have to check inside the node. If this + // node is not a hole, make sure that it collides against the slice. If it + // doesn't, don't override the parent setting, otherwise do override it + //------------------------------------------------------------------------- + // + BoundingBox *hit = NULL; + if (staticContents) + { + Check(staticContents); + if (staticContents->IntersectsBounded(clipped_box)) + { + hit = staticContents; + } + } + + // + //------------------------------------------------------------------ + // If the solid has been subspaced, have it check against collisions + //------------------------------------------------------------------ + // + if (innerNode) + { + Check(innerNode); + innerNode->FindBoundingBoxesContaining( + volume, + clipped_box, + list + ); + } + + // + //------------------------------------------------------------------------- + // Otherwise, if the volume this node points to is not a hole, go ahead and + // add it to the list + //------------------------------------------------------------------------- + // + if (hit && list.collisionsLeft) + { + Check(hit); + list.AddCollisionToList(hit, clipped_box); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTreeNode::FindBoundingBoxUnder( + const Point3D &point, + Scalar* height + ) +{ + Check(this); + Check(&point); + Check_Pointer(height); + Verify((TraversalOrder[4]>>1) == Y_Axis) + + BoundingBoxTreeNode *branch = this; + BoundingBox *floor; + + // + //-------------------------------------------------------------------------- + // Check along each of the faces to see if the point lies within any of + // these subspaces. Note the change in the comparison resulting in only the + // first four coordinates (for X and Z) being checked, as the Y coordinate + // needs special treatment + //-------------------------------------------------------------------------- + // +Find_Column: + Check(branch); + for (int i=0; i<4; ++i) + { + int face = TraversalOrder[i]; + int axis = face >> 1; + if (face&1) + { + if (point[axis] <= branch->nodeExtents[face]) + { + continue; + } + } + else if (point[axis] >= branch->nodeExtents[face]) + { + continue; + } + + // + //--------------------------------------------------------------------- + // If a facing subspace exists, start this routine again with the given + // subspace and the point. If it doesn't exist, nothing will be hit + //--------------------------------------------------------------------- + // + if (branch->nodeBranches[face]) + { + branch = branch->nodeBranches[face]; + goto Find_Column; + } + else + { + *height = -1.0f; + return NULL; + } + } + + // + //------------------------------------------------------------------------- + // We now know that the object has a presence along the line defined by the + // projection of the point unto the XZ plane. If the point lies above the + // object, and other objects exist in the maxZ subspace, and they are able + // to determine the height, return the height they returned + //------------------------------------------------------------------------- + // + if (point.y > branch->nodeExtents.maxY && branch->nodeBranches[3]) + { + Check(branch->nodeBranches[3]); + floor = branch->nodeBranches[3]->FindBoundingBoxUnder(point, height); + if (floor) + { + return floor; + } + } + + // + //-------------------------------------------------------------------------- + // Handle processing the ray internal to this solid if we need to project + // the ray into our solid. If we are negative space, allow the ray to + // project through the node unhindered. + // + // Note that this code will not properly handle going through negative space + // if the negative space does not completely bore through solids + //-------------------------------------------------------------------------- + // + if (point.y >= branch->nodeExtents.minY) + { + if (branch->staticContents) + { + Check(branch->staticContents); + floor = branch->staticContents; + *height = branch->staticContents->FindDistanceBelowBounded(point); + if (*height == -1.0f || point.y - *height < branch->nodeExtents.minY) + { + goto Missed_Us; + } + } + else + { +Missed_Us: + floor = NULL; + *height = -1.0f; + } + + // + //----------------------------------------------------------------------- + // If there is internal space defined, we will rely upon it to return the + // proper value if it supersedes this node's height value + //----------------------------------------------------------------------- + // + if (branch->innerNode) + { + Check(branch->innerNode); + Scalar height_2; + BoundingBox *floor_2; + floor_2 = branch->innerNode->FindBoundingBoxUnder(point, &height_2); + if (floor_2 && (height_2 < *height || !floor)) + { + *height = height_2; + floor = floor_2; + } + } + + // + //-------------------------------------------------- + // If something was struck, return that as the floor + //-------------------------------------------------- + // + if (floor) + { + return floor; + } + } + + // + //-------------------------------------------------------------------------- + // We now know that the projection went through our bounding box without + // intersecting our solid. If any objects exist in our Min_Z subspace, have + // them try and return the height + //-------------------------------------------------------------------------- + // + if (branch->nodeBranches[2]) + { + Check(branch->nodeBranches[2]); + return branch->nodeBranches[2]->FindBoundingBoxUnder(point, height); + } + + // + //-------------------------------------------------------------- + // Since there is nothing below this bounding box, return no hit + //-------------------------------------------------------------- + // + else + { + *height = -1.0f; + return NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTreeNode::FindBoundingBoxHitBy(Line *line) +{ + Check(this); + Check(line); + + int + test_queue[7]; + Scalar + enter = 0.0f, + leave = 0.0f, + perpendicular, + drift, + distance; + BoundingBox + *result; + + // + //-------------------- + // Set up for the test + //-------------------- + // + int first = 0; + int last = 6; + Logical entered = False; + Logical left = False; + int i; + for (i=0; i<6; ++i) + { + // + //-------------------------------------------------------------------- + // Figure out what axis we are dealing with, then based upon the + // direction of the face, find out the distance from the origin to the + // place against the normal, and find out how fast the perpendicular + // distance changes with a unit movement along the line + //-------------------------------------------------------------------- + // + int face = TraversalOrder[i]; + int axis = face >> 1; + if (face&1) + { + perpendicular = line->origin[axis] - nodeExtents[face]; + drift = line->direction[axis]; + } + else + { + perpendicular = nodeExtents[face] - line->origin[axis]; + drift = -line->direction[axis]; + } + + // + //---------------------------------------------------------------------- + // If the line is parallel to the face, figure out whether or not the + // line origin lies within the face's half-space. If not, put it in the + // list and abort the loop + //---------------------------------------------------------------------- + // + if (Small_Enough(drift)) + { + if (perpendicular > 0.0f) + { + if (nodeBranches[face]) + { + test_queue[first++] = face; + } + break; + } + else + { + continue; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + distance = -perpendicular / drift; + if (drift < 0.0f) + { + if (!entered) + { + entered = True; + enter = distance; + } + else if (distance > enter) + { + enter = distance; + } + + // + //-------------------------------------------------------------------- + // Queue up the node branch if the origin lies outside of this plane's + // halfspace. If the line cannot reach the plane, abort any more + // testing + //-------------------------------------------------------------------- + // + if (perpendicular >= 0.0f) + { + if (nodeBranches[face]) + { + test_queue[first++] = face; + } + if (distance > line->length || left && enter > leave) + { + break; + } + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + else + { + if (!left) + { + left = True; + leave = distance; + } + else if (distance < leave) + { + leave = distance; + } + + // + //-------------------------------------------------------------------- + // Queue up the node branch if the origin lies outside of this plane's + // halfspace, and stop further testing. If the origin is inside the + // halfspace, register this branch if the line will reach the plane + //-------------------------------------------------------------------- + // + if (perpendicular >= 0.0f) + { + if (nodeBranches[face]) + { + test_queue[last--] = face; + } + break; + } + if (distance <= line->length) + { + if (nodeBranches[face]) + { + test_queue[last--] = face; + } + } + if (entered && leave < enter) + { + break; + } + } + } + + // + //------------------------------------------------------------------------- + // If the loop exited normally, check to see if the bounding box was struck + // by the ray. If it was, then the interior of the voxel must be checked. + // We know that the box was hit if the farthest face opposing the ray + // direction is not farther than the nearest face not opposing the ray + //------------------------------------------------------------------------- + // + if (i == 6) + { + test_queue[last--] = 6; + } + + // + //------------------------------------------------------------------------- + // Step through the queue, checking in each of the identified regions to be + // processed first. If a hit is found in one of these, immediately return + // the result + //------------------------------------------------------------------------- + // + for (i=0; iFindBoundingBoxHitBy(line); + if (result) + { + Check(result); + return result; + } + } + + // + //----------------------------------- + // Process the interior if it's there + //----------------------------------- + // + if (last<6 && test_queue[last+1] == 6) + { + result = NULL; + if (!staticContents) + { + if (innerNode) + { + Check(innerNode); + result = innerNode->FindBoundingBoxHitBy(line); + } + } + else + { + Check(staticContents); + if (staticContents->HitByBounded(line, enter, leave)) + { + result = staticContents; + } + if (innerNode) + { + Check(innerNode); + BoundingBox + *result2 = innerNode->FindBoundingBoxHitBy(line); + if (result2) + { + result = result2; + } + } + } + + // + //--------------------------------------------------------------------- + // If the ray hit something, return the result, otherwise increment the + // last pointer so that we don't process this subspace again + //--------------------------------------------------------------------- + // + if (result) + { + Check(result); + return result; + } + last++; + } + + // + //------------------------------------------------------------------------- + // Step through the queue, checking in each of the identified regions to be + // processed last. If a hit is found, immediately return the result + //------------------------------------------------------------------------- + // + for (i=last+1; i<7; ++i) + { + Check(nodeBranches[test_queue[i]]); + result = nodeBranches[test_queue[i]]->FindBoundingBoxHitBy(line); + if (result) + { + Check(result); + return result; + } + } + + // + //---------------------------------------------------------- + // The ray hit nothing in this voxel, so return the sentinel + //---------------------------------------------------------- + // + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxTreeNode::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################### BoundingBoxTree ########################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTree::Add( + BoundingBox* volume, + const ExtentBox &slice + ) +{ + Check(this); + Check(volume); + + if (!root) + { + root = new BoundingBoxTreeNode(volume, slice); + Register_Object(root); + } + else + { + Check(root); + root->Add(volume, slice); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTree::EraseTree() +{ + if (root) + { + Unregister_Object(root); + delete root; + } + root = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTree::FindBoundingBoxHitBy(Line *line) +{ + Check(this); + Check(line); + Check(root); + + Point3D line_end; + line->FindEnd(&line_end); + ExtentBox line_volume(line->origin, line_end); + return + root->FindSmallestNodeContaining(line_volume, NULL) + ->FindBoundingBoxHitBy(line); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxTree::TestInstance() const +{ + return True; +} + diff --git a/CODE/RP/MUNGA/BOXWEDGE.CPP b/CODE/RP/MUNGA/BOXWEDGE.CPP new file mode 100644 index 0000000..795b851 --- /dev/null +++ b/CODE/RP/MUNGA/BOXWEDGE.CPP @@ -0,0 +1,892 @@ +//===========================================================================// +// File: boxsolid.cc // +// Project: MUNGA Brick: Spatializer Library // +// Contents: Implementation details of bounding-box collision subtypes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 JMA Initial port back to C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(PLANE_HPP) +# include +#endif + +extern Logical + BoxedRampContainsLine( + Line *line, + const Plane& plane, + Scalar enters, + Scalar leaves + ); + +//############################################################################# +//################# BoxedWedgeFacingNegativeZAndPositiveX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndPositiveX::BoxedWedgeFacingNegativeZAndPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingNegativeZAndPositiveXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndPositiveX::~BoxedWedgeFacingNegativeZAndPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - minX; + Scalar z = extents.minZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingNegativeZAndPositiveX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = maxX - minX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise >= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = minZ - maxZ; + ramp.normal.y = 0.0f; + ramp.normal.z = maxX - minX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = maxX*ramp.normal.x + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::TestInstance() const +{ + return solidType == WedgeFacingNegativeZAndPositiveXType; +} + +//############################################################################# +//################# BoxedWedgeFacingPositiveZAndNegativeX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndNegativeX::BoxedWedgeFacingPositiveZAndNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingPositiveZAndNegativeXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndNegativeX::~BoxedWedgeFacingPositiveZAndNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - maxX; + Scalar z = extents.maxZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingPositiveZAndNegativeX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = minX - maxX; + Scalar rise = minZ - maxZ; + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise >= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = maxZ - minZ; + ramp.normal.y = 0.0f; + ramp.normal.z = minX - maxX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = maxX*ramp.normal.x + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::TestInstance() const +{ + return solidType == WedgeFacingPositiveZAndNegativeXType; +} + +//############################################################################# +//################# BoxedWedgeFacingPositiveZAndPositiveX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndPositiveX::BoxedWedgeFacingPositiveZAndPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingPositiveZAndPositiveXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndPositiveX::~BoxedWedgeFacingPositiveZAndPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - minX; + Scalar z = extents.maxZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingPositiveZAndPositiveX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = maxX - minX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise <= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = minZ - maxZ; + ramp.normal.y = 0.0f; + ramp.normal.z = minX - maxX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = maxX*ramp.normal.x + minZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::TestInstance() const +{ + return solidType == WedgeFacingPositiveZAndPositiveXType; +} + +//############################################################################# +//################# BoxedWedgeFacingNegativeZAndNegativeX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndNegativeX::BoxedWedgeFacingNegativeZAndNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingNegativeZAndNegativeXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndNegativeX::~BoxedWedgeFacingNegativeZAndNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - maxX; + Scalar z = extents.minZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingNegativeZAndNegativeX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = minX - maxX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise <= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = maxZ - minZ; + ramp.normal.y = 0.0f; + ramp.normal.z = maxX - minX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = minX*ramp.normal.x + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::TestInstance() const +{ + return solidType == WedgeFacingNegativeZAndNegativeXType; +} + diff --git a/CODE/RP/MUNGA/CAMINST.CPP b/CODE/RP/MUNGA/CAMINST.CPP new file mode 100644 index 0000000..69437da --- /dev/null +++ b/CODE/RP/MUNGA/CAMINST.CPP @@ -0,0 +1,590 @@ +//===========================================================================// +// File: caminst.cc // +// Project: Munga // +// Contents: Class CameraInstance Data and Manipulation of one camera's // +// position and orientation // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/08/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +// Munga Includes +// +#include +#pragma hdrstop + +#if !defined(CAMINST_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +//########################################################################## +//############################# CameraInstance ####################### +//########################################################################## + +//########################################################################## +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance::CameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type +) +{ + Str_Copy(cameraName, "camera", sizeof(cameraName)); + itoa(camera_ID, cameraName+6, 10); + cameraID = camera_ID; + cameraDataType = camera_type; + SetLocalOrigin(camera_origin); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance::CameraInstance(StreamedInstance *model) +{ + cameraID = model->cameraID; + localOrigin = model->localOrigin; + cameraToWorld = localOrigin; + cameraDataType = model->cameraType; + for (int i=0; i<4; ++i) + { + clampValues[i] = model->clampValues[i]; + } + Str_Copy(cameraName, "camera", sizeof(cameraName)); + itoa(cameraID, cameraName+6, 10); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define READ_CAMERA_ENTRY(name,value)\ + if (\ + !cam_file->GetEntry(\ + camera_page_name,\ + name,\ + &value\ + )\ + )\ + { \ + DEBUG_STREAM << camera_page_name << " missing " name "!\n";\ + Fail("Bad cameras!");\ + } + +CameraInstance::CameraInstance( + NotationFile *cam_file, + const char *camera_page_name +) +{ + Check(this); + Check(cam_file); + Check_Pointer(camera_page_name); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PageName represents the cameraName + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Str_Copy(cameraName, camera_page_name, sizeof(cameraName)); + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Read in the position + //~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("tranx", localOrigin.linearPosition.x); + READ_CAMERA_ENTRY("trany", localOrigin.linearPosition.y); + READ_CAMERA_ENTRY("tranz", localOrigin.linearPosition.z); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the Orientation + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("quatx", localOrigin.angularPosition.x); + READ_CAMERA_ENTRY("quaty", localOrigin.angularPosition.y); + READ_CAMERA_ENTRY("quatz", localOrigin.angularPosition.z); + READ_CAMERA_ENTRY("quatw", localOrigin.angularPosition.w); + cameraToWorld = localOrigin; + + // + //--------------------- + // Read in camera clamp + //--------------------- + // + clampValues[0] = -PI; + cam_file->GetEntry( + camera_page_name, + "minYawClamp", + &clampValues[0].angle + ); + clampValues[1] = PI; + cam_file->GetEntry( + camera_page_name, + "maxYawClamp", + &clampValues[1].angle + ); + clampValues[2] = -PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "minPitchClamp", + &clampValues[2].angle + ); + clampValues[3] = PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "maxPitchClamp", + &clampValues[3].angle + ); + + // + // Overwrite default cameraID + // + const char *camera_data_entry; + if( + !cam_file->GetEntry( + camera_page_name, + "cameraType", + &camera_data_entry + ) + ) + { + cameraDataType = DefaultCameraType; + } + else + { + Check_Pointer(camera_data_entry); + cameraDataType = FindCameraType(camera_data_entry); + } + + READ_CAMERA_ENTRY("cameraID", cameraID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance::~CameraInstance() +{ +} + +//########################################################################## +// Data Access Funtions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + CameraInstance::FindCameraType(const char *camera_data_type) +{ + + if(strcmp("DefaultCameraType", camera_data_type) == 0) + { + return DefaultCameraType; + } + else if(strcmp("AlwaysSeesCameraType", camera_data_type) == 0) + { + return AlwaysSeesCameraType; + } + return ErrorCameraType; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void + CameraInstance::GetCameraTypeString(char *camera_type_string) +{ + switch(cameraDataType) + { + case DefaultCameraType: + Str_Copy( + camera_type_string, + "DefaultCameraType", + (sizeof(char) * 128) + ); + break; + case AlwaysSeesCameraType: + Str_Copy( + camera_type_string, + "AlwaysSeesCameraType", + (sizeof(char) * 128) + ); + break; + default: + Tell(cameraDataType); + Warn(" Invalid cameraType !\n"); + break; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::CalculateCameraRotation( + YawPitchRoll *result, + const Point3D &world + ) +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Given a Vector this function finds a rotation involving only + // pitch and yaw, roll will not be affected. In addition the rotation + // chosed will always be in the direction of least rotation + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(this); + Check(result); + Check(&world); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // find the vector from where we are to where we want to point + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Point3D local; + local.MultiplyByInverse(world, cameraToWorld); + if (Small_Enough(local.LengthSquared())) + { + *result = YawPitchRoll::Identity; + return; + } + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Calculate the angles + //~~~~~~~~~~~~~~~~~~~~~ + // + result->yaw = Radian::Normalize(Arctan(-local.x, -local.z)); + Scalar xz_direction = Sqrt((local.x * local.x) + (local.z *local.z)); + result->pitch = Radian::Normalize(Arctan(local.y, xz_direction)); + result->roll = 0.0f; + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::SetLocalOrigin( + const Origin &new_origin + ) +{ + Check(this); + Check(&new_origin); + + YawPitchRoll ypr; + ypr = new_origin.angularPosition; + clampValues[0] = clampValues[1] = 0.0f; + clampValues[2] = clampValues[3] = ypr.pitch; + ypr.pitch = 0.0f; + localOrigin.linearPosition = new_origin.linearPosition; + localOrigin.angularPosition = ypr; + cameraToWorld = localOrigin; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::LookAt( + Origin *result, + const Point3D &world_point + ) +{ + result->linearPosition = localOrigin.linearPosition; + YawPitchRoll first,local; + first = localOrigin.angularPosition; + CalculateCameraRotation(&local, world_point); + Clamp(local.yaw, clampValues[0], clampValues[1]); + Clamp(local.pitch, clampValues[2], clampValues[3]); + first.yaw += local.yaw; + first.pitch = local.pitch; + result->angularPosition = first; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::AllowLookingAt(const Point3D &world) +{ + YawPitchRoll local; + CalculateCameraRotation(&local, world); + if (local.yaw < clampValues[0]) + { + clampValues[0] = local.yaw; + } + else if (local.yaw > clampValues[1]) + { + clampValues[1] = local.yaw; + } + if (local.pitch < clampValues[2]) + { + clampValues[2] = local.pitch; + } + else if (local.pitch > clampValues[3]) + { + clampValues[3] = local.pitch; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define YAW_SLOP (PI/12.0) +#define PITCH_SLOP (0.75*(YAW_SLOP)) + +Logical + CameraInstance::CanCameraSee(const Point3D &world_point) +{ + YawPitchRoll ypr; + CalculateCameraRotation(&ypr, world_point); + return + clampValues[0]-YAW_SLOP <= ypr.yaw + && clampValues[1]+YAW_SLOP >= ypr.yaw + && clampValues[2]-PITCH_SLOP <= ypr.pitch + && clampValues[3]+PITCH_SLOP >= ypr.pitch; +} + +//########################################################################## +// Test Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraInstance::TestInstance() const +{ + return True; +} + +//########################################################################## +// Tool Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::WriteNotationPage(NotationFile *camera_stream) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Output this camera's information to the given notation file +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(this); + Check(camera_stream); + camera_stream->SetEntry( + cameraName, + "cameraID", + cameraID + ); + + char camera_type[128]; + GetCameraTypeString(camera_type); + camera_stream->SetEntry( + cameraName, + "cameraType", + camera_type + ); + + camera_stream->SetEntry( + cameraName, + "tranx", + localOrigin.linearPosition.x + ); + camera_stream->SetEntry( + cameraName, + "trany", + localOrigin.linearPosition.y + ); + camera_stream->SetEntry( + cameraName, + "tranz", + localOrigin.linearPosition.z + ); + camera_stream->SetEntry( + cameraName, + "quatx", + localOrigin.angularPosition.x + ); + camera_stream->SetEntry( + cameraName, + "quaty", + localOrigin.angularPosition.y + ); + camera_stream->SetEntry( + cameraName, + "quatz", + localOrigin.angularPosition.z + ); + camera_stream->SetEntry( + cameraName, + "quatw", + localOrigin.angularPosition.w + ); + camera_stream->SetEntry( + cameraName, + "minYawClamp", + clampValues[0] + ); + camera_stream->SetEntry( + cameraName, + "maxYawClamp", + clampValues[1] + ); + camera_stream->SetEntry( + cameraName, + "minPitchClamp", + clampValues[2] + ); + camera_stream->SetEntry( + cameraName, + "maxPitchClamp", + clampValues[3] + ); + camera_stream->AppendEntry(cameraName, NULL, (char *)NULL); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#undef READ_CAMERA_ENTRY +#define READ_CAMERA_ENTRY(name,value)\ + if (\ + !cam_file->GetEntry(\ + camera_page_name,\ + name,\ + &value\ + )\ + )\ + { \ + DEBUG_STREAM << camera_page_name << " missing " name "!\n";\ + return False;\ + } + +Logical + CameraInstance::CreateStreamedInstance( + StreamedInstance *model, + NotationFile *cam_file, + const char *camera_page_name + ) +{ + Check_Pointer(model); + Check(cam_file); + Check_Pointer(camera_page_name); + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Read in the position + //~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("tranx", model->localOrigin.linearPosition.x); + READ_CAMERA_ENTRY("trany", model->localOrigin.linearPosition.y); + READ_CAMERA_ENTRY("tranz", model->localOrigin.linearPosition.z); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the Orientation + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("quatx", model->localOrigin.angularPosition.x); + READ_CAMERA_ENTRY("quaty", model->localOrigin.angularPosition.y); + READ_CAMERA_ENTRY("quatz", model->localOrigin.angularPosition.z); + READ_CAMERA_ENTRY("quatw", model->localOrigin.angularPosition.w); + + // + //--------------------- + // Read in camera clamp + //--------------------- + // + model->clampValues[0] = -PI; + cam_file->GetEntry( + camera_page_name, + "minYawClamp", + &model->clampValues[0].angle + ); + model->clampValues[1] = PI; + cam_file->GetEntry( + camera_page_name, + "maxYawClamp", + &model->clampValues[1].angle + ); + model->clampValues[2] = -PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "minPitchClamp", + &model->clampValues[2].angle + ); + model->clampValues[3] = PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "maxPitchClamp", + &model->clampValues[3].angle + ); + + // + // Overwrite default cameraID + // + const char *camera_data_entry; + if( + !cam_file->GetEntry( + camera_page_name, + "cameraType", + &camera_data_entry + ) + ) + { + model->cameraType = DefaultCameraType; + } + else + { + Check_Pointer(camera_data_entry); + model->cameraType = FindCameraType(camera_data_entry); + } + + READ_CAMERA_ENTRY("cameraID", model->cameraID); + + model->instanceSize = sizeof(*model); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlwaysSeesCameraInstance::AlwaysSeesCameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type +): + CameraInstance(camera_ID, camera_origin, camera_type) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlwaysSeesCameraInstance::AlwaysSeesCameraInstance(StreamedInstance *model): + CameraInstance(model) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlwaysSeesCameraInstance::AlwaysSeesCameraInstance( + NotationFile *cam_file, + const char *camera_page_name +): + CameraInstance(cam_file, camera_page_name) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + AlwaysSeesCameraInstance::CanCameraSee(const Point3D &) +{ + return True; +} diff --git a/CODE/RP/MUNGA/CAMINST.HPP b/CODE/RP/MUNGA/CAMINST.HPP new file mode 100644 index 0000000..de68f21 --- /dev/null +++ b/CODE/RP/MUNGA/CAMINST.HPP @@ -0,0 +1,201 @@ +//===========================================================================// +// File: caminst.hh // +// Project: Munga // +// Contents: CameraInstance Interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/08/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(CAMINST_HPP) +# define CAMINST_HPP + +# if !defined (PLUG_HPP) +# include +# endif + +# if !defined (ORIGIN_HPP) +# include +# endif + +# if !defined (ROTATION_HPP) +# include +# endif + +# if !defined(LINMTRX_HPP) +# include +# endif + + class NotationFile; + + struct CameraInstance__StreamedInstance + { + size_t instanceSize; + int + cameraType, + cameraID; + Origin + localOrigin; + Radian + clampValues[4]; + }; + + //########################################################################## + //############################# CameraInstance ####################### + //########################################################################## + + class CameraInstance : + public Plug + { + friend class CameraInstanceManager; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // local member data + // + public: + + enum { + ErrorCameraType, + DefaultCameraType, + AlwaysSeesCameraType, + CameraTypeCount, + }; + + Radian + clampValues[4]; + + protected: + Origin + localOrigin; + LinearMatrix + cameraToWorld; + + static int + FindCameraType(const char *camera_data_type); + + void + GetCameraTypeString(char *camera_type_string); + + Enumeration + cameraDataType; + + int + cameraID; + + char + cameraName[128]; + + void + CalculateCameraRotation( + YawPitchRoll *result, + const Point3D &world + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // public member data access functions + // + public: + int + GetCameraID() + {Check(this); return cameraID;} + + const char* + GetCameraName() + {Check(this); return cameraName;} + void + SetCameraName(const char* camera_name) + {Str_Copy(cameraName, camera_name, sizeof(cameraName));} + + const Enumeration + GetCameraType() + {Check(this); return cameraDataType;} + + const Origin& + GetLocalOrigin() + {Check(this); return localOrigin;} + void + SetLocalOrigin(const Origin &new_origin); + const Point3D& + GetPosition() + {Check(this); return localOrigin.linearPosition;} + + void + LookAt( + Origin *result, + const Point3D &world_point + ); + void + AllowLookingAt(const Point3D &world); + + virtual Logical + CanCameraSee(const Point3D &world_point); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test Class Support + // + public: + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Contruction and Destruction Support + // + public: + typedef CameraInstance__StreamedInstance StreamedInstance; + + CameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type = DefaultCameraType + ); + CameraInstance(StreamedInstance *model); + CameraInstance( + NotationFile *cam_file, + const char *camera_page_name + ); + + ~CameraInstance(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Tool Support + // + public: + void + WriteNotationPage(NotationFile *camera_stream); + static Logical + CreateStreamedInstance( + StreamedInstance *model, + NotationFile *cam_file, + const char *camera_page_name + ); + }; + + //########################################################################## + //############################# CameraInstance ####################### + //########################################################################## + + class AlwaysSeesCameraInstance : + public CameraInstance + { + public: + AlwaysSeesCameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type = DefaultCameraType + ); + AlwaysSeesCameraInstance(StreamedInstance *model); + AlwaysSeesCameraInstance( + NotationFile *cam_file, + const char *camera_page_name + ); + + Logical + CanCameraSee(const Point3D &world_point); + }; + +#endif diff --git a/CODE/RP/MUNGA/CAMMGR.CPP b/CODE/RP/MUNGA/CAMMGR.CPP new file mode 100644 index 0000000..7d1e70c --- /dev/null +++ b/CODE/RP/MUNGA/CAMMGR.CPP @@ -0,0 +1,779 @@ +//===========================================================================// +// File: cammgr.cc // +// Project: Munga // +// Contents: Implementation details of vectored thrust vehicles // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/09/95 JM Initial coding. // +// Classes: CameraInstanceManager // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +// Munga Includes +// +#include +#pragma hdrstop + +#if !defined(CAMMGR_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +//########################################################################## +//##################### CameraInstanceManager ####################### +//########################################################################## + +//########################################################################## +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstanceManager::CameraInstanceManager() : + cameraList(NULL) +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize local member data + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + cameraIterator = new SChainIteratorOf(cameraList); + Register_Object(cameraIterator); + InitializeCameraInstances(); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstanceManager::~CameraInstanceManager() +{ + DeleteCameraList(); + Unregister_Object(cameraIterator); + delete cameraIterator; + cameraIterator = NULL; + Check_Fpu(); +} + +//########################################################################## +// CameraInstance Creation and Deletion Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + CameraInstanceManager::FindUniqueCameraID() +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Finds a cameraID that has been freed up or the next sequential number +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + SChainIteratorOf iterator(cameraList); + CameraInstance *camera_instance; + int camera_ID = 0; + Logical ID_exists = False; + + while(1) + { + // + //~~~~~~~~~~~~~~~~~~~~ + // Reset the iterator + //~~~~~~~~~~~~~~~~~~~~ + // + iterator.First(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Iterate through the list of all cameraInstances for every ID Chosen + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + while ( (camera_instance = iterator.ReadAndNext()) != NULL) + { + if(camera_ID == camera_instance->GetCameraID()) + { + ID_exists = True; + break; + } + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If this cameraID not already used return the ID + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(!ID_exists) + { + break; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Otherwise increment the ID and reset the boolean + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ++camera_ID; + ID_exists = False; + } + + Check_Fpu(); + return camera_ID; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::SetCamera( + const Origin &new_origin, + CameraInstance *camera_instance + ) +{ + + if(!camera_instance) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // No camera passed as an argument use cameraIterator + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + camera_instance = cameraIterator->GetCurrent(); + if(!camera_instance) + { + CreateCameraInstance(new_origin); + } + else + { + camera_instance->SetLocalOrigin(new_origin); + } + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Camera passed in set its origin + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + camera_instance->SetLocalOrigin(new_origin); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::CreateCameraInstance(const Origin &new_origin) +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Find a Unique CameraID + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + int camera_ID; + camera_ID = FindUniqueCameraID(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the new cameraInstance + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CameraInstance *camera_instance = + new CameraInstance( + camera_ID, + new_origin + ); + Register_Object(camera_instance); + AddCameraInstance(camera_instance); + + Check_Fpu(); + return camera_instance; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::AddCameraInstance(CameraInstance *camera_instance) +{ + Check(this); + Check(cameraIterator); + Check(&cameraList); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Insert the new Camera Instance into the cameraList + // & Point the cameraIterator to it + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (!cameraIterator->GetCurrent()) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If nothing in the cameraList create the first element + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + cameraList.Add(camera_instance); + cameraIterator->First(); + Tell("Created the First Camera Instance \n"); + } + else + { + cameraList.Add(camera_instance); + cameraIterator->Next(); + Tell("Created a Camera Instance \n"); + } + Check_Fpu(); + return camera_instance; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::DeleteCameraInstance() +{ + CameraInstance *camera_instance = cameraIterator->GetCurrent(); + if(!camera_instance) + { + return NULL; + } + + cameraIterator->Remove(); + if(!cameraIterator->GetCurrent()) + { + cameraIterator->First(); + } + Unregister_Object(camera_instance); + delete camera_instance; + return GetCurrent(); +} + +//########################################################################## +// CameraList Manipulator Functions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::DeleteCameraList() +{ + while (cameraIterator->GetCurrent() != NULL) + { + DeleteCameraInstance(); + } +} + +//########################################################################## +// CameraList Iterator Manipulator Functions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::IncrementIterator() +{ + Check(this); + if (cameraIterator->GetCurrent()) + { + Check(cameraIterator); + cameraIterator->ReadAndNext(); + if (!cameraIterator->GetCurrent()) + { + cameraIterator->First(); + } + } + Check_Fpu(); + return GetCurrent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::DecrementIterator() +{ + Check(this); + if (cameraIterator->GetCurrent()) + { + Check(cameraIterator); + cameraIterator->ReadAndPrevious(); + if (!cameraIterator->GetCurrent()) + { + cameraIterator->Last(); + } + } + Check_Fpu(); + return GetCurrent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::AdvanceIterator(const CameraInstance &camera_instance) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Search for the camera_instance in the cameraList +// Iterator points to camera_instance upon return +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(&camera_instance); + Check(&cameraList); + Check(cameraIterator); + + CameraInstance *current_instance; + cameraIterator->First(); + + while((current_instance = cameraIterator->GetCurrent()) != NULL) + { + if(current_instance == &camera_instance) + { + Check_Fpu(); + return current_instance; + } + cameraIterator->Next(); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // camera_instance not found return NULL + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check_Fpu(); + return NULL; +} + +//########################################################################## +// CameraList Searching and Query Functions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::FindClosestCamera(const Point3D &point_3D) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Use a Simple distance formula to find closest camera +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(this); + CameraInstance *closest_camera = NULL; + Scalar dist_to_goal, min_dist=1e8f; + + SChainIteratorOf iterator(cameraList); + CameraInstance *camera_instance; + while ( (camera_instance = iterator.ReadAndNext()) != NULL) + { + Check(camera_instance); + if (camera_instance->CanCameraSee(point_3D)) + { + Vector3D v; + v.Subtract(point_3D, camera_instance->GetPosition()); + dist_to_goal = v.LengthSquared(); + Check_Fpu(); + if (dist_to_goal < min_dist) + { + min_dist = dist_to_goal; + closest_camera = camera_instance; + } + } + } + Check_Fpu(); + return closest_camera; +} + +//########################################################################## +// Test Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraInstanceManager::TestInstance() const +{ + return True; +} + +//########################################################################## +// Tool Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::InitializeCameraInstances() +{ + Check(application); + ResourceDescription::ResourceID map_ID; + map_ID = application->GetCurrentMission()->GetMapID(); + + ResourceFile *res_file; + res_file = application->GetResourceFile(); + Check(res_file); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the camera filename from the map name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *res = res_file->FindResourceDescription(map_ID); + Check(res); + Str_Copy( + cameraFilename, + "cameras\\", + sizeof(cameraFilename) + ); + // + // cam name matches map name + // + Str_Cat( + cameraFilename, + res->resourceName, + sizeof(cameraFilename) + ); + // + // trunc cam name to DOS filename size + // + int name_length = strlen(cameraFilename); + if(name_length > 17) + { + cameraFilename[17] = '\0'; + } + + // + // Add the extension + // + Str_Cat( + cameraFilename, + ".cam", + sizeof(cameraFilename) + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // See if the file exists + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + fstream cam_file; + cam_file.open(cameraFilename, ios::nocreate | ios::in | ios::out); + if(cam_file) + { + cam_file.close(); + ReadNotationFile(); + } + else + { + cam_file.close(); + CreateStreamedCameraInstances(res_file, res->resourceName); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::ReadNotationFile() +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a Notation file out of the camera file + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NotationFile *cam_file = new NotationFile(cameraFilename); + Register_Object(cam_file); + + NameList* camera_namelist = cam_file->MakePageList(); + Register_Object(camera_namelist); + + NameList::Entry *camera_entry = camera_namelist->GetFirstEntry(); + + char + camera_page_name[128]; + + while (camera_entry) + { + Str_Copy( + camera_page_name, + camera_entry->GetName(), + sizeof(camera_page_name) + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a new camera Instance for this page + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CameraInstance *camera_instance; + const char *camera_data_entry; + int cam_type; + if( + !cam_file->GetEntry( + camera_page_name, + "cameraType", + &camera_data_entry + ) + ) + { + cam_type = CameraInstance::DefaultCameraType; + } + else + { + Check_Pointer(camera_data_entry); + cam_type = CameraInstance::FindCameraType(camera_data_entry); + } + switch (cam_type) + { + case CameraInstance::DefaultCameraType: + camera_instance = new CameraInstance(cam_file, camera_page_name); + break; + case CameraInstance::AlwaysSeesCameraType: + camera_instance = + new AlwaysSeesCameraInstance(cam_file, camera_page_name); + break; + } + Register_Object(camera_instance); + AddCameraInstance(camera_instance); + camera_entry = camera_entry->GetNextEntry(); + } + Unregister_Object(camera_namelist); + delete camera_namelist; + Unregister_Object(cam_file); + delete cam_file; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define PAGE_NAME_SIZE 128 + +void + CameraInstanceManager::CreateStreamedCameraInstances( + ResourceFile *res_file, + const char *map_name + ) +{ + Check(this); + Check_Pointer(res_file); + Check_Pointer(map_name); + + ResourceDescription *res = + res_file->FindResourceDescription( + map_name, + ResourceDescription::CameraStreamResourceType + ); + if (!res) + { + Check_Fpu(); + return; + } + + res->Lock(); + + MemoryStream camera_stream(res->resourceAddress, res->resourceSize); + int camera_count = *(int*)camera_stream.GetPointer(); + camera_stream.AdvancePointer(sizeof(camera_count)); + + // + //-------------------- + // Read in each camera + //-------------------- + // + while (camera_count--) + { + Check(&camera_stream); + CameraInstance::StreamedInstance *model = + (CameraInstance::StreamedInstance*)camera_stream.GetPointer(); + Check_Pointer(model); + CameraInstance *camera_instance; + switch (model->cameraType) + { + case CameraInstance::DefaultCameraType: + camera_instance = new CameraInstance(model); + break; + case CameraInstance::AlwaysSeesCameraType: + camera_instance = new AlwaysSeesCameraInstance(model); + break; + } + Register_Object(camera_instance); + AddCameraInstance(camera_instance); + camera_stream.AdvancePointer(model->instanceSize); + } + res->Unlock(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::WriteNotationFile() +{ + Check(this); + Check(&cameraList); + + NotationFile *camera_stream = new NotationFile(); + Register_Object(camera_stream); + + if(!camera_stream) + { + Fail("Error Opening Camera File\n"); + } + SChainIteratorOf iterator(cameraList); + CameraInstance *camera_instance; + + iterator.First(); + while ( (camera_instance = iterator.ReadAndNext()) != NULL) + { + camera_instance->WriteNotationPage(camera_stream); + } + camera_stream->WriteFile(cameraFilename); + Unregister_Object(camera_stream); + delete camera_stream; + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define PAGE_NAME_SIZE 128 +ResourceDescription::ResourceID + CameraInstanceManager::CreateCameraInstancesStream( + ResourceFile *resource_file, + const char *camera_name, + const ResourceDirectories *directories + ) +{ + Check_Pointer(camera_name); + Check_Pointer(directories); + + // + //------------------- + // Open the .cam file + //------------------- + // + int length = strlen(camera_name) + strlen(directories->mapDirectory)+ 1; + + char *filename = new char[length]; + Register_Pointer(filename); + + Str_Copy(filename, directories->mapDirectory, length); + strncat(filename, camera_name, strlen(camera_name)-3); + Str_Cat(filename, "cam", length); + + NotationFile *camera_notation = new NotationFile(filename); + Register_Object(camera_notation); + + if (camera_notation->PageCount() == 0) + { + DEBUG_STREAM << "Missing .cam file" << endl; +Dump_And_Die: + Unregister_Object(camera_notation); + delete camera_notation; + Unregister_Pointer(filename); + delete[] filename; + return ResourceDescription::NullResourceID; + } + + int camera_count = 0; + NameList *pagelist = camera_notation->MakePageList(); + Register_Object(pagelist); + NameList::Entry *entry = pagelist->GetFirstEntry(); + char page_name[PAGE_NAME_SIZE]; + + while (entry) + { + ++camera_count; + entry = entry->GetNextEntry(); + } + + size_t array_size = + sizeof(CameraInstance::StreamedInstance) * camera_count * 2; + long *camera_array = new long[(array_size+3) >> 2]; + Register_Pointer(camera_array); + MemoryStream camera_stream(camera_array, array_size); + + *(int*)camera_stream.GetPointer() = camera_count; + camera_stream.AdvancePointer(sizeof(camera_count)); + + entry = pagelist->GetFirstEntry(); + while (entry) + { + Str_Copy( + page_name, + entry->GetName(), + sizeof(page_name) + ); + + if(strcmp(page_name, "CameraInfo") == 0) + { + entry = entry->GetNextEntry(); + continue; + } + + Check(&camera_stream); + CameraInstance::StreamedInstance *model = + (CameraInstance::StreamedInstance*)camera_stream.GetPointer(); + Check_Pointer(model); + if ( + !CameraInstance::CreateStreamedInstance( + model, + camera_notation, + page_name + ) + ) + { + Unregister_Pointer(camera_array); + delete[] camera_array; + Unregister_Object(pagelist); + delete pagelist; + goto Dump_And_Die; + } + camera_stream.AdvancePointer(model->instanceSize); + entry = entry->GetNextEntry(); + } + + // + //------------------------------- + // Write the stream out to disk. + // + + Str_Copy(filename, camera_name, length); + filename[strlen(camera_name)-4] = '\0'; + + ResourceDescription *new_res = + resource_file->AddResource( + filename, + ResourceDescription::CameraStreamResourceType, + 1, + ResourceDescription::LoadOnDemandFlag, + camera_array, + camera_stream.GetBytesUsed() + ); + Check(new_res); + + //----------- + // Free Mem + // + + + Unregister_Pointer(camera_array); + delete[] camera_array; + Unregister_Pointer(filename); + delete[] filename; + Unregister_Object(camera_notation); + delete camera_notation; + Unregister_Object(pagelist); + delete pagelist; + + return new_res->resourceID; +} + diff --git a/CODE/RP/MUNGA/CAMMGR.HPP b/CODE/RP/MUNGA/CAMMGR.HPP new file mode 100644 index 0000000..0e9cf1d --- /dev/null +++ b/CODE/RP/MUNGA/CAMMGR.HPP @@ -0,0 +1,159 @@ +//===========================================================================// +// File: cammgr.hh // +// Project: Munga // +// Contents: Camera Interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/08/95 JM Initial coding. // +// Classes: CameraInstanceManager // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(CAMMGR_HPP) +# define CAMMGR_HPP + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(CAMINST_HPP) +# include +# endif + + //########################################################################## + //##################### CameraInstanceManager ####################### + //########################################################################## + + class CameraInstanceManager SIGNATURED + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // local member data + // + protected: + // + // cameraList is a circular Linked list + // which holds cameraInstances + // + SChainOf cameraList; + // + // CameraIterator holds the current position in the + // camera list for the lifetime of the class + // & == NULL if the list is empty + // + SChainIteratorOf *cameraIterator; + + int + FindUniqueCameraID(); + + char + cameraFilename[128]; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public Member Manipulation Functions + // + public: + // + // CameraList Manipulator Functions + // + void + SetCamera( + const Origin &new_origin, + CameraInstance *camera_instance = NULL + ); + + CameraInstance* + CreateCameraInstance(const Origin &new_origin); + + CameraInstance* + AddCameraInstance(CameraInstance *camera_instance); + + CameraInstance* + DeleteCameraInstance(); + + void + DeleteCameraList(); + + // + // Iterator Manipulator Functions (Circular Chain) + // + CameraInstance* + IncrementIterator(); + + CameraInstance* + DecrementIterator(); + + CameraInstance* + AdvanceIterator(const CameraInstance &camera_instance); + + CameraInstance* + GetCurrent() const + {Check(this); return cameraIterator->GetCurrent();} + + CameraInstance* + First() + { + Check(this); + Check(cameraIterator->GetCurrent()); + cameraIterator->First(); + return GetCurrent(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CameraList Searching and Query Functions + // + public: + + CameraInstance* + FindClosestCamera(const Point3D &point_3D); + CameraInstance* + FindClosestCameraShowing(const Point3D *points); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test Class Support + // + public: + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + public: + CameraInstanceManager(); + ~CameraInstanceManager(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Tool Support + // + protected: + + void + InitializeCameraInstances(); + + public: + void + ReadNotationFile(); + void + CreateStreamedCameraInstances( + ResourceFile *res_file, + const char *map_name + ); + + void + WriteNotationFile(); + static ResourceDescription::ResourceID + CreateCameraInstancesStream( + ResourceFile *resource_file, + const char *camera_name, + const ResourceDirectories *directories + ); + }; + +#endif diff --git a/CODE/RP/MUNGA/CAMMPPR.CPP b/CODE/RP/MUNGA/CAMMPPR.CPP new file mode 100644 index 0000000..86728fb --- /dev/null +++ b/CODE/RP/MUNGA/CAMMPPR.CPP @@ -0,0 +1,262 @@ +//===========================================================================// +// File: cammppr.hpp. // +// Project: MUNGA Brick: Camera Controls Mapper // +// Contents: Interface specification for camera mapper // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/20/95 JM Initial Coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +// Munga +// +#include +#pragma hdrstop + +#if !defined(CAMMPPR_HPP) +# include +#endif + +//############################################################################# +// Shared Data Support +// +CameraControlsMapper::SharedData + CameraControlsMapper::DefaultData( + CameraControlsMapper::ClassDerivations, + CameraControlsMapper::MessageHandlers, + CameraControlsMapper::AttributeIndex, + CameraControlsMapper::StateCount + ); + +Derivation + CameraControlsMapper::ClassDerivations( + Subsystem::ClassDerivations, + "CameraControlsMapper" + ); + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraControlsMapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraControlsMapper, Keypress), + MESSAGE_ENTRY(CameraControlsMapper, DirectorMode), + MESSAGE_ENTRY(CameraControlsMapper, IncrementCamera), + MESSAGE_ENTRY(CameraControlsMapper, DecrementCamera), + MESSAGE_ENTRY(CameraControlsMapper, CreateCameraInstance), + MESSAGE_ENTRY(CameraControlsMapper, DeleteCameraInstance), + MESSAGE_ENTRY(CameraControlsMapper, OutputCameraInstances) +}; + +CameraControlsMapper::MessageHandlerSet + CameraControlsMapper::MessageHandlers( + ELEMENTS(CameraControlsMapper::MessageHandlerEntries), + CameraControlsMapper::MessageHandlerEntries, + Subsystem::MessageHandlers + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::KeypressMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + switch (message->dataContents) + { + case 'd': + case 'D': + { + ReceiverDataMessageOf + button_message2( + CameraControlsMapper::DirectorModeMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + Dispatch(&button_message2); + break; + } + + case 'o': + case 'O': + { + ReceiverDataMessageOf + button_message2( + CameraControlsMapper::OutputCameraInstancesMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + Dispatch(&button_message2); + break; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::DirectorModeMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + if(camera->GetSimulationState() != CameraShip::ConfigureCamerasState) + { + camera->SetPerformance(&CameraShip::DriveCamera); + camera->SetSimulationState(CameraShip::ConfigureCamerasState); + CameraInstance *cam = camera->GetCurrentCamera(); + Check(cam); + DEBUG_STREAM << cam->GetCameraName() << endl; + } + else + { + camera->SetPerformance(&CameraShip::FollowGoal); + camera->SetSimulationState(CameraShip::DefaultState); + camera->lastSwitch = Now(); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::IncrementCameraMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if(message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->IncrementCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::DecrementCameraMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->DecrementCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::CreateCameraInstanceMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->CreateCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::DeleteCameraInstanceMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->DeleteCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::OutputCameraInstancesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->OutputCameraList(); + } +} + +//############################################################################# +// Attribute Support +// +const CameraControlsMapper::IndexEntry + CameraControlsMapper::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(CameraControlsMapper, StickPosition, stickPosition), + ATTRIBUTE_ENTRY(CameraControlsMapper, ThrottlePosition, throttlePosition), + ATTRIBUTE_ENTRY(CameraControlsMapper, PedalsPosition, pedalsPosition), + ATTRIBUTE_ENTRY(CameraControlsMapper, ReverseThrust, reverseThrust), + ATTRIBUTE_ENTRY(CameraControlsMapper, DriveCamera, driveCamera), + ATTRIBUTE_ENTRY(CameraControlsMapper, SlideOrClamp, slideOrClamp) +}; + +CameraControlsMapper::AttributeIndexSet + CameraControlsMapper::AttributeIndex( + ELEMENTS(CameraControlsMapper::AttributePointers), + CameraControlsMapper::AttributePointers, + Subsystem::AttributeIndex + ); + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraControlsMapper::CameraControlsMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + Subsystem(owner, subsystem_ID, subsystem_resource, shared_data) +{ + stickPosition.x = 0.0f; + stickPosition.y = 0.0f; + throttlePosition = 0.0f; + pedalsPosition = 0.0f; + driveCamera = 0; + slideOrClamp = 0; + reverseThrust = 0; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraControlsMapper::~CameraControlsMapper() +{ +} + +Logical + CameraControlsMapper::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/CAMMPPR.HPP b/CODE/RP/MUNGA/CAMMPPR.HPP new file mode 100644 index 0000000..c3a1464 --- /dev/null +++ b/CODE/RP/MUNGA/CAMMPPR.HPP @@ -0,0 +1,163 @@ +//===========================================================================// +// File: cammppr.hpp. // +// Project: MUNGA Brick: Camera Controls Mapper // +// Contents: Interface specification for camera mapper // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/20/95 JM Initial Coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(CAMMPPR_HPP) +# define CAMMPPR_HPP + +# if !defined (SUBSYSTM_HPP) +# include +# endif + +# if !defined (CAMSHIP_HPP) +# include +# endif + +# if !defined (CONTROLS_HPP) +# include +# endif + + //########################################################################## + //####################### CameraControlsMapper ######################## + //########################################################################## + class CameraControlsMapper: + public Subsystem + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messaging Support + // + public: + enum { + KeypressMessageID = Subsystem::NextMessageID, + DirectorModeMessageID, + IncrementCameraMessageID, + DecrementCameraMessageID, + CreateCameraInstanceMessageID, + DeleteCameraInstanceMessageID, + OutputCameraInstancesMessageID, + NextMessageID + }; + + void + KeypressMessageHandler(ReceiverDataMessageOf *message); + + void + DirectorModeMessageHandler( + ReceiverDataMessageOf *message + ); + + void + IncrementCameraMessageHandler( + ReceiverDataMessageOf *message + ); + + void + DecrementCameraMessageHandler( + ReceiverDataMessageOf *message + ); + + void + CreateCameraInstanceMessageHandler( + ReceiverDataMessageOf *message + ); + + void + DeleteCameraInstanceMessageHandler( + ReceiverDataMessageOf *message + ); + + void + OutputCameraInstancesMessageHandler( + ReceiverDataMessageOf *message + ); + + protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + StickPositionAttributeID = Subsystem::NextAttributeID, + ThrottlePositionAttributeID, + PedalsPositionAttributeID, + ReverseThrustAttributeID, + DriveCameraAttributeID, + SlideOrClampAttributeID, + NextAttributeID + }; + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + ControlsJoystick stickPosition; + Scalar throttlePosition; + Scalar pedalsPosition; + ControlsButton + reverseThrust, + driveCamera, + slideOrClamp; + + //########################################################################## + // Model support + // + public: + + CameraShip* + GetEntity() + {return (CameraShip*)Subsystem::GetEntity();} + + typedef void + (CameraControlsMapper::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + protected: + CameraControlsMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data + ); + + public: + ~CameraControlsMapper(); + + Logical + TestInstance() const; + }; +#endif diff --git a/CODE/RP/MUNGA/CAMSHIP.CPP b/CODE/RP/MUNGA/CAMSHIP.CPP new file mode 100644 index 0000000..21646a2 --- /dev/null +++ b/CODE/RP/MUNGA/CAMSHIP.CPP @@ -0,0 +1,767 @@ +//===========================================================================// +// File: camship.cc // +// Project: Munga // +// Contents: CameraShip Controls the current viewpoint of the cameraShip & // +// manages the simulation modes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/09/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +// munga Includes +// +#include +#pragma hdrstop + +#if !defined(CAMSHIP_HPP) +# include +#endif + +#if !defined(PLAYER_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(CAMMPPR_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +//########################################################################## +//############################# CameraShip ################################ +//########################################################################## + +//############################################################################# +// Shared Data Support +// +Derivation + CameraShip::ClassDerivations( + Mover::ClassDerivations, + "CameraShip" + ); + +CameraShip::SharedData + CameraShip::DefaultData( + CameraShip::ClassDerivations, + CameraShip::MessageHandlers, + CameraShip::AttributeIndex, + CameraShip::StateCount, + (Entity::MakeHandler)CameraShip::Make + ); + +//############################################################################# +// Attribute Support +// + +const CameraShip::IndexEntry + CameraShip::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(CameraShip, MapRange, mapRange), + ATTRIBUTE_ENTRY(CameraShip, MapLinearPosition, mapLinearPosition), + ATTRIBUTE_ENTRY(CameraShip, MapAngularPosition, mapAngularPosition) +}; + +CameraShip::AttributeIndexSet + CameraShip::AttributeIndex( + ELEMENTS(CameraShip::AttributePointers), + CameraShip::AttributePointers, + Mover::AttributeIndex + ); + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraShip::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraShip, Direction) +}; + +CameraShip::MessageHandlerSet + CameraShip::MessageHandlers( + ELEMENTS(CameraShip::MessageHandlerEntries), + CameraShip::MessageHandlerEntries, + Entity::MessageHandlers + + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DirectionMessageHandler(DirectionMessage *message) +{ + Check(this); + Check(message); + + Check(application); + HostManager *host = application->GetHostManager(); + Check(host); + SetGoalEntity(host->GetEntityPointer(message->goalEntity)); + Check(goalEntity); + mapLinearPosition = &goalEntity->localOrigin.linearPosition; + focusOffset = message->focusOffset; + SetSimulationState(DefaultState); + timeOnCamera = message->timeOnCamera; + lastSwitch = Now(); + lastSwitch -= timeOnCamera; + Check_Fpu(); +} + +//############################################################################# +// ControlsMapper Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::SetMappingSubsystem(CameraControlsMapper *mapper) +{ + Check(this); + Check(mapper); + if(subsystemArray[ControlsMapperSubsystem]) + { + Unregister_Object(subsystemArray[ControlsMapperSubsystem]); + delete subsystemArray[ControlsMapperSubsystem]; + } + subsystemArray[ControlsMapperSubsystem] = mapper; + Check_Fpu(); +} + +//############################################################################# +// Simulation Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DriveCamera(Scalar time_slice) +{ + Check(this); + CameraControlsMapper* controls = + Cast_Object( + CameraControlsMapper*, + GetSubsystem(CameraShip::ControlsMapperSubsystem) + ); + Check(controls); + + // + //----------------------------------------------- + // If we are in positioning mode, move the camera + //----------------------------------------------- + // + if (controls->driveCamera > 0) + { + ApplyControlledPanAndTilt(controls, time_slice); + ApplyControlledCameraMotion(controls, time_slice); + ApplyControlledCameraHeight(controls); + currentCamera->SetLocalOrigin(localOrigin); + } + + // + //------------------------------------------------------------------------ + // Operate in camera mode, obeying the limits of the camera as established + // by the clamps + //------------------------------------------------------------------------ + // + else + { + // + //------------------------- + // Stop any existing motion + //------------------------- + // + worldLinearVelocity = Vector3D::Identity; + + // + //----------------------------------------------------------------------- + // Read the controls for panning the camera, and if the clamp override is + // on, tell the camera to allow this orientation + //----------------------------------------------------------------------- + // + ApplyControlledPanAndTilt(controls, time_slice); + localToWorld = localOrigin; + + // + //--------------------------------------------------------------------- + // Establish an aim point along negative Z and figure out where that is + // in world space, then point the camera there. The camera clamps will + // automatically do their thing + //--------------------------------------------------------------------- + // + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + if (controls->slideOrClamp > 0) + { + currentCamera->AllowLookingAt(world_aim); + } + AimCameraAtPoint(world_aim); + } + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::ApplyControlledPanAndTilt( + CameraControlsMapper *controls, + Scalar time_slice + ) +{ + Check(this); + Check(controls); + + // + //----------------------------------------- + // Point the Camera in the direction of the + // Joystick Position Calc Pitch and Yaw only + //----------------------------------------- + // + Scalar rotation_amount; + if(controls->stickPosition.x < -0.02f) + { + + rotation_amount = controls->stickPosition.x + 0.02f; + rotation_amount *= rotation_amount; + rotation_amount *= -1.0f; + } + else if (controls->stickPosition.x > 0.02f) + { + rotation_amount = controls->stickPosition.x - 0.02f; + rotation_amount *= rotation_amount; + } + else + { + rotation_amount = 0.0f; + } + YawPitchRoll ypr; + ypr = localOrigin.angularPosition; + + ypr.yaw += rotation_amount * PI * time_slice; + ypr.pitch += controls->stickPosition.y * PI * 0.2f * time_slice; + + localOrigin.angularPosition = ypr; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::ApplyControlledCameraHeight(CameraControlsMapper *controls) +{ + Check(this); + Check(controls); + + // + //---------------------------------------------------- + // Raise and lower the cameraShip according to the pedals + //---------------------------------------------------- + // + localOrigin.linearPosition.y += controls->pedalsPosition; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::ApplyControlledCameraMotion( + CameraControlsMapper *controls, + Scalar time_slice + ) +{ + Check(this); + Check(controls); + + localAcceleration.linearMotion.z = + -25.0f * controls->throttlePosition * time_slice; + if (controls->reverseThrust > 0) + { + localAcceleration.linearMotion.z = -localAcceleration.linearMotion.z; + } + + // + //~~~~~~~~~~~~~~~~~~~ + // Apply Linear Drag + //~~~~~~~~~~~~~~~~~~~ + // + Vector3D drag_force; + + drag_force.Multiply( + localVelocity.linearMotion, + positiveLinearDragCoefficients + ); + + Vector3D new_accel; + new_accel.Subtract( + localAcceleration.linearMotion, + drag_force + ); + + localAcceleration.linearMotion = new_accel; + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // ApplyWorldAccelerations + //~~~~~~~~~~~~~~~~~~~~~~~~ + localVelocity.linearMotion += localAcceleration.linearMotion; + + worldLinearVelocity.Multiply( + localVelocity.linearMotion, + localToWorld + ); + localOrigin.linearPosition += worldLinearVelocity; + + Check_Fpu(); +} + +//############################################################################# +// Follow GoalEntity Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::FollowGoal(Scalar time_slice) +{ + Check(this); + + // + //----------------------------------------------- + // If no goalEntity assigned ask for one and wait + //----------------------------------------------- + // + if (!goalEntity) + { + return; + } + Check(goalEntity); + Point3D target; + target.Multiply(focusOffset, goalEntity->localToWorld); + + // + //------------------------------------------------------------------------ + // If time has not yet expired on this camera, keep with it if can see the + // goal entity + //------------------------------------------------------------------------ + // + Check(currentCamera); + if ( + lastPerformance - lastSwitch > timeOnCamera + || !currentCamera->CanCameraSee(target) + ) + { + CameraInstance *old_camera = currentCamera; + GoToClosestCamera(target); + if (!currentCamera) + { + currentCamera = old_camera; + } + Check(currentCamera); + + // + //------------------------------------------------------------------------ + // If we need to switch cameras, have the new camera point directly at the + // target + //------------------------------------------------------------------------ + // + if (currentCamera != old_camera) + { + AimCameraAtPoint(target); + lastSwitch = lastPerformance; + } + else + { + goto Rotate_Camera; + } + } + + // + //--------------------------------------------------- + // Otherwise, rotate the camera as needed and allowed + //--------------------------------------------------- + // + else + { +Rotate_Camera: + RotateCameraToPoint(time_slice, target); + } + + // + //------------------------ + // Set the tranform matrix + //------------------------ + // + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::GoToClosestCamera(const Point3D &point_3D) +{ + Check(this); + currentCamera = cameraManager.FindClosestCamera(point_3D); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::AimCameraAtPoint(const Point3D &point_3D) +{ + Check(this); + Check(currentCamera); + currentCamera->LookAt(&localOrigin, point_3D); + localVelocity.angularMotion = Vector3D::Identity; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::RotateCameraToPoint( + Scalar time_slice, + const Point3D &point_3D + ) +{ + Check(this); + Check(currentCamera); + Check(&point_3D); + + // + //--------------------------------------------------------- + // Calculate the rotation needed to point to the goalEntity + //--------------------------------------------------------- + // + Origin target; + currentCamera->LookAt(&target, point_3D); + YawPitchRoll new_yaw_pitch_roll; + new_yaw_pitch_roll = target.angularPosition; + + Vector3D new_pos(new_yaw_pitch_roll.pitch, new_yaw_pitch_roll.yaw, 0.0f); + YawPitchRoll old_pos_euler; + old_pos_euler = localOrigin.angularPosition; + + Vector3D old_pos(old_pos_euler.pitch, old_pos_euler.yaw, 0.0f); + old_pos.x = Radian::Normalize(old_pos.x); + old_pos.y = Radian::Normalize(old_pos.y); + + // + // new - old position + // + if (new_pos.x-old_pos.x > PI) { + new_pos.x -= TWO_PI; + } + else if (new_pos.x-old_pos.x < -PI) { + new_pos.x += TWO_PI; + } + if (new_pos.y-old_pos.y > PI) { + new_pos.y -= TWO_PI; + } + else if (new_pos.y-old_pos.y < -PI) { + new_pos.y += TWO_PI; + } + Vector3D delta_rot; + delta_rot.Subtract( + new_pos, + old_pos + ); + + // + //------------------- + // Apply Angular Drag + //------------------- + // + Vector3D + drag; + + drag.Multiply( + localVelocity.angularMotion, + angularDragCoefficients + ); + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Apply SpringConstant + //~~~~~~~~~~~~~~~~~~~~~ + // + Vector3D + delta_rot_spring; + delta_rot_spring.Multiply( + delta_rot, + elasticityCoefficient + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Calculate the new angular acceleration + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + localAcceleration.angularMotion.Subtract( + delta_rot_spring, + drag + ); + + Scalar halft_squared = 0.5 *(time_slice * time_slice); + + Vector3D + accel_comp; + accel_comp.Multiply( + localAcceleration.angularMotion, + halft_squared + ); + + // + // velocity * delta time + // + Vector3D + scaled_velocity; + scaled_velocity.Multiply( + localVelocity.angularMotion, + time_slice + ); + + Vector3D + tmp_position; + tmp_position.Add( + scaled_velocity, + accel_comp + ); + Vector3D + clamped_accel; + clamped_accel.Add( + old_pos, + tmp_position + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Apply Acceleration to angular Position + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + YawPitchRoll + new_yawpitchroll(clamped_accel.y, clamped_accel.x, clamped_accel.z); + + LinearMatrix + rot_matrix(LinearMatrix::Identity); + rot_matrix = new_yawpitchroll; + localOrigin.angularPosition = rot_matrix; + + // + // Calc new Velocity + // + Vector3D + scaled_accel; + scaled_accel.Multiply( + localAcceleration.angularMotion, + time_slice + ); + Vector3D + ang_vel; + ang_vel.Add( + localVelocity.angularMotion, + scaled_accel + ); + localVelocity.angularMotion = ang_vel; + + Check_Fpu(); +} + +//############################################################################# +// CameraInstanceManager Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::CreateCameraInstance() +{ + Check(this); + Check(&cameraManager); + currentCamera = cameraManager.CreateCameraInstance(localOrigin); + DEBUG_STREAM << currentCamera->GetCameraName() << endl; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DeleteCameraInstance() +{ + Check(this); + + // + //--------------------------------------------- + // If this is the last camera, don't delete it! + //--------------------------------------------- + // + Check(&cameraManager); + CameraInstance *next_camera = cameraManager.IncrementIterator(); + if (next_camera == currentCamera) + { + return; + } + + currentCamera = cameraManager.DeleteCameraInstance(); + Check(currentCamera); + DEBUG_STREAM << currentCamera->GetCameraName() << endl; + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::IncrementCameraInstance() +{ + Check(this); + Check(&cameraManager); + currentCamera = cameraManager.IncrementIterator(); + Check(currentCamera); + DEBUG_STREAM << currentCamera->GetCameraName() << endl; + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DecrementCameraInstance() +{ + Check(this); + Check(&cameraManager); + currentCamera = cameraManager.DecrementIterator(); + Check(currentCamera); + DEBUG_STREAM << currentCamera->GetCameraName() << endl; + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + Check_Fpu(); +} + +//############################################################################# +// Motion Support Functions +// + +//############################################################################# +// Construction and Destruction Support +// +CameraShip::CameraShip( + CameraShip::MakeMessage *creation_message, + CameraShip::SharedData &virtual_data +): + Mover(creation_message, virtual_data) +{ + SetValidFlag(); + if (GetInstance() == ReplicantInstance) + { + return; + } + // + //---------------------------- + // Initialize local variables + //---------------------------- + // + goalEntity = NULL; + localOrigin = Origin::Identity; + focusOffset = Vector3D::Identity; + + // + //------------------------------ + // Initialize attributes + //------------------------------ + // + mapRange = 1000.0; // number of meters across display + mapLinearPosition = NULL; // force nav display to use object's lin. pos + mapAngularPosition = NULL; // force nav display to not turn or tilt + // + //------------------------------ + // Initialize the subsystemArray + //------------------------------ + // + subsystemCount = BasicSubsystemCount; + Verify(!subsystemArray); + subsystemArray = new (Subsystem (*[subsystemCount])); + Register_Pointer(subsystemArray); + subsystemArray[ControlsMapperSubsystem] = NULL; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the camera's viewpoint to the first camera + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + currentCamera = cameraManager.GetCurrent(); + if (!currentCamera) + { + CreateCameraInstance(); + } + Check(currentCamera); + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + lastSwitch = Now(); + timeOnCamera = 0.0f; + + SetPerformance(&CameraShip::FollowGoal); + SetSimulationState(DefaultState); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraShip* + CameraShip::Make(MakeMessage *creation_message) +{ + return new CameraShip(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraShip::~CameraShip() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraShip::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/CAMSHIP.HPP b/CODE/RP/MUNGA/CAMSHIP.HPP new file mode 100644 index 0000000..ddeabef --- /dev/null +++ b/CODE/RP/MUNGA/CAMSHIP.HPP @@ -0,0 +1,284 @@ +//===========================================================================// +// File: camship.hh // +// Project: Munga // +// Contents: Camera Interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/08/95 JM Initial coding. // +// Classes: CameraShip // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(CAMSHIP_HPP) +# define CAMSHIP_HPP + +# if !defined (MOVER_HPP) +# include +# endif + +# if !defined (CAMMGR_HPP) +# include +# endif + + class CameraControlsMapper; + + //########################################################################## + //############### CameraShip::DirectionMessage ################# + //########################################################################## + + class CameraShip__DirectionMessage : + public Mover::Message + { + public: + EntityID + goalEntity; + Scalar + timeOnCamera; + Point3D + focusOffset; + + CameraShip__DirectionMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID& goal_entity, + Scalar time_on_camera, + const Point3D& focus + ): + Entity::Message(message_ID, length), + goalEntity(goal_entity), + timeOnCamera(time_on_camera), + focusOffset(focus) + {} + }; + + //########################################################################## + //############################# CameraShip ################################ + //########################################################################## + + class CameraShip : + public Mover + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messaging support + // + protected: + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + public: + enum{ + DirectionMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef CameraShip__DirectionMessage DirectionMessage; + + void + DirectionMessageHandler(DirectionMessage *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum + { + MapRangeAttributeID = Mover::NextAttributeID, + MapLinearPositionAttributeID, + MapAngularPositionAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + public: + Scalar + mapRange; + Point3D + *mapLinearPosition; // pointer to linear position of object or NULL + Quaternion + *mapAngularPosition; // pointer to angular position of object or NULL + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model support + // + public: + enum { + ControlsMapperSubsystem, + BasicSubsystemCount + }; + void + SetMappingSubsystem(CameraControlsMapper *mapper); + + // + // Various States of the CameraShip + // + enum { + ConfigureCamerasState = Mover::StateCount, + StateCount + }; + + typedef void + (CameraShip::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + FollowGoal(Scalar time_slice); + + void + DriveCamera(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Flag Support + // + public: + + enum{ + DefaultFlags = Mover::DefaultFlags | + NoCollisionVolumeFlag | + NoCollisionTestFlag | + InitialStasisFlag + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + + static CameraShip* + Make(MakeMessage *creation_message); + + CameraShip( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~CameraShip(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public Data and Member Access Functions + // + public: + + void + SetGoalEntity(Entity *goal_entity) + {Check(this); Check(goal_entity); goalEntity = goal_entity;} + + Entity* + GetGoalEntity() + {Check(this); return goalEntity; } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local Member Data + // + public: + void + GoToClosestCamera(const Point3D &point_3D); + CameraInstance* + GetCurrentCamera() + {Check(this); return currentCamera;} + + Time + lastSwitch; + Scalar + timeOnCamera; + + protected: + CameraInstanceManager + cameraManager; + Entity + *goalEntity; + CameraInstance + *currentCamera; + Point3D + focusOffset; + + void + MoveCameraShip(CameraInstance *camera_instance); + + void + AimCameraAtPoint(const Point3D &point_3D); + + void + RotateCameraToPoint( + Scalar time_slice, + const Point3D &point_3D + ); + + // + // Camera Motion Support + // + public: + void + ResetMotionVariables() + { + Check(this); + localVelocity = Motion::Identity; + localAcceleration = Motion::Identity; + worldLinearVelocity = Vector3D::Identity; + worldLinearAcceleration = Vector3D::Identity; + } + + protected: + void + ApplyControlledPanAndTilt( + CameraControlsMapper *controls, + Scalar time_slice + ); + void + ApplyControlledCameraHeight(CameraControlsMapper *controls); + + void + ApplyControlledCameraMotion( + CameraControlsMapper *controls, + Scalar time_slice + ); + + // + // Camera Manager Support + // + public: + void + CreateCameraInstance(); + + void + DeleteCameraInstance(); + + void + IncrementCameraInstance(); + + void + DecrementCameraInstance(); + + public: + void + OutputCameraList() + {cameraManager.WriteNotationFile();} + }; + +#endif + diff --git a/CODE/RP/MUNGA/CHAIN.CPP b/CODE/RP/MUNGA/CHAIN.CPP new file mode 100644 index 0000000..d850c44 --- /dev/null +++ b/CODE/RP/MUNGA/CHAIN.CPP @@ -0,0 +1,474 @@ +//===========================================================================// +// File: chain.cc // +// Project: MUNGA Brick: Connection Engine // +// Contents: Implementation details of chains and their iterators // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. Merged with CHNITR.HPP, and added // +// operator functions to iterator // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(CHAIN_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +MemoryBlock + ChainLink::AllocatedMemory( + sizeof(ChainLink), + CHAINLINK_MEMORYBLOCK_ALLOCATION, + CHAINLINK_MEMORYBLOCK_ALLOCATION, + "ChainLink" + ); + +// +//############################################################################# +// ChainLink +//############################################################################# +// +ChainLink::ChainLink( + Chain *chain, + Plug *plug, + ChainLink *next_link, + ChainLink *prev_link +): + Link(chain, plug) +{ + // + //------------------------- + // Link into existing chain + //------------------------- + // + if ((nextChainLink = next_link) != NULL) + { + Check(nextChainLink); + nextChainLink->prevChainLink = this; + } + if ((prevChainLink = prev_link) != NULL) + { + Check(prevChainLink); + prevChainLink->nextChainLink = this; + } +} + +// +//############################################################################# +// ~ChainLink +//############################################################################# +// +ChainLink::~ChainLink() +{ + Chain *chain = Cast_Object(Chain*, socket); + + // + //-------------------------------------- + // Remove this link from the linked list + //-------------------------------------- + // + if (prevChainLink != NULL) + { + Check(prevChainLink); + prevChainLink->nextChainLink = nextChainLink; + } + else + { + Check(chain); + chain->head = nextChainLink; + } + if (nextChainLink != NULL) + { + Check(nextChainLink); + nextChainLink->prevChainLink = prevChainLink; + } + else + { + Check(chain); + chain->tail = prevChainLink; + } + prevChainLink = nextChainLink = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (chain->GetReleaseNode() != NULL) + { + Check(chain->GetReleaseNode()); + chain->GetReleaseNode()->ReleaseLinkHandler(chain, plug); + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + ChainLink::TestInstance() const +{ + Link::TestInstance(); + + if (prevChainLink != NULL) + { + Check_Signature(prevChainLink); + } + if (nextChainLink != NULL) + { + Check_Signature(nextChainLink); + } + return( True ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Chain +//############################################################################# +// +Chain::Chain(Node *node): + Socket(node) +{ + head = NULL; + tail = NULL; +} + +// +//############################################################################# +// ~Chain +//############################################################################# +// +Chain::~Chain() +{ + SetReleaseNode(NULL); + while (head != NULL) + { + Unregister_Object(head); + delete head; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Chain::TestInstance() const +{ + Socket::TestInstance(); + + if (head != NULL) + { + Check(head); + } + if (tail != NULL) + { + Check(tail); + } + return True; +} + +// +//############################################################################# +// AddImplementation +//############################################################################# +// +void + Chain::AddImplementation(Plug *plug) +{ + Check(this); + + tail = new ChainLink(this, plug, NULL, tail); + Register_Object(tail); + + if (head == NULL) + { + head = tail; + } +} + +// +//############################################################################# +// InsertChainLink +//############################################################################# +// +ChainLink* + Chain::InsertChainLink( + Plug *plug, + ChainLink *current_link + ) +{ + Check(this); + Check(plug); + Check(current_link); + + ChainLink *new_link = + new ChainLink( + this, + plug, + current_link, + current_link->prevChainLink + ); + Register_Object(new_link); + + Check(head); + if (head == current_link) + { + head = new_link; + } + return new_link; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// ChainIterator +//############################################################################# +// +ChainIterator::ChainIterator(Chain *chain): + SocketIterator(chain) +{ + Check(chain); + currentLink = chain->head; +} + +ChainIterator::ChainIterator(const ChainIterator &iterator): + SocketIterator(Cast_Object(Chain*, iterator.socket)) +{ + Check(&iterator); + currentLink = iterator.currentLink; +} + +ChainIterator::~ChainIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + ChainIterator::TestInstance() const +{ + SocketIterator::TestInstance(); + + if (currentLink != NULL) + { + Check( currentLink ); + } + return(True); +} + +// +//########################################################################### +// First +//########################################################################### +// +void + ChainIterator::First() +{ + currentLink = Cast_Object(Chain*, socket)->head; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + ChainIterator::Last() +{ + currentLink = Cast_Object(Chain*, socket)->tail; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + ChainIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->nextChainLink; +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + ChainIterator::Previous() +{ + Check( currentLink ); + currentLink = currentLink->prevChainLink; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void* + ChainIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->nextChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void* + ChainIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->prevChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + ChainIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + return currentLink->plug; + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + ChainIterator::GetSize() +{ + + ChainLink *link; + CollectionSize count; + + count = 0; + + for ( + link = Cast_Object(Chain*, socket)->head; + link != NULL; + link = link->nextChainLink + ) { + Check(link); + count++; + } + return count; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void* + ChainIterator::GetNthImplementation(CollectionSize index) +{ + ChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(Chain*, socket)->head; + link != NULL; + link = link->nextChainLink + ) { + Check(link); + if (count == index) { + currentLink = link; + return currentLink->plug; + } + count++; + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + ChainIterator::Remove() +{ + ChainLink *oldLink = currentLink; + + Check(currentLink); + currentLink = currentLink->nextChainLink; + + Unregister_Object(oldLink); + delete oldLink ; +} + +// +//########################################################################### +// InsertImplementation +//########################################################################### +// +void + ChainIterator::InsertImplementation(Plug *plug) +{ + currentLink = + Cast_Object(Chain*, socket)->InsertChainLink(plug, currentLink); + Check(currentLink); +} + +#ifdef TEST_CLASS +# include "chain.tcp" +#endif diff --git a/CODE/RP/MUNGA/CHAIN.HPP b/CODE/RP/MUNGA/CHAIN.HPP new file mode 100644 index 0000000..cb548bf --- /dev/null +++ b/CODE/RP/MUNGA/CHAIN.HPP @@ -0,0 +1,367 @@ +//===========================================================================// +// File: chain.hh // +// Project: MUNGA Brick: Connection Engine // +// Contents: Interface specification of Chains and their iterators // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. Merged with CHNITR.HPP, and added // +// operator functions to iterator // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(CHAIN_HPP) +# define CHAIN_HPP + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + + class Chain; + class ChainIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define CHAINLINK_MEMORYBLOCK_ALLOCATION (100) + + class ChainLink : public Link + { + friend class Chain; + friend class ChainIterator; + + public: + ~ChainLink(); + Logical + TestInstance() const; + + private: + ChainLink( + Chain *chain, + Plug *plug, + ChainLink *nextChainLink, + ChainLink *prevChainLink + ); + + ChainLink + *nextChainLink, + *prevChainLink; + + private: + static MemoryBlock + AllocatedMemory; + + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Chain: + public Socket + { + friend class ChainLink; + friend class ChainIterator; + + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructor and testing + //-------------------------------------------------------------------- + // + Chain(Node *node); + ~Chain(); + + Logical + TestInstance() const; + static Logical + TestClass(); + static Logical + ProfileClass(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + AddImplementation(Plug *plug); + + private: + // + //-------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------- + // + ChainLink* + InsertChainLink( + Plug *plug, + ChainLink *current_link + ); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + ChainLink + *head, + *tail; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class ChainOf: + public Chain + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + ChainOf(Node *node); + ~ChainOf(); + + // + //-------------------------------------------------------------------- + // Socket methods (see Socket for full listing) + //-------------------------------------------------------------------- + // + void + Add(T plug) + {AddImplementation(Cast_Object(Plug*,plug));} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + ChainOf::ChainOf(Node *node): + Chain(node) + { + } + + template + ChainOf::~ChainOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class ChainIterator: + public SocketIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors, Destructor and testing + //-------------------------------------------------------------------- + // + ChainIterator(Chain *chain); + ChainIterator(const ChainIterator &iterator); + ~ChainIterator(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + void + First(); + void + Last(); + void + Next(); + void + Previous(); + CollectionSize + GetSize(); + void + Remove(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void* + ReadAndNextImplementation(); + void* + ReadAndPreviousImplementation(); + void* + GetCurrentImplementation(); + void* + GetNthImplementation(CollectionSize index); + void + InsertImplementation(Plug*); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + ChainLink + *currentLink; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class ChainIteratorOf: + public ChainIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors and Destructor + //-------------------------------------------------------------------- + // + ChainIteratorOf(ChainOf *chain); + ChainIteratorOf(ChainOf &chain); + ChainIteratorOf(const ChainIteratorOf &iterator); + ~ChainIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T + ReadAndNext() + {return (T)ReadAndNextImplementation();} + T + ReadAndPrevious() + {return (T)ReadAndPreviousImplementation();} + T + GetCurrent() + {return (T)GetCurrentImplementation();} + T + GetNth(CollectionSize index) + {return (T)GetNthImplementation(index);} + void + Insert(T plug) + {InsertImplementation(Cast_Object(Plug*,plug));} + + ChainIteratorOf& + Begin() + {return (ChainIteratorOf&)BeginImplementation();} + ChainIteratorOf& + End() + {return (ChainIteratorOf&)EndImplementation();} + ChainIteratorOf& + Forward() + {return (ChainIteratorOf&)ForwardImplementation();} + ChainIteratorOf& + Backward() + {return (ChainIteratorOf&)BackwardImplementation();} + + // + //--------------------------------------------------- + // Operators useful when it is know that the iterator + // is a ChainOf<> Iterator + //--------------------------------------------------- + // +#if 0 + Logical + operator!() + {return currentLink == NULL;} + operator T*() + {return GetCurrent();} + T* + operator->() + {return GetCurrent();} + T& + operator*() + {return *GetCurrent();} + + ChainIteratorOf& + operator++() + {Next(); return *this;} + ChainIteratorOf& + operator--() + {Previous(); return *this;} + T* + operator++(int) + {return ReadAndNext();} + T* + operator--(int) + {return ReadAndPrevious();} +#endif + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + ChainIteratorOf::ChainIteratorOf(ChainOf *chain): + ChainIterator(chain) + { + } + + template + ChainIteratorOf::ChainIteratorOf(ChainOf &chain): + ChainIterator(&chain) + { + } + + template + ChainIteratorOf::ChainIteratorOf(const ChainIteratorOf &iterator): + ChainIterator(iterator) + { + } + + template + ChainIteratorOf::~ChainIteratorOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/CMPNNT.CPP b/CODE/RP/MUNGA/CMPNNT.CPP new file mode 100644 index 0000000..ca16c4b --- /dev/null +++ b/CODE/RP/MUNGA/CMPNNT.CPP @@ -0,0 +1,90 @@ +//===========================================================================// +// File: cmpnnt.cc // +// Project: MUNGA Brick: Entity // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(CMPNNT_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +// Shared Data Support +// +Derivation + Component::ClassDerivations( + Receiver::ClassDerivations, + "Component" + ); + +Component::SharedData + Component::DefaultData( + Component::ClassDerivations, + Component::MessageHandlers + ); + +// +//############################################################################# +//############################################################################# +// +Component::Component( + ClassID class_id, + SharedData &shared_data +): + Receiver(class_id, shared_data) +{ +} + +// +//############################################################################# +//############################################################################# +// +Component::Component( + PlugStream *stream, + SharedData &shared_data +): + Receiver(stream, shared_data) +{ +} + +// +//############################################################################# +//############################################################################# +// +Component::~Component() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + Component::Execute() +{ + Fail("Component::Execute - Should never reach here"); +} + +// +//############################################################################# +//############################################################################# +// +Logical + Component::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/CMPNNT.HPP b/CODE/RP/MUNGA/CMPNNT.HPP new file mode 100644 index 0000000..b0d0c90 --- /dev/null +++ b/CODE/RP/MUNGA/CMPNNT.HPP @@ -0,0 +1,73 @@ +//===========================================================================// +// File: cmpnnt.hh // +// Project: MUNGA Brick: Watcher // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(CMPNNT_HPP) +# define CMPNNT_HPP + +# if !defined(RECEIVER_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Component: + public Receiver + { + public: + // + //----------------------------------------------------------------------- + // Destructor + //----------------------------------------------------------------------- + // + ~Component(); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + virtual void + Execute(); + + // + //----------------------------------------------------------------------- + // Shared Data Support + //----------------------------------------------------------------------- + // + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + Logical + TestInstance() const; + + protected: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + Component( + ClassID class_id = TrivialComponentClassID, + SharedData &shared_data = DefaultData + ); + Component( + PlugStream *stream, + SharedData &shared_data = DefaultData + ); + }; + +#endif + diff --git a/CODE/RP/MUNGA/COLLASST.CPP b/CODE/RP/MUNGA/COLLASST.CPP new file mode 100644 index 0000000..8bad5cb --- /dev/null +++ b/CODE/RP/MUNGA/COLLASST.CPP @@ -0,0 +1,392 @@ +//===========================================================================// +// File: collasst.cc // +// Project: MUNGA Brick: Collision // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/17/95 ECH Initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(COLLASST_HPP) +# include +#endif + +#if !defined(MOVER_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(INTEREST_HPP) + #include +#endif + +// +//############################################################################# +// Make +//############################################################################# +// +CollisionAssistant* + CollisionAssistant::Make(Mover *mover) +{ + Check(mover); + + // + // Create the collision assistant + // + CollisionAssistant *collision_assistant; + + collision_assistant = new CollisionAssistant(mover->GetInterestZoneID()); + Check(collision_assistant); + return collision_assistant; +} + +// +//############################################################################# +// CollisionAssistant +//############################################################################# +// +CollisionAssistant::CollisionAssistant(InterestZoneID interest_zone_ID): + collisionOriginSocket(NULL) +{ + Verify(interest_zone_ID != NullInterestZoneID); + currentInterestZoneID = interest_zone_ID; + LinkToInterestZone(interest_zone_ID); +} + +// +//############################################################################# +// ~CollisionAssistant +//############################################################################# +// +CollisionAssistant::~CollisionAssistant() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + CollisionAssistant::TestInstance() const +{ + Node::TestInstance(); + Verify(currentInterestZoneID != NullInterestZoneID); + Check(&collisionOriginSocket); + return True; +} + +// +//############################################################################# +// Update +//############################################################################# +// +void + CollisionAssistant::Update(InterestZoneID interest_zone_ID) +{ + Check(this); + Verify(interest_zone_ID != NullInterestZoneID); + + if (interest_zone_ID == currentInterestZoneID) + return; + currentInterestZoneID = interest_zone_ID; + + // + // Remove current collision origin and link to new one + // + if (collisionOriginSocket.GetCurrent() != NULL) + { + collisionOriginSocket.Remove(); + } + LinkToInterestZone(interest_zone_ID); +} + +// +//############################################################################# +// LinkToInterestZone +//############################################################################# +// +void + CollisionAssistant::LinkToInterestZone(InterestZoneID interest_zone_ID) +{ + Check(this); + Verify(interest_zone_ID != NullInterestZoneID); + + // + //-------------------------------------------------------------------------- + // Does the interest zone have a collision origin? + //-------------------------------------------------------------------------- + // + InterestZone *interest_zone; + CollisionOrigin *collision_origin; + + Check(application); + Check(application->GetInterestManager()); + interest_zone = + application->GetInterestManager()->GetInterestZone(interest_zone_ID); + Check(interest_zone); + + collision_origin = interest_zone->GetCollisionOrigin(); + if (collision_origin == NULL) + { + // + // It does not, so create one + // + collision_origin = new CollisionOrigin(interest_zone_ID); + Register_Object(collision_origin); + interest_zone->AdoptCollisionOrigin(collision_origin); + + application->GetInterestManager()->AdoptInterestOrigin(collision_origin); + } + Check(collision_origin); + + // + // link to the collision origin + // + collisionOriginSocket.Add(collision_origin); +} + +//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~ + +CollisionAssistant__MovingEntityIterator:: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ): + CollisionOrigin__MovingEntityIterator( + collision_assistant->collisionOriginSocket.GetCurrent() + ) +{ +} + +CollisionAssistant__MovingEntityIterator:: + ~CollisionAssistant__MovingEntityIterator() +{ +} + +#if 0 +// +//############################################################################# +// Make +//############################################################################# +// +CollisionAssistant* + CollisionAssistant::Make(Mover *mover) +{ + Check(mover); + + // + //----------------------------------------------------------------------- + // Create the collision assistant + //----------------------------------------------------------------------- + // + CollisionAssistant *collision_assistant; + + Check(application); + collision_assistant = new CollisionAssistant( + application->GetApplicationLoopFrameRate() + ); + Check(collision_assistant); + + // + //----------------------------------------------------------------------- + // Prime the collision assistant + //----------------------------------------------------------------------- + // + collision_assistant->LinkToMover(mover); + collision_assistant->LoadMission(NULL); // JM - This should work... + + return collision_assistant; +} + +// +//############################################################################# +// CollisionAssistant +//############################################################################# +// +CollisionAssistant::CollisionAssistant(RendererRate render_rate): + Renderer( + render_rate, + MaxRendererComplexity, + DefaultRendererPriority, + CollisionInterestType, + DefaultInterestDepth, + CollisionAssistantClassID + ), + movingEntitySocket(NULL) +{ +} + +// +//############################################################################# +// ~CollisionAssistant +//############################################################################# +// +CollisionAssistant::~CollisionAssistant() +{ + Suspend(); + UnlinkFromEntity(); + Shutdown(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + CollisionAssistant::TestInstance() const +{ + Renderer::TestInstance(); + Check(&movingEntitySocket); + return True; +} + +// +//############################################################################# +// LinkToEntity +//############################################################################# +// +void + CollisionAssistant::LinkToMover(Mover *mover) +{ + Check(this); + Check(mover); + + // + // Call inherited method + // + Renderer::LinkToEntity(mover); + + // + //----------------------------------------------------------------- + // Tell the entity that is collisionable here ... + //----------------------------------------------------------------- + // +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + CollisionAssistant::NotifyOfNewInterestingEntity( + Entity *interesting_entity + ) +{ + Check(this); + Check(interesting_entity); + + // + //------------------------------------------------------------------------- + // Make sure that we don't check against ourself our against something that + // doesn't move + //------------------------------------------------------------------------- + // + if ( + interesting_entity != GetLinkedEntity() + && interesting_entity->IsDynamic() + ) + { + + // + //------------------------------------------------------------- + // If it is a mover and tangible, or a door, add it to our list + //------------------------------------------------------------- + // + if (interesting_entity->IsDerivedFrom(Mover::ClassDerivations)) + { + Mover *mover = Cast_Object(Mover*, interesting_entity); + if (mover->IsTangible()) + { + goto Add_Entity; + } + } + else if (interesting_entity->IsDerivedFrom(DoorFrame::ClassDerivations)) + { +Add_Entity: + movingEntitySocket.Add(interesting_entity); + } + } +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntity +//############################################################################# +// +void + CollisionAssistant::NotifyOfBecomingUninterestingEntity( + Entity *uninteresting_entity + ) +{ + // + // HACK - ECH The following may not be a legitimate assertion + // + #if DEBUG_LEVEL>0 && 0 + { + SChainIteratorOf iterator(&movingEntitySocket); + Verify(iterator.IsPlugMember(uninteresting_entity) == True); + } + #endif + + // + // Remove from socket + // + PlugIterator iterator(uninteresting_entity); + + iterator.RemoveSocket(&movingEntitySocket); +} + +// +//############################################################################# +// GetCollisionRoot +//############################################################################# +// +BoxedSolidTree* + CollisionAssistant::GetCollisionRoot() +{ + Check(GetInterestOrigin()); + Check(GetInterestOrigin()->GetInterestArena()); + return GetInterestOrigin()->GetInterestArena()->GetCollisionRoot(); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +void + CollisionAssistant::ExecuteImplementation( + RendererComplexity, + InterestOrigin::InterestingEntityIterator* + ) +{ +} + +//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +CollisionAssistant__MovingEntityIterator:: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ): + SChainIteratorOf(collision_assistant->movingEntitySocket) +{ +} + +CollisionAssistant__MovingEntityIterator:: + ~CollisionAssistant__MovingEntityIterator() +{ +} +#endif diff --git a/CODE/RP/MUNGA/COLLASST.HPP b/CODE/RP/MUNGA/COLLASST.HPP new file mode 100644 index 0000000..de72226 --- /dev/null +++ b/CODE/RP/MUNGA/COLLASST.HPP @@ -0,0 +1,206 @@ +//===========================================================================// +// File: collasst.hh // +// Project: MUNGA Brick: Collision // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/17/95 ECH Initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(COLLASST_HPP) +# define COLLASST_HPP + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(COLLORGN_HPP) +# include +# endif + + //########################################################################## + //####################### CollisionAssistant ######################### + //########################################################################## + + class Mover; + + class CollisionAssistant: + public Node + { + friend class CollisionAssistant__MovingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public Types + // + public: + typedef CollisionAssistant__MovingEntityIterator + MovingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + CollisionAssistant(InterestZoneID interest_zone_ID); + ~CollisionAssistant(); + + Logical + TestInstance() const; + + static CollisionAssistant* + Make(Mover *mover); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update + // + public: + void + Update(InterestZoneID interest_zone_ID); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private + // + private: + void + LinkToInterestZone(InterestZoneID interest_zone_ID); + + InterestZoneID + currentInterestZoneID; + SlotOf + collisionOriginSocket; + }; + + //~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~ + + class CollisionAssistant__MovingEntityIterator: + public CollisionOrigin__MovingEntityIterator + { + public: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ); + ~CollisionAssistant__MovingEntityIterator(); + }; + +#if 0 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CollisionAssistant ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class CollisionAssistant: + public Renderer + { + friend class CollisionAssistant__MovingEntityIterator; + + public: + // + //-------------------------------------------------------------------- + // Public Types + //-------------------------------------------------------------------- + // + typedef CollisionAssistant__MovingEntityIterator + MovingEntityIterator; + + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + CollisionAssistant(RendererRate render_rate); + ~CollisionAssistant(); + + Logical + TestInstance() const; + + static CollisionAssistant* + Make(Mover *mover); + + // + //-------------------------------------------------------------------- + // LinkToEntity + //-------------------------------------------------------------------- + // + void + LinkToMover(Mover *mover); + + // + //-------------------------------------------------------------------- + // NotifyOfNewInterestingEntity + //-------------------------------------------------------------------- + // + void + NotifyOfNewInterestingEntity(Entity *interesting_entity); + + // + //-------------------------------------------------------------------- + // NotifyOfBecomingUninterestingEntity + //-------------------------------------------------------------------- + // + void + NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity); + + // + //-------------------------------------------------------------------- + // GetCollisionRoot + //-------------------------------------------------------------------- + // + BoxedSolidTree* + GetCollisionRoot(); + + protected: + // + //-------------------------------------------------------------------- + // ExecuteImplementation + //-------------------------------------------------------------------- + // + void + ExecuteImplementation( + RendererComplexity complexity_update, + InterestOrigin::InterestingEntityIterator *iterator + ); + + private: + // + //-------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------- + // + void + LoadMissionImplementation(Mission*) {} + void + ShutdownImplementation() {} + void + SuspendImplementation() {} + void + ResumeImplementation() {} + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SChainOf + movingEntitySocket; + }; + + //~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class CollisionAssistant__MovingEntityIterator: + public SChainIteratorOf + { + public: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ); + ~CollisionAssistant__MovingEntityIterator(); + }; +#endif + +#endif + diff --git a/CODE/RP/MUNGA/COLLORGN.CPP b/CODE/RP/MUNGA/COLLORGN.CPP new file mode 100644 index 0000000..bd6f3ba --- /dev/null +++ b/CODE/RP/MUNGA/COLLORGN.CPP @@ -0,0 +1,167 @@ +//===========================================================================// +// File: collorgn.cc // +// Project: MUNGA Brick: Collision // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 06/01/95 ECH Initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(COLLORGN_HPP) +# include +#endif + +#if !defined(MOVER_HPP) +# include +#endif + +#if !defined(DOORFRAM_HPP) +# include +#endif + +// +//############################################################################# +// CollisionOrigin +//############################################################################# +// +CollisionOrigin::CollisionOrigin(InterestZoneID interest_zone_ID): + InterestOrigin( + interest_zone_ID, + CollisionInterestType, + DefaultInterestDepth + ), + movingEntitySocket(NULL) +{ +} + +// +//############################################################################# +// ~CollisionOrigin +//############################################################################# +// +CollisionOrigin::~CollisionOrigin() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + CollisionOrigin::TestInstance() const +{ + InterestOrigin::TestInstance(); + Check(&movingEntitySocket); + return True; +} + +// +//############################################################################# +// AddInterestingEntity +//############################################################################# +// +void + CollisionOrigin::AddInterestingEntity(Entity *interesting_entity) +{ + Check(this); + Check(interesting_entity); + + // + //-------------------------------------------------------------------------- + // Make sure that we don't check against something that doesn't move + //-------------------------------------------------------------------------- + // + if (interesting_entity->IsDynamic()) + { + // + //----------------------------------------------------------------------- + // If it is a mover and tangible, or a door, add it to our list + //----------------------------------------------------------------------- + // + if (interesting_entity->IsDerivedFrom(Mover::ClassDerivations)) + { + Mover *mover = Cast_Object(Mover*, interesting_entity); + if (mover->IsCollisionTestable()) + { + movingEntitySocket.Add(interesting_entity); + } + } + else if (interesting_entity->IsDerivedFrom(DoorFrame::ClassDerivations)) + { + movingEntitySocket.Add(interesting_entity); + } + } +} + +// +//############################################################################# +// RemoveUninterestingEntity +//############################################################################# +// +void + CollisionOrigin::RemoveUninterestingEntity(Entity *uninteresting_entity) +{ + Check(this); + Check(uninteresting_entity); + + // + // HACK - ECH The following may not be a legitimate assertion + // + #if DEBUG_LEVEL>0 && 0 + { + SChainIteratorOf iterator(&movingEntitySocket); + Verify(iterator.IsPlugMember(uninteresting_entity) == True); + } + #endif + + // + // Remove from socket + // + PlugIterator iterator(uninteresting_entity); + + Check(&iterator); + iterator.RemoveSocket(&movingEntitySocket); +} + +// +//############################################################################# +// RemoveUninterestingEntities +//############################################################################# +// +void + CollisionOrigin::RemoveUninterestingEntities() +{ + Check(this); + + SChainIteratorOf iterator(&movingEntitySocket); + + Check(&iterator); + while (iterator.GetCurrent() != NULL) + { + Check(iterator.GetCurrent()); + iterator.Remove(); + } +} + +//~~~~~~~~~~~~~~~~~~~ CollisionOrigin__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~ + +CollisionOrigin__MovingEntityIterator::CollisionOrigin__MovingEntityIterator( + CollisionOrigin *collision_origin +): + SChainIteratorOf(collision_origin->movingEntitySocket) +{ +} + +CollisionOrigin__MovingEntityIterator::~CollisionOrigin__MovingEntityIterator() +{ +} + diff --git a/CODE/RP/MUNGA/COLLORGN.HPP b/CODE/RP/MUNGA/COLLORGN.HPP new file mode 100644 index 0000000..806377c --- /dev/null +++ b/CODE/RP/MUNGA/COLLORGN.HPP @@ -0,0 +1,80 @@ +//===========================================================================// +// File: collorgn.hh // +// Project: MUNGA Brick: Collision // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 06/01/95 ECH Initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(COLLORGN_HPP) +# define COLLORGN_HPP + +# if !defined(INTEREST_HPP) +# include +# endif + + //########################################################################## + //###################### CollisionOrigin ############################# + //########################################################################## + + class CollisionOrigin: + public InterestOrigin + { + friend class CollisionOrigin__MovingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Manager support + // + public: + typedef CollisionOrigin__MovingEntityIterator + MovingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + CollisionOrigin(InterestZoneID interest_zone_ID); + ~CollisionOrigin(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Manager support + // + protected: + void + AddInterestingEntity(Entity *interesting_entity); + void + RemoveUninterestingEntity(Entity *uninteresting_entity); + void + RemoveUninterestingEntities(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + SChainOf + movingEntitySocket; + }; + + //~~~~~~~~~~~~~~~~~~~~ CollisionOrigin__MovingEntityIterator ~~~~~~~~~~~~~~~ + + class CollisionOrigin__MovingEntityIterator: + public SChainIteratorOf + { + public: + CollisionOrigin__MovingEntityIterator( + CollisionOrigin *collision_origin + ); + ~CollisionOrigin__MovingEntityIterator(); + }; + +#endif + diff --git a/CODE/RP/MUNGA/COLOR.CPP b/CODE/RP/MUNGA/COLOR.CPP new file mode 100644 index 0000000..f93c4d7 --- /dev/null +++ b/CODE/RP/MUNGA/COLOR.CPP @@ -0,0 +1,97 @@ +//===========================================================================// +// File: Color.cpp // +// Project: MUNGA Brick: Utility Library // +// Contents: Implementation details for color classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/12/95 GDU Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(COLOR_HPP) +# include +#endif + +#if !defined(CSTR_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +void + Convert_From_Ascii( + const char *str, + RGBColor *color + ) +{ + Check_Pointer(str); + Check_Signature(color); + + CString parse_string(str); + + Check_Pointer(parse_string.GetNthToken(0)); + color->Red = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + color->Green = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + color->Blue = atof(parse_string.GetNthToken(2)); + + Check(color); +} + +// +//########################################################################### +//########################################################################### +// +Logical + RGBColor::TestInstance() const +{ + return True; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +void + Convert_From_Ascii( + const char *str, + RGBAColor *color + ) +{ + Check_Pointer(str); + Check_Signature(color); + + CString parse_string(str); + + Check_Pointer(parse_string.GetNthToken(0)); + color->Red = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + color->Green = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + color->Blue = atof(parse_string.GetNthToken(2)); + + Check_Pointer(parse_string.GetNthToken(3)); + color->Alpha = atof(parse_string.GetNthToken(3)); + + Check(color); +} + diff --git a/CODE/RP/MUNGA/COLOR.HPP b/CODE/RP/MUNGA/COLOR.HPP new file mode 100644 index 0000000..754f969 --- /dev/null +++ b/CODE/RP/MUNGA/COLOR.HPP @@ -0,0 +1,194 @@ +//===========================================================================// +// File: color.hh // +// Title: Declaration of Color classes. // +// Project: Tool Architecture II // +// Author: Jerry Edsall & Ken Olsen (based on work by J.M. Albertson) // +// Purpose: Stores color information. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/15/94 KEO Added RGBAColor class. // +// 11/12/95 GDU Added MUNGA signatures and stream IO, moved to MUNGA // +//---------------------------------------------------------------------------// +// Copyright (c) 1994 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(COLOR_HPP) + #define COLOR_HPP + + #if !defined(MEMSTRM_HPP) + #include + #endif + + #if !defined(SCALAR_HPP) + #include + #endif + + //########################################################################## + //############## RGBColor ############################################ + //########################################################################## + + class RGBColor + { + friend class RGBAColor; + + public: + Scalar + Red, + Green, + Blue; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile RGBColor *p) + { + return False; + } + + #endif + + + RGBColor() + { + Red = Green = Blue = -1.0f; + } + + RGBColor( + Scalar r, + Scalar g, + Scalar b + ) + { + Red = r; + Green = g; + Blue = b; + } + + Logical + operator==(const RGBColor &a_RGBColor) const + { return !memcmp(this, &a_RGBColor, sizeof(RGBColor)); } + Logical + operator!=(const RGBColor &a_RGBColor) const + { return memcmp(this, &a_RGBColor, sizeof(RGBColor)); } + + Logical + TestInstance() const; + + RGBColor + operator+(const RGBColor &a_RGBColor) const + { + return RGBColor ( + min(this->Red + a_RGBColor.Red, 1.0), + min(this->Green + a_RGBColor.Green, 1.0), + min(this->Blue + a_RGBColor.Blue, 1.0)); + } + Scalar + Infrared() const + { return 0.3 * this->Red + 0.5 * this->Green + 0.2 * this->Blue; } + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const RGBColor& C + ); + + + private: + Scalar + min(Scalar x, Scalar y) const + { return x < y ? x : y; } + + + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + RGBColor *color + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + RGBColor *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const RGBColor *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + //########################################################################## + //############## RGBAColor ########################################### + //########################################################################## + + class RGBAColor: + public RGBColor + { + public: + Scalar + Alpha; + + RGBAColor(): + RGBColor() + { Alpha = -1.0f; } + + RGBAColor( + Scalar r, + Scalar g, + Scalar b, + Scalar a + ): + RGBColor(r, g, b) + { Alpha = a; } + + Logical + operator==(const RGBAColor &a_RGBAColor) const + { return !memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); } + Logical + operator!=(const RGBAColor &a_RGBAColor) const + { return memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); } + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const RGBAColor& c + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + RGBAColor *color + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + RGBAColor *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const RGBAColor *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + +#endif + +//============================================================================= diff --git a/CODE/RP/MUNGA/CONFIG.HPP b/CODE/RP/MUNGA/CONFIG.HPP new file mode 100644 index 0000000..032ac66 --- /dev/null +++ b/CODE/RP/MUNGA/CONFIG.HPP @@ -0,0 +1,158 @@ +#if !defined(CONFIG_HPP) +# define CONFIG_HPP + +# if DEBUG_LEVEL>=3 +# undef USE_ACTIVE_PROFILE // Disables trace activity +# define USE_TIME_ANALYSIS // Enables trace time statistics +# undef USE_TRACE_LOG // Disables logging functions +# define USE_FPU_ANALYSIS // Enables entity FPU checks +# define USE_MEMORY_ANALYSIS // Enables heap statistics +# undef USE_EVENT_STATISTICS // Disables event statistics +# elif DEBUG_LEVEL==2 +# undef USE_ACTIVE_PROFILE // Disables trace activity +# define USE_TIME_ANALYSIS // Enables trace time statistics +# undef USE_TRACE_LOG // Disables logging functions +# define USE_FPU_ANALYSIS // Enables entity FPU checks +# define USE_MEMORY_ANALYSIS // Enables heap statistics +# undef USE_EVENT_STATISTICS // Disables event statistics +# elif DEBUG_LEVEL==1 +# undef USE_ACTIVE_PROFILE // Disables trace activity +# define USE_TIME_ANALYSIS // Enables trace time statistics +# undef USE_TRACE_LOG // Disables logging functions +# define USE_FPU_ANALYSIS // Enables entity FPU checks +# define USE_MEMORY_ANALYSIS // Enables heap statistics +# undef USE_EVENT_STATISTICS // Disables event statistics +# elif DEBUG_LEVEL==0 +# if defined(LAB_ONLY) +# undef USE_ACTIVE_PROFILE // Disables trace activity +# define USE_TIME_ANALYSIS // Enables trace time statistics +# define USE_TRACE_LOG // Enables logging functions +# undef USE_FPU_ANALYSIS // Disables entity FPU checks +# undef USE_MEMORY_ANALYSIS // Disables heap statistics +# define USE_EVENT_STATISTICS // Enables event statistics +# else +# undef USE_ACTIVE_PROFILE // Disables trace activity +# undef USE_TIME_ANALYSIS // Disables trace time statistics +# undef USE_TRACE_LOG // Disables logging functions +# undef USE_FPU_ANALYSIS // Disables entity FPU checks +# undef USE_MEMORY_ANALYSIS // Disables heap statistics +# undef USE_EVENT_STATISTICS // Disables event statistics +# endif +# endif + +# if defined(USE_TIME_ANALYSIS) || defined(USE_ACTIVE_PROFILE)\ + || defined(USE_TRACE_LOG) +# define TRACE_ON +# endif + +// +// Traces are expensive, release build should not have them +// +# if defined(TRACE_ON) && defined(LAB_ONLY) + +# define TRACE_FOREGROUND_PROCESSING +//# define TRACE_RENDERER_MANAGER +//# define TRACE_PROCESS_EVENT +# define TRACE_EVENT_COUNT + +// +// Update Manager Group +// + +//# define TRACE_UPDATE_MANAGER +//# define TRACE_UPDATE_MASTER +//# define TRACE_UPDATE_REPLICANTS + +// +// Networking Group +// + +//# define TRACE_SEND_PACKET +//# define TRACE_ROUTE_PACKET +//# define TRACE_LOST_DATA +//# define TRACE_SEND_BUFFER +// +// Video Renderer group +// To see all the video renderer traces seperately, DO NOT define USE_ONE_VIDEO_TRACE +// To see all of the video renderer on the same trace, enable the following: +// +// USE_ONE_VIDEO_TRACE +// TRACE_VIDEO_RENDERER +// TRACE_VIDEO_BECOME_INTERESTING +// TRACE_VIDEO_BECOME_UNINTERESTING +// TRACE_VIDEO_RENDERER_FRAME_DONE +// +// The time used by the above four traces will all appear on the video renderer +// trace together. This configuration should not cause any buzzing of traces and +// should capture 100% of the video renderer's activity. +// Other video renderer traces may be enabled but will appear seperately +// +// CAUTION: Depending on the setup, TRACE_VIDEO_RENDERABLES can buzz, severly +// lengthening the video renderer profile times. Use carefully. +// +//# define USE_ONE_VIDEO_TRACE +//# define TRACE_VIDEO_RENDERER +//# define TRACE_VIDEO_BECOME_INTERESTING +//# define TRACE_VIDEO_BECOME_UNINTERESTING +//# define TRACE_VIDEO_RENDERER_FRAME_DONE + +//# define TRACE_VIDEO_CULL_SETUP +//# define TRACE_VIDEO_VEHICLE_RENDERABLES +//# define TRACE_VIDEO_ALL_RENDERABLES +//# define TRACE_VIDEO_MECH_CULL_RENDERABLE +//# define TRACE_VIDEO_BATCH_FLUSH +//# define TRACE_VIDEO_LOAD_OBJECT +//# define TRACE_VIDEO_PICKPOINT +//# define TRACE_VIDEO_RENDERABLES +//# define TRACE_VIDEO_CONSTRUCT_ROOT // construct the root of +//# define TRACE_VIDEO_FIRST_FRAME_DONE // obsolete soon + +// +// Audio renderer group +// + +//# define TRACE_AUDIO_RENDERER +//# define TRACE_AUDIO_RENDERER_MIDI +//# define TRACE_AUDIO_RENDERER_CREATE_OBJECTS +//# define TRACE_AUDIO_RENDERER_DESTROY_OBJECTS +//# define TRACE_AUDIO_RENDERER_START_HANDLER +//# define TRACE_AUDIO_RENDERER_STOP_HANDLER +//# define TRACE_AUDIO_RENDERER_EXECUTE +//# define TRACE_AUDIO_RENDERER_RUNNING_SOURCES +//# define TRACE_AUDIO_RENDERER_RUNNING_SORT +//# define TRACE_AUDIO_RENDERER_CALCULATE_MIX +//# define TRACE_AUDIO_RENDERER_EXECUTE_SOURCES +//# define TRACE_AUDIO_RENDERER_DORMANT_SOURCES + +// +// Gauge renderer group +// + +//# define TRACE_GAUGE_RENDERER +//# define TRACE_SCREEN_COPY + +// +// Other leftovers, these are probably obsolete, if you know ones that are, kill +// kill them off as appropriate. +// + +# if 0 +# define TRACE_COMPLETE_CYCLES +# define TRACE_DEATH_ROW + +# define TRACE_EXECUTE_ENTITY +# define TRACE_PERFORM_ENTITY +# define TRACE_PERFORM_SUBSYSTEMS +# define TRACE_EXECUTE_WATCHERS + +# define TRACE_RIO_RECEIVE_PACKET +# define TRACE_RIO_SEND_PACKET +# define TRACE_CHECK_BUFFERS +# define TRACE_CALL_NETNUB + +# endif + +# endif + +#endif + diff --git a/CODE/RP/MUNGA/CONSOLE.CPP b/CODE/RP/MUNGA/CONSOLE.CPP new file mode 100644 index 0000000..82d37c6 --- /dev/null +++ b/CODE/RP/MUNGA/CONSOLE.CPP @@ -0,0 +1,103 @@ +//===========================================================================// +// File: cnslmsgs.cpp // +// Project: MUNGA Brick: // +// Contents: Console messages // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/02/95 ECH Initial coding. // +// 06/03/95 GAH Added corresponding Macintosh message defintions. // +// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(CONSOLE_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~ ConsoleApplicationReadyToRunMessage ~~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationReadyToRunMessage:: + ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID): + NetworkClient::Message( + ConsoleApplicationReadyToRunMessageID, + sizeof(ConsoleApplicationReadyToRunMessage) + ) +{ + readyToRunHostID = ready_to_run_host_ID; +} + +//~~~~~~~~~~~~~~~~ ConsoleApplicationStateResponseMessage ~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationStateResponseMessage::ConsoleApplicationStateResponseMessage( + HostID responding_host_ID, + Enumeration application_state, + Enumeration application_type +): + NetworkClient::Message( + ConsoleApplicationStateResponseMessageID, + sizeof(ConsoleApplicationStateResponseMessage) + ) +{ + respondingHostID = responding_host_ID; + applicationState = application_state; + application = application_type; +} + +//~~~~~~~~~~~~~~~~~~ ConsoleApplicationEndMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationEndMissionMessage:: + ConsoleApplicationEndMissionMessage( + HostID player_host_ID, + int final_score + ): + NetworkClient::Message( + ConsoleApplicationEndMissionMessageID, + sizeof(ConsoleApplicationEndMissionMessage) + ) +{ + playerHostID = player_host_ID; + finalScore = final_score; +} + +//~~~~~~~~~~~~~~~~~~ ConsoleApplicationAbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationAbortMissionMessage:: + ConsoleApplicationAbortMissionMessage( + HostID player_host_ID + ): + NetworkClient::Message( + ConsoleApplicationAbortMissionMessageID, + sizeof(ConsoleApplicationAbortMissionMessage) + ) +{ + playerHostID = player_host_ID; +} + +//~~~~~~~~~~~~~~~~ ConsoleApplicationTeamEndMissionMessage ~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationTeamEndMissionMessage:: + ConsoleApplicationTeamEndMissionMessage( + HostID player_host_ID, + int player_score, + int team_ID, + int team_score + ): + NetworkClient::Message( + ConsoleApplicationTeamEndMissionMessageID, + sizeof(ConsoleApplicationTeamEndMissionMessage) + ) +{ + playerHostID = player_host_ID; + playerScore = player_score; + teamID = team_ID; + teamScore = team_score; +} + +//============================================================================== diff --git a/CODE/RP/MUNGA/CONSOLE.HPP b/CODE/RP/MUNGA/CONSOLE.HPP new file mode 100644 index 0000000..a5602c6 --- /dev/null +++ b/CODE/RP/MUNGA/CONSOLE.HPP @@ -0,0 +1,306 @@ +//===========================================================================// +// File: cnslmsgs.hpp // +// Project: MUNGA Brick: // +// Contents: Console messages // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/02/95 ECH Initial coding. // +// 06/03/95 GAH Added corresponding Macintosh message defintions. // +// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(CONSOLE_HPP) +# define CONSOLE_HPP + +#ifdef MAC +#pragma once +#endif + +#ifdef MAC +#include "NetworkEndpoint.h" +#include "Participant.h" +#else +# if !defined(NETWORK_HPP) +# include +# endif +#endif + + //~~~~~~~~~~~~~~~~~~~~~~~~ Console Message IDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + enum ConsoleMessageID + { + ConsoleApplicationReadyToRunMessageID = 0, + ConsoleApplicationStateResponseMessageID = 1, + ConsoleApplicationEndMissionMessageID = 7, + ConsoleApplicationAbortMissionMessageID = 11, + ConsoleApplicationTeamEndMissionMessageID = 14 + }; + + //~~~~~~~~~~~~~~~~~~ ConsoleApplicationReadyToRunMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationReadyToRunMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID); + + long + GetReadyToRunHostID() + {return readyToRunHostID.value();} + + private: + HostID + readyToRunHostID; + }; +#pragma options align=reset +#else + class ConsoleApplicationReadyToRunMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID); + + HostID + GetReadyToRunHostID() + {return readyToRunHostID;} + + private: + HostID + readyToRunHostID; + }; +#endif + + //~~~~~~~~~~~~~~~~ ConsoleApplicationStateResponseMessage ~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationStateResponseMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationStateResponseMessage( + HostID responding_host_ID, + LEDWORD application_state, + LEDWORD application_type + ); + + long + GetRespondingHostID() + {return respondingHostID.value();} + long + GetApplicationState() + {return applicationState.value();} + ApplicationID + GetApplication() + {return((ApplicationID) application.value());} + + private: + HostID + respondingHostID; + LEDWORD + applicationState; + LEDWORD + application; + }; +#pragma options align=reset +#else + class ConsoleApplicationStateResponseMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationStateResponseMessage( + HostID responding_host_ID, + Enumeration application_state, + Enumeration application + ); + + HostID + GetRespondingHostID() + {return respondingHostID;} + Enumeration + GetApplicationState() + {return applicationState;} + Enumeration + GetApplication() + {return application;} + + private: + HostID + respondingHostID; + Enumeration + applicationState; + Enumeration + application; + }; +#endif + + //~~~~~~~~~~~~~~~~~~ ConsoleApplicationEndMissionMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationEndMissionMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationEndMissionMessage( + HostID player_ID, + LEDWORD final_score + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetFinalScore() + {return finalScore.value();} + + private: + HostID + playerHostID; + LEDWORD + finalScore; + }; +#pragma options align=reset +#else + class ConsoleApplicationEndMissionMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationEndMissionMessage( + HostID player_host_ID, + int final_score + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + int + GetFinalScore() + {return finalScore;} + + private: + HostID + playerHostID; + int + finalScore; + }; +#endif + + //~~~~~~~~~~~~~~~~~~ ConsoleApplicationAbortMissionMessage ~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationAbortMissionMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationAbortMissionMessage( + HostID player_ID + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + + private: + HostID + playerHostID; + }; +#pragma options align=reset +#else + class ConsoleApplicationAbortMissionMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationAbortMissionMessage( + HostID player_host_ID + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + + private: + HostID + playerHostID; + }; +#endif + + //~~~~~~~~~~~~~~~~ ConsoleApplicationTeamEndMissionMessage ~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationTeamEndMissionMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationTeamEndMissionMessage( + HostID player_ID, + LEDWORD player_score, + LEDWORD team_id, + LEDWORD team_score + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetPlayerScore() + {return playerScore.value();} + long + GetTeamID() + {return teamID.value();} + long + GetTeamScore() + {return teamScore.value();} + + private: + HostID + playerHostID; + LEDWORD + playerScore; + LEDWORD + teamID; + LEDWORD + teamScore; + }; +#pragma options align=reset +#else + class ConsoleApplicationTeamEndMissionMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationTeamEndMissionMessage( + HostID player_host_ID, + int player_score, + int team_id, + int team_score + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + int + GetFinalScore() + {return playerScore;} + int + GetTeamID() + {return teamID;} + int + GetTeamScore() + {return teamScore;} + + private: + HostID + playerHostID; + int + playerScore; + int + teamID; + int + teamScore; + }; +#endif + +#endif diff --git a/CODE/RP/MUNGA/CONTROLS.CPP b/CODE/RP/MUNGA/CONTROLS.CPP new file mode 100644 index 0000000..2b2bad0 --- /dev/null +++ b/CODE/RP/MUNGA/CONTROLS.CPP @@ -0,0 +1,682 @@ +//==========================================================================// +// File: controls.cc // +// Project: MUNGA Brick: Controls Manager // +// Contents: Interface specification for Controls // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 11/21/94 CPB Initial coding. // +// 01/25/95 CPB Major surgery! Removed Entities, added Subsystems. // +//--------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include +#pragma hdrstop + +#if !defined(CONTROLS_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//############################################################################ +//####################### ControlsInstance ############################# +//############################################################################ + +ControlsInstance::ControlsInstance( + ClassID class_ID, + ModeMask mode_mask, + Plug *dependant +): + Node(class_ID), + dependantPlug(this) +{ + Check_Pointer(this); + modeMask = mode_mask; + dependantPlug.Add(dependant); + + Check_Fpu(); +} + +ControlsInstance::~ControlsInstance() +{ + Check(this); + Check_Fpu(); +} + +void + ControlsInstance::Update(void *) +{ + Fail("ControlsInstance::Update not overridden!"); +} + +// +//############################################################################# +//############################################################################# +// +void + ControlsInstance::ReleaseLinkHandler( + Socket*, + Plug* + ) +{ + Unregister_Object(this); + delete this; + Check_Fpu(); +} + +//############################################################################ +//######################### ControlsMappingGroup ############################# +//############################################################################ + +// +// The ControlsMappingGroup object maintains a group of ControlInstances. +// +// ControlsMappingGroup.Update() will call ControlsInstance.Update() +// for each instance in the group. +// + +ControlsMappingGroup::ControlsMappingGroup(): + Node(ControlsMappingGroup::ControlsMappingGroupClassID), + instanceList(this) +{ + Check_Pointer(this); + Check_Fpu(); +} + +ControlsMappingGroup::~ControlsMappingGroup() +{ + Check(this); + Remove(0); // remove all mappings + Check_Fpu(); +} + +void ControlsMappingGroup::Remove(ModeMask mode_mask) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + ControlsInstance + *controls_instance; + + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //--------------------------------------------- + // Remove mapping bit(s) + //--------------------------------------------- + controls_instance->modeMask &= ~mode_mask; + //--------------------------------------------- + // If no bits left, delete mapping + //--------------------------------------------- + if (controls_instance->modeMask == (ModeMask)0) + { + Unregister_Object(controls_instance); + delete controls_instance; + } + } + Check_Fpu(); +} + +void + ControlsMappingGroup::Update(void *data_source, ModeMask mode_mask) +{ + Check(this); + Check_Pointer(data_source); + + ChainIteratorOf + i(instanceList); + + ControlsInstance + *controls_instance; + + while ((controls_instance=i.ReadAndNext()) != NULL) + { + //------------------------------------------------ + // Process only if at least one mode bit matches + //------------------------------------------------ + Check(controls_instance); + if (controls_instance->modeMask & mode_mask) + { + controls_instance->Update(data_source); + } + } + Check_Fpu(); +} + +Logical + ControlsMappingGroup::CurrentFilterStatus(ModeMask mode_mask) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + ControlsInstance + *controls_instance; + + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + + if (controls_instance->modeMask & mode_mask) + { + Check_Fpu(); + return True; + } + } + Check_Fpu(); + return False; +} + +//############################################################################ +//########################### ControlsManager ################################ +//############################################################################ + +//--------------------------------------------------------------------------- +// Class derivation +//--------------------------------------------------------------------------- +Derivation + ControlsManager::ClassDerivations( + Receiver::ClassDerivations,"ControlsManager" + ); + +unsigned int + ControlsManager::nextOwnerID=0; + +ControlsManager + *ControlsManager::headControlsManager = NULL; + +// +//############################################################################ +// ControlsManager +// +// Creator method +//---------------------------------------------------------------------------- +// Enter: virtualDataPtr +//############################################################################ +// +ControlsManager::ControlsManager( + ClassID class_ID, + SharedData &shared_data +): + Receiver( + class_ID, + shared_data + ) +{ + activeDestination = NULL; + activeReceiver = NULL; + activeMessageID = (Receiver::MessageID) 0; + activeDependant = NULL; + //---------------------------------------------------- + // Add this object to the chain + //---------------------------------------------------- + nextControlsManager = headControlsManager; + headControlsManager = this; + Check_Fpu(); +} + +// +//############################################################################ +// ~ControlsManager +// +// Destructor method +//############################################################################ +// +ControlsManager::~ControlsManager() +{ + //---------------------------------------------------- + // Unlink this object from the chain + //---------------------------------------------------- + ControlsManager + *controls_manager, + *previous_controls_manager(NULL); + + // + // Search for 'this' in the chain + // + for( + controls_manager = headControlsManager; + controls_manager != NULL; + controls_manager = controls_manager->nextControlsManager + ) + { + if (controls_manager == this) + { + // + // Found! head of list? + // + if (previous_controls_manager == NULL) + { + headControlsManager = nextControlsManager; + } + // + // Not head, remove from chain + // + else + { + previous_controls_manager->nextControlsManager = + nextControlsManager; + } + break; + } + // + // Keep track of 'previous' object + // + previous_controls_manager = controls_manager; + } + Check_Fpu(); +} + +void + ControlsManager::Remove(ModeMask /*mode_mask*/) +{ + Fail("ControlsManager::Remove should not be called!\n"); +} + +void + ControlsManager::Execute() +{ + Fail("ControlsManager::Execute should not be called!\n"); +} + +void + ControlsManager::StartMappableButtonsConfigure( + void *active_direct_target, + Receiver *target, + Plug *dependant, + Receiver::MessageID active_message_id, + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ) +{ + Check(this); + + activeReceiver = target; + activeMessageID = active_message_id; + activeDestination = active_direct_target; + activeDependant = dependant; + + Check(application); + ModeManager + *mode_manager = application->GetModeManager(); + Check(mode_manager); + + mode_manager->RemoveModeMask(remove_mode_mask); + mode_manager->AddModeMask(add_mode_mask); + + Check_Fpu(); +} + +void + ControlsManager::StopMappableButtonsConfigure( + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ) +{ + Check(this); + + Check(application); + ModeManager + *mode_manager = application->GetModeManager(); + Check(mode_manager); + + mode_manager->RemoveModeMask(remove_mode_mask); + mode_manager->AddModeMask(add_mode_mask); + + activeDestination = NULL; + activeReceiver = NULL; + activeMessageID = (Receiver::MessageID) 0; + activeDependant = NULL; + + Check_Fpu(); +} + +void + ControlsManager::AddOrEraseMappableButton( + int /*button_number*/, + ModeMask /*mode_mask*/ + ) +{ + Check(this); + Check_Fpu(); +} + +// +//############################################################################ +// TestInstance +// +//############################################################################ +// +Logical + ControlsManager::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +// +//############################################################################ +// Shutdown +// +//############################################################################ +// +void + ControlsManager::Shutdown() +{ + ControlsManager + *controls_manager; + + for( + controls_manager = headControlsManager; + controls_manager != NULL; + controls_manager = controls_manager->nextControlsManager + ) + { + controls_manager->LocalShutdown(); + } + Check_Fpu(); +} + +void + ControlsManager::LocalShutdown() +{ + Check(this); + Check_Fpu(); +} + +//######################################################################### +//############################# ControlsString ############################ +//######################################################################### +int + ControlsString::nextID = 1; + +ControlsString::ControlsString( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + int user_code +): + Node(RegisteredClass::ControlsStringClassID) +{ + Test_Tell( + "ControlsString creator('" new_string << + "'," << keypad_unit_number << + "," << receiver_pointer << + "," << message_id << + ")\n" + ); + Check_Pointer(this); + Check_Pointer(new_string); + Check(receiver_pointer); + + //---------------------------------------------- + // Assign unique ID + //---------------------------------------------- + id = nextID++; + matchStringPointer = new_string; + keypadUnitNumber = keypad_unit_number; + //---------------------------------------------- + // Save message data + //---------------------------------------------- + receiverPointer = receiver_pointer; + messageID = message_id; + userCode = user_code; + //---------------------------------------------- + // Clear the buffer + //---------------------------------------------- + string[0] = '\0'; + stringLength = 0; + + Check_Fpu(); +} + +ControlsString::~ControlsString() +{ + Test_Tell("ControlsString destructor\n"); + Check(this); + Check_Fpu(); +} + +Logical + ControlsString::TestInstance() const +{ + return True; +} + +void + ControlsString::Update(int keypad_unit_number, ControlsKey new_key) +{ + Test_Tell( + "ControlsString::Update(" << keypad_unit_number << + "," << new_key << + "\n" + ); + Check(this); + + //---------------------------------------------- + // Update only if proper keyboard unit + //---------------------------------------------- + if (keypad_unit_number == keypadUnitNumber) + { + //-------------------------------------- + // Get string length + //-------------------------------------- + Check_Pointer(matchStringPointer); + int + length = strlen(matchStringPointer); + if (length > maxStringLength) + { + length = maxStringLength; + } + + if (stringLength > length) // in case matchString changes + { + stringLength = length; + string[stringLength] = '\0'; + } + //-------------------------------------- + // Update string buffer + //-------------------------------------- + if (stringLength < length) + { + string[stringLength++] = (char) new_key; + string[stringLength] = '\0'; + } + else + { + if (length > 1) + { + memmove(&string[0],&string[1], length-1); + } + string[length-1] = (char) new_key; + } + Test_Tell("string=" << string << "\n"); + //-------------------------------------- + // Check for match + //-------------------------------------- + if (strnicmp(string, matchStringPointer, length) == 0) + { + Test_Tell( + "ControlsString::Update, '" << matchStringPointer << + "' matched!\n" + ); + //-------------------------------------- + // Match found, send message + //-------------------------------------- + Check(receiverPointer); + Check(application); + + ControlsStringMessage + message(messageID, this->userCode); + receiverPointer->Dispatch(&message); + //-------------------------------------- + // Clear the string + //-------------------------------------- + string[0] = '\0'; + stringLength = 0; + } + } + Check_Fpu(); +} + +//######################################################################### +//######################## ControlsStringManager ########################## +//######################################################################### +ControlsStringManager::ControlsStringManager() : + Node(RegisteredClass::ControlsStringManagerClassID), + instanceList(this) +{ + Test_Tell("ControlsStringManager creator\n"); + Check_Pointer(this); +} + +ControlsStringManager::~ControlsStringManager() +{ + Test_Tell("ControlsStringManager destructor\n"); + Check(this); + //---------------------------------------------- + // Remove all ControlStrings + //---------------------------------------------- + Remove(0); + + Check_Fpu(); +} + +Logical + ControlsStringManager::TestInstance() const +{ + return True; +} + +ControlsStringID + ControlsStringManager::Add( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + int user_code + ) +{ + Test_Tell("ControlsStringManager::Add(" << new_string << + "," << keypad_unit_number << + "," << receiver_pointer << + "," << message_id << + "\n" + ); + Check(this); + Check_Pointer(new_string); + Check(receiver_pointer); + + //---------------------------------------------- + // Create the ControlsString + //---------------------------------------------- + ControlsString + *string_item = new ControlsString( + new_string, + keypad_unit_number, + receiver_pointer, + message_id, + user_code + ); + Check(string_item); + Register_Object(string_item); + //---------------------------------------------- + // Add to the instance list + //---------------------------------------------- + instanceList.Add(string_item); + //---------------------------------------------- + // return the new string's (unique) ID + //---------------------------------------------- + Check_Fpu(); + return string_item->id; +} + +void + ControlsStringManager::Remove(ControlsStringID string_id) +{ + Test_Tell("ControlsStringManager::Remove(" << string_id << ")\n"); + Check(this); + + ChainIteratorOf + i(instanceList); + + ControlsString + *controls_string; + + //---------------------------------------------- + // Search for the given ID (or universal match) + //---------------------------------------------- + while ((controls_string=i.ReadAndNext()) != NULL) + { + Check(controls_string); + if ( + (string_id == 0) || + (controls_string->id == string_id) + ) + { + Unregister_Object(controls_string); + delete controls_string; + //------------------------------------------ + // If this is not a 'universal' remove, + // we're done (ID's are unique) + //------------------------------------------ + if (string_id != 0) + { + break; + } + } + } + Check_Fpu(); +} + +void + ControlsStringManager::Update( + int keypad_unit_number, + ControlsKey new_key + ) +{ + Test_Tell("ControlsStringManager::Update(" << keypad_unit_number << + "," << new_key << + ")\n" + ); + Check(this); + + //-------------------------------------- + // Update all matching string items + //-------------------------------------- + ChainIteratorOf + i(instanceList); + + ControlsString + *controls_string; + + while ((controls_string=i.ReadAndNext()) != NULL) + { + Check(controls_string); + controls_string->Update(keypad_unit_number, new_key); + } + Check_Fpu(); +} + + +#if defined(TEST_CLASS) +# include "controls.tcp" +#endif + + + diff --git a/CODE/RP/MUNGA/CONTROLS.HPP b/CODE/RP/MUNGA/CONTROLS.HPP new file mode 100644 index 0000000..0693a72 --- /dev/null +++ b/CODE/RP/MUNGA/CONTROLS.HPP @@ -0,0 +1,947 @@ +//===========================================================================// +// File: controls.hpp // +// Project: MUNGA Brick: Controls Module // +// Contents: Interface specification for Controls module // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/12/94 CPB Initial coding. // +// 01/25/95 CPB Major surgery! Removed Entities, added Receivers. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(CONTROLS_HPP) +# define CONTROLS_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + class Controls; + class ControlsInstance; + class ControlsMappingGroup; + struct ControlsMapping; + class ControlsOwner; + class ControlsManager; + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(VECTOR2D_HPP) +# include +# endif + +# if !defined(RECEIVER_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(MODE_HPP) +# include +# endif + + //######################################################################## + //######################## Basic control typedefs ######################## + //######################################################################## + + typedef Scalar ControlsScalar; + typedef Vector2DOf ControlsJoystick; + typedef int ControlsKey; + typedef int ControlsButton; // negative for release + typedef Vector2DOf ControlsMouse; + + //######################################################################### + //######################### ControlsInstance ############################## + //######################################################################### + + // The ControlsInstance object exists to serve the ControlsMappingGroup + // object. It maintains one instance of a mapping from a physical + // input device to either an entity event message or a value. + + class ControlsInstance : + public Node + { + friend class ControlsMappingGroup; + friend class ControlsManager; // required for testing + friend class L4MappableButtonManager; + + public: + ControlsInstance( + ClassID class_id, + ModeMask mode_mask, + Plug *dependant + ); + ~ControlsInstance(); + + ModeMask + modeMask; // lots of objects (and templates) need access to this + + protected: + virtual void Update(void *data_source); + + SlotOf + dependantPlug; + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ControlsInstanceDirectOf ~~~~~~~~~~~~~~~~~~ + + template class ControlsInstanceDirectOf: + public ControlsInstance + { + friend class ControlsMappingGroup; + friend class ControlsManager; // required for testing + + public: + ControlsInstanceDirectOf( + ModeMask mode_mask, + T* data_pointer, + Plug *dependant + ); + ControlsInstanceDirectOf( + ControlsInstanceDirectOf *original + ); + ~ControlsInstanceDirectOf(); + Logical + TestInstance() const; + +// protected: + void Update(void *data_source); + + T *dataPointer; + }; + + template ControlsInstanceDirectOf::ControlsInstanceDirectOf( + ModeMask mode_mask, + T* data, + Plug *dependant + ): + ControlsInstance( + DirectControlsInstanceClassID, + mode_mask, + dependant + ), + dataPointer(data) + {} + + template ControlsInstanceDirectOf::ControlsInstanceDirectOf( + ControlsInstanceDirectOf *original + ): + ControlsInstance( + DirectControlsInstanceClassID, + original->modeMask, + original->dependantPlug.GetCurrent() + ), + dataPointer(original->dataPointer) + {} + + template ControlsInstanceDirectOf::~ControlsInstanceDirectOf() + {} + + template void + ControlsInstanceDirectOf::Update(void *data_source) + { + Check(this); + Check_Pointer(data_source); + Check_Pointer(dataPointer); + *dataPointer = *(T*)data_source; + Verify(*dataPointer == *(T*)data_source); + Check_Fpu(); + } + + template Logical + ControlsInstanceDirectOf::TestInstance() const + { + Check_Pointer(this); + Check_Pointer(dataPointer); + Check_Fpu(); + return Plug::TestInstance(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ControlsInstanceEventOf ~~~~~~~~~~~~~~~~~~ + + template class ControlsInstanceEventOf: + public ControlsInstance + { + friend class ControlsMappingGroup; + friend class ControlsManager; // required for testing + + public: + ControlsInstanceEventOf( + ModeMask mode_mask, + Receiver *receiver, + Receiver::MessageID message_id, + Plug *dependant + ); + ControlsInstanceEventOf( + ControlsInstanceEventOf *original + ); + + ~ControlsInstanceEventOf(); + Logical + TestInstance() const; + +// protected: + void Update(void *data_source); + + Receiver *receiverPointer; + Receiver::MessageID messageID; + }; + + template ControlsInstanceEventOf::ControlsInstanceEventOf( + ModeMask mode_mask, + Receiver *receiver, + Receiver::MessageID message_id, + Plug *dependant + ): + ControlsInstance( + EventControlsInstanceClassID, + mode_mask, + dependant + ), + receiverPointer(receiver), + messageID(message_id) + {} + + template ControlsInstanceEventOf::ControlsInstanceEventOf( + ControlsInstanceEventOf *original + ): + ControlsInstance( + EventControlsInstanceClassID, + original->modeMask, + original->dependantPlug.GetCurrent() + ), + receiverPointer(original->receiverPointer), + messageID(original->messageID) + {} + + template ControlsInstanceEventOf::~ControlsInstanceEventOf() + {} + + template void + ControlsInstanceEventOf::Update(void *data_source) + { + Check(this); + Check_Pointer(data_source); + Check(application); + + ReceiverDataMessageOf + update_message( + messageID, + sizeof(ReceiverDataMessageOf), + *(T*)data_source + ); + + application->Post( + ControlsEventPriority, + receiverPointer, + &update_message + ); + } + + template Logical + ControlsInstanceEventOf::TestInstance() const + { + Check_Pointer(this); + Check(receiverPointer); + Check_Fpu(); + return Plug::TestInstance(); + } + + //######################################################################### + //######################### ControlsMappingGroup ########################## + //######################################################################### + + // The ControlsMappingGroup object maintains a group of ControlInstances. + // + // ControlsMappingGroup.Update() will call ControlsInstance.Update() + // for each instance in the group. + + class ControlsMappingGroup : + public Node + { + friend class ControlsManager; // required for testing + + public: + ControlsMappingGroup(); + ~ControlsMappingGroup(); + + void + Add(ControlsInstance *mapping) + { + Check(this); + Check(mapping); + instanceList.Add(mapping); + } + + virtual void + Remove(ModeMask mode_mask); + + virtual void + Update(void *value, ModeMask mode_mask); + + Logical // returns true if at least one button active + CurrentFilterStatus(ModeMask mode_mask); + + protected: + ChainOf + instanceList; + }; + + //######################################################################### + //########################## ControlsUpdateManager ######################## + //######################################################################### + + template class ControlsUpdateManager : + public ControlsMappingGroup + { + public: + ControlsUpdateManager(); + ~ControlsUpdateManager(); + + Logical + TestInstance() const; + + virtual ControlsInstance* + Add( + ModeMask mode_mask, + Receiver *receiver_pointer, + Receiver::MessageID id, + Plug *dependant + ); + + virtual ControlsInstance* + Add( + ModeMask mode_mask, + T *destination, + Plug *dependant + ); + + virtual ControlsInstance* + AddOrErase( + ModeMask mode_mask, + Receiver *target, + Receiver::MessageID message_ID, + Plug *dependant + ); + + virtual ControlsInstance* + AddOrErase( + ModeMask mode_mask, + T *destination, + Plug *dependant + ); + + enum + { + unmapped = 0, + mappedByOthers = 1, + mappedByMe = 2 + }; + + virtual int + GetMapState( + void *direct_destination, + Receiver *event_receiver, + Receiver::MessageID message_id, + ModeMask mode_mask + ); + + virtual void + Update(void *sourcePointer, ModeMask mode_mask); + + void + ForceUpdate(T *sourcePointer, ModeMask mode_mask); + + T + previousValue; + }; + + template Logical + ControlsUpdateManager::TestInstance() const + { + return True; + } + + template + ControlsUpdateManager::ControlsUpdateManager() + : ControlsMappingGroup() + { + } + + template ControlsUpdateManager::~ControlsUpdateManager() + { + } + + template void + ControlsUpdateManager::Update( + void * source_pointer, + ModeMask mode_mask + ) + { + Check(this); + Check_Pointer(source_pointer); + + if (previousValue != *(T*) source_pointer) + { + ForceUpdate((T*)source_pointer, mode_mask); + } + Check_Fpu(); + } + + template void + ControlsUpdateManager::ForceUpdate( + T* source_pointer, + ModeMask mode_mask + ) + { + Check(this); + Check_Pointer(source_pointer); + previousValue = *source_pointer; + ControlsMappingGroup::Update(source_pointer, mode_mask); + Check_Fpu(); + } + + template ControlsInstance* + ControlsUpdateManager::Add( + ModeMask mode_mask, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + Plug *dependant + ) + { + Check(this); + Check(receiver_pointer); + + ControlsInstanceEventOf *instance = + new ControlsInstanceEventOf( + mode_mask, + receiver_pointer, + message_id, + dependant + ); + Register_Object(instance); + ControlsMappingGroup::Add(instance); + Check_Fpu(); + return instance; + } + + template ControlsInstance* + ControlsUpdateManager::Add( + ModeMask mode_mask, + T *destination, + Plug *dependant + ) + { + Check(this); + Check_Pointer(destination); + + ControlsInstanceDirectOf *instance = + new ControlsInstanceDirectOf( + mode_mask, + destination, + dependant + ); + Register_Object(instance); + ControlsMappingGroup::Add(instance); + Check_Fpu(); + return instance; + } + + template ControlsInstance* + ControlsUpdateManager::AddOrErase( + ModeMask mode_mask, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + Plug *dependant + ) + { + Check(this); + Check(receiver_pointer); + + ChainIteratorOf + i(instanceList); + ControlsInstance + *controls_instance; + ControlsInstanceEventOf + *event_mapping; + + //----------------------------------------------- + // Search through all mappings + //----------------------------------------------- + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //----------------------------------------------- + // Process only the event mappings + //----------------------------------------------- + if (controls_instance->GetClassID() == EventControlsInstanceClassID) + { + event_mapping = (ControlsInstanceEventOf *)controls_instance; + Check(event_mapping); + //----------------------------------------------- + // Process only if the target is correct, AND + // if the mapping is allowed under the given + // mode mask + //----------------------------------------------- + if ( + (event_mapping->receiverPointer == receiver_pointer) && + (event_mapping->messageID == message_id) && + (event_mapping->modeMask & mode_mask) + ) + { + //----------------------------------------------- + // Found! Remove mode enable bit(s) + //----------------------------------------------- + event_mapping->modeMask &= ~mode_mask; + //----------------------------------------------- + // If this mapping no longer matches ANY mode + // (i.e., all bits cleared), delete it, 'cuz + // it doesn't do anything anymore. + //----------------------------------------------- + if (event_mapping->modeMask == (ModeMask)0) + { + Unregister_Object(event_mapping); + delete event_mapping; + } + //----------------------------------------------- + // We found the match, break out of the loop + //----------------------------------------------- + break; + } + } + } + + //---------------------------------------------------------- + // If the mapping wasn't found (controls_instance == NULL), + // then create one. + //---------------------------------------------------------- + if (controls_instance == NULL) + { + event_mapping = + new ControlsInstanceEventOf( + mode_mask, + receiver_pointer, + message_id, + dependant + ); + Register_Object(event_mapping); + ControlsMappingGroup::Add(event_mapping); + Check_Fpu(); + return event_mapping; + } + Check_Fpu(); + return NULL; + } + + template ControlsInstance* + ControlsUpdateManager::AddOrErase( + ModeMask mode_mask, + T *destination, + Plug *dependant + ) + { + Check(this); + Check_Pointer(destination); + + ChainIteratorOf + i(instanceList); + ControlsInstance + *controls_instance; + ControlsInstanceDirectOf + *direct_mapping; + + //----------------------------------------------- + // Search through all mappings + //----------------------------------------------- + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //----------------------------------------------- + // Process only the direct mappings + //----------------------------------------------- + if (controls_instance->GetClassID() == DirectControlsInstanceClassID) + { + direct_mapping = (ControlsInstanceDirectOf *)controls_instance; + Check(direct_mapping); + //----------------------------------------------- + // Process only if the target is correct, AND + // if the mapping is allowed under the given + // mode mask + //----------------------------------------------- + if ( + (direct_mapping->dataPointer == destination) && + (direct_mapping->modeMask & mode_mask) + ) + { + //----------------------------------------------- + // Found! Remove mode enable bit(s) + //----------------------------------------------- + direct_mapping->modeMask &= ~mode_mask; + //----------------------------------------------- + // If this mapping no longer matches ANY mode + // (i.e., all bits cleared), delete it, 'cuz + // it doesn't do anything anymore. + //----------------------------------------------- + if (direct_mapping->modeMask == (ModeMask)0) + { + Unregister_Object(direct_mapping); + delete direct_mapping; + } + //----------------------------------------------- + // We found the match, break out of the loop + //----------------------------------------------- + break; + } + } + } + //---------------------------------------------------------- + // If the mapping wasn't found (controls_instance == NULL), + // then create one. + //---------------------------------------------------------- + if (controls_instance == NULL) + { + direct_mapping = + new ControlsInstanceDirectOf( + mode_mask, + destination, + dependant + ); + Register_Object(direct_mapping); + ControlsMappingGroup::Add(direct_mapping); + Check_Fpu(); + return direct_mapping; + } + Check_Fpu(); + return NULL; + } + + template int + ControlsUpdateManager::GetMapState( + void *direct_destination, + Receiver *event_receiver, + Receiver::MessageID message_id, + ModeMask mode_mask + ) + { + Check(this); + + ChainIteratorOf + i(instanceList); + ControlsInstance + *controls_instance; + int + map_state = 0; + + //----------------------------------------------- + // Search through all mappings + //----------------------------------------------- + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //------------------------------------ + // Process if allowed mode + //------------------------------------ + if (controls_instance->modeMask & mode_mask) + { + //------------------------------------ + // Process direct mappings + //------------------------------------ + if (controls_instance->GetClassID() == + DirectControlsInstanceClassID + ) + { + ControlsInstanceDirectOf + *direct_mapping = (ControlsInstanceDirectOf *) + controls_instance; + + Check(direct_mapping); + if (direct_mapping->dataPointer == direct_destination) + { + map_state |= mappedByMe; + } + else + { + map_state |= mappedByOthers; + } + } + //------------------------------------ + // Process event mappings + //------------------------------------ + else + { + Verify(controls_instance->GetClassID() == + EventControlsInstanceClassID + ); + + ControlsInstanceEventOf + *event_mapping = (ControlsInstanceEventOf *) + controls_instance; + + Check(event_mapping); + if ( + (event_mapping->receiverPointer == event_receiver) && + (event_mapping->messageID == message_id) + ) + { + map_state |= mappedByMe; + } + else + { + map_state |= mappedByOthers; + } + } + } + } + Check_Fpu(); + return map_state; + } + + //######################################################################### + //############################ ControlsManager ############################ + //######################################################################### + class ControlsManager: + public Receiver + { + friend class ControlsMappingGroup; // for access to groupEnable + //------------------------------------------------------------------- + // Shared data support + //------------------------------------------------------------------- + public: + static Derivation ClassDerivations; +// static SharedData DefaultData; + + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- + protected: + ControlsManager( + ClassID class_ID = ControlsManagerClassID, + SharedData &shared_data = ControlsManager::DefaultData + ); + public: + ~ControlsManager(); + + unsigned int + UniqueOwnerID() + { + if ((nextOwnerID+1)==0) { ++nextOwnerID; } + Check_Fpu(); + return (++nextOwnerID); + } + + virtual void + Remove(ModeMask mode_mask); + + virtual void + Execute(); + + static Logical + TestClass(); + + Logical + TestInstance() const; + + static void + Shutdown(); + + virtual void + LocalShutdown(); + + //------------------------------------------------------------------- + // Mode control + //------------------------------------------------------------------- + virtual void + StartMappableButtonsConfigure( + void *active_direct_target, + Receiver *target, + Plug *dependant, + Receiver::MessageID active_message_id, + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ); + + virtual void + StopMappableButtonsConfigure( + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ); + + virtual void + AddOrEraseMappableButton( + int button_number, + ModeMask mode_mask + ); + //------------------------------------------------------------------- + // Gauge support + //------------------------------------------------------------------- + void + *activeDestination; + Receiver + *activeReceiver; + Receiver::MessageID + activeMessageID; + Plug + *activeDependant; + + private: + static ControlsManager + *headControlsManager; + + ControlsManager + *nextControlsManager; + + static unsigned int + nextOwnerID; + }; + + + //######################################################################### + //############################ ControlsMapping ############################ + //######################################################################### + // Used by tools for building/reading control map streams + struct ControlsMapping + { + public: + enum { + DirectMapping=0, + EventMapping=1 + }; + + Enumeration + controlsGroup, + controlsElement, + mappingType, + subsystemID; + ModeMask + modeMask; + union + { + Simulation::AttributeID attributeID; + Receiver::MessageID messageID; + }; + }; + + //######################################################################### + //############################ ControlsString ############################# + //######################################################################### + + typedef int ControlsStringID; + + class ControlsString : + public Node + { + friend class ControlsStringManager; + protected: + + enum + { + maxStringLength=16 + }; + + ControlsString( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + int user_code + ); + ~ControlsString(); + + Logical + TestInstance() const; + void + Update(int keypad_unit_number, ControlsKey new_key); + + ControlsStringID + id; + const char + *matchStringPointer; + char + string[maxStringLength+1]; + int + stringLength, + keypadUnitNumber, + userCode; + Receiver + *receiverPointer; + Receiver::MessageID + messageID; + + static ControlsStringID + nextID; + }; + + + + //######################################################################### + //######################## ControlsStringMessage ########################## + //######################################################################### + // This is sent by the controlsString object when a match is detected + + class ControlsStringMessage: + public Receiver::Message + { + public: + ControlsStringMessage( + Receiver::MessageID message_ID, + int user_code + ): + Receiver::Message(message_ID, sizeof(ControlsStringMessage)), + userCode(user_code) + {} + + int + userCode; + }; + + //######################################################################### + //######################## ControlsStringManager ########################## + //######################################################################### + // This class matches strings from a keypad. When the given string + // is matched, it sends an event to the given receiver. + + class ControlsStringManager : + public Node + { + public: + ControlsStringManager(); + ~ControlsStringManager(); + + Logical + TestInstance() const; + + ControlsStringID + Add( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID id, + int user_code = 0 + ); + void + Remove(ControlsStringID string_id); + + void + Update(int keypad_unit_number, ControlsKey new_key); + + ChainOf + instanceList; + }; + +#endif + diff --git a/CODE/RP/MUNGA/CONTROLS.TCP b/CODE/RP/MUNGA/CONTROLS.TCP new file mode 100644 index 0000000..e938e57 --- /dev/null +++ b/CODE/RP/MUNGA/CONTROLS.TCP @@ -0,0 +1,303 @@ +//==========================================================================// +// File: controls.tst // +// Project: MUNGA Brick: COntrols module // +// Contents: Test code for vector classes // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 12/12/94 CPB Initial coding. // +//--------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include + +#pragma initialize 34 + +// +//########################################################################### +//########################################################################### +// +TestControlsManager::TestControlsManager() + : ControlsManager() +{ +} + +// +//########################################################################### +//########################################################################### +// +TestControlsManager::~TestControlsManager() +{ +} + +// +//########################################################################### +//########################################################################### +// +void + TestControlsManager::Execute() +{ +} + +//########################################################################### +//############################# TestReceiver ################################ +//########################################################################### +Derivation + TestControlsReceiver::ClassDerivations( + Receiver::ClassDerivations,"TestControlsReceiver1" + ); + +TestControlsReceiver::SharedData + TestControlsReceiver::DefaultData( + TestControlsReceiver::ClassDerivations, + TestControlsReceiver::MessageHandlers + ); + +TestControlsReceiver::TestControlsReceiver( + TestControlsReceiver::ClassID class_ID, + TestControlsReceiver::SharedData &shared_data +): + Receiver(class_ID, shared_data) +{ + keyStroke = 0; + joystickValue.x = 0.0f; + joystickValue.y = 0.0f; +} + +TestControlsReceiver::~TestControlsReceiver() +{ +} + +void +TestControlsReceiver::KeyboardMessageHandler( + ReceiverDataMessageOf *message +) +{ + keyStroke = message->dataContents; +} + +void +TestControlsReceiver::JoystickMessageHandler( + ReceiverDataMessageOf > *message +) +{ + joystickValue = message->dataContents; +} + +const Receiver::HandlerEntry + TestControlsReceiver::MessageHandlerEntries[]= +{ + { + TestControlsReceiver::KeyboardMessageID, + "Keyboard", + (Receiver::Handler)&TestControlsReceiver::KeyboardMessageHandler + }, + { + TestControlsReceiver::JoystickMessageID, + "Joystick", + (Receiver::Handler)&TestControlsReceiver::JoystickMessageHandler + } +}; + +Receiver::MessageHandlerSet + TestControlsReceiver::MessageHandlers( + ELEMENTS(TestControlsReceiver::MessageHandlerEntries), + TestControlsReceiver::MessageHandlerEntries, + Receiver::MessageHandlers + ); + +// +//########################################################################### +//########################################################################### +// +Logical + ControlsManager::TestClass() +{ +#if 0 + Test_Message("Starting ControlsManager test...\n"); + unsigned int fakeOwnerID(1); + + Vector2DOf vector1(0.0f, 0.0f); + Vector2DOf vector2(1.0f, 2.0f); + Vector2DOf vector3(3.0f, 4.0f); + // + //-------------------------------------------------------- + // Test ControlsInstanceDirectOf... + //-------------------------------------------------------- + // + { + ControlsInstanceDirectOf< Vector2DOf > *instance1; + + instance1 = new ControlsInstanceDirectOf< Vector2DOf >( + fakeOwnerID,&vector1 + ); + + Check(instance1); + Register_Object(instance1); + + instance1->Update(&vector2); + Test(vector1 == vector2); + + Unregister_Object(instance1); + delete instance1; + } + // + //-------------------------------------------------------- + // Test ControlsMappingGroup + //-------------------------------------------------------- + // + { + ControlsMappingGroup testGroup; + Check(&testGroup); + + ControlsInstanceDirectOf< Vector2DOf > *instance1; + instance1 = new ControlsInstanceDirectOf< Vector2DOf >( + fakeOwnerID, + &vector1 + ); + Check(instance1); + Register_Object(instance1); + + ControlsInstanceDirectOf< Vector2DOf > *instance2; + instance2 = new ControlsInstanceDirectOf< Vector2DOf > ( + fakeOwnerID, + &vector2 + ); + Check(instance2); + Register_Object(instance2); + + testGroup.Add(instance1); + testGroup.Add(instance2); + + ChainIteratorOf + i(testGroup.instanceList); + + ControlsInstance + *controls_instance; + + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + } + + testGroup.Update(&vector3); + Test(vector1 == vector3); + Test(vector2 == vector3); + + Unregister_Object(instance2); + delete instance2; + + Unregister_Object(instance1); + delete instance1; + } + // + //-------------------------------------------------------- + // Create Receiver + //-------------------------------------------------------- + // + TestControlsReceiver *my_receiver; + + my_receiver = new TestControlsReceiver(); + Check(my_receiver); + Register_Object(my_receiver); + + // + //-------------------------------------------------------- + // Test ControlsInstanceEventOf... + //-------------------------------------------------------- + // + { + int q0, q1; + int testKey = 0; + + ControlsInstanceEventOf< int > *instance1; + + instance1 = new ControlsInstanceEventOf< int > ( + fakeOwnerID, + my_receiver, + TestControlsReceiver::KeyboardMessageID + ); + Check(instance1); + Register_Object(instance1); + + ControlsInstanceDirectOf< int > *instance2; + instance2 = new ControlsInstanceDirectOf< int > ( + fakeOwnerID, + &testKey + ); + Check(instance2); + Register_Object(instance2); + + Test(my_receiver->keyStroke == 0); + q0 = 1; + instance1->Update(&q0); + application->ProcessAllEvents(); // process posted events + Test(my_receiver->keyStroke == q0); + // + //-------------------------------------------------------- + // Test ControlsMappingGroup, again + //-------------------------------------------------------- + // + ControlsMappingGroup testGroup; + Check(&testGroup); + testGroup.Add(instance1); + testGroup.Add(instance2); + + q1=2; + testGroup.Update(&q1); + application->ProcessAllEvents(); // process posted events + Test(my_receiver->keyStroke == q1); + Test(testKey == q1); + + Unregister_Object(instance2); + delete instance2; + Unregister_Object(instance1); + delete instance1; + } + // + //-------------------------------------------------------- + // Test ControlsUpdateManager + //-------------------------------------------------------- + // + { + ControlsUpdateManager intGroup; + int source = 1; + int dest1 = 0; + int dest2 = 0; + + intGroup.Add(0,&dest1); + intGroup.Add(0,&dest2); + + intGroup.ForceUpdate(&source); + + Test(dest1 == source); + Test(dest2 == source); + + intGroup.Remove(0); + + dest1 = 0; + dest2 = 0; + intGroup.ForceUpdate(&source); + Test(dest1 == 0); + Test(dest2 == 0); + } + // + //-------------------------------------------------------- + // Destroy Receiver + //-------------------------------------------------------- + // + Unregister_Object(my_receiver); + delete my_receiver; + + // + //-------------------------------------------------------- + // Return test result + //-------------------------------------------------------- + // +#endif + return True; +} + diff --git a/CODE/RP/MUNGA/CONTROLS.THP b/CODE/RP/MUNGA/CONTROLS.THP new file mode 100644 index 0000000..80b7eed --- /dev/null +++ b/CODE/RP/MUNGA/CONTROLS.THP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: controls.thh // +// Project: MUNGA Brick: Controls Module // +// Contents: Interface specification for Controls module // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/12/94 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(CONTROLS_THH) +# define CONTROLS_THH + + //######################################################################### + //########################## TestControlsManager ########################## + //######################################################################### + + class TestControlsManager: + public ControlsManager + { + public: + TestControlsManager(); + ~TestControlsManager(); + + void + Execute(); + }; + + //######################################################################### + //############################# TestReceiver ############################## + //######################################################################### + class TestControlsReceiver: + public Receiver + { + //######################################################################### + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //######################################################################### + // Construction and Destruction Support + // + public: + TestControlsReceiver( + ClassID class_ID=TrivialReceiverClassID, + SharedData &shared_data=DefaultData + ); + + ~TestControlsReceiver(); + + //########################################################################## + // Messaging Support + // + public: + enum { + KeyboardMessageID=Receiver::NextMessageID, + JoystickMessageID, + NextMessageID + }; + + protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void KeyboardMessageHandler(ReceiverDataMessageOf *); + void JoystickMessageHandler(ReceiverDataMessageOf > *); + + //########################################################################## + // Test Support + // + public: + int + keyStroke; + + Vector2DOf + joystickValue; + }; + + +#endif + diff --git a/CODE/RP/MUNGA/CSTR.HPP b/CODE/RP/MUNGA/CSTR.HPP new file mode 100644 index 0000000..ecd613a --- /dev/null +++ b/CODE/RP/MUNGA/CSTR.HPP @@ -0,0 +1,1089 @@ +//===========================================================================// +// File: string.hpp // +// Title: Definition of CString class. // +// Project: Munga // +// Author: Eric Huffman // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/21/95 ECH Initial coding // +//---------------------------------------------------------------------------// +// Copyright (c) 1994-1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(CSTR_HPP) +# define CSTR_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + class CStringRepresentation; + class CString; + + class MemoryStream; + + class StringRepresentation; + class pString; + class pcString; + typedef StringRepresentation& rString; + typedef const StringRepresentation& rcString; + + //########################################################################## + //#################### StringRepresentation ########################## + //########################################################################## + + class StringRepresentation + { + private: + char firstByte; + + // + // A new string cannot be created directly. It must already exist in + // RAM and simply be pointed where needed + // + StringRepresentation(); + StringRepresentation(rcString string); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessor functions + // + public: + const char& + operator[](size_t index) const + {Check(this); return (&firstByte)[index];} + char& + operator[](size_t index) + {Check(this); return (&firstByte)[index];} + + operator const char*() const + {Check(this); return &firstByte;} + operator char*() + {Check(this); return &firstByte;} + + size_t + GetLength() const + {Check(this); return strlen(&firstByte);} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Assignment functions + // + public: + rString + operator=(const char* string) + { + Check(this); Check_Pointer(string); + strcpy(&firstByte, string); return *this; + } + rString + operator=(rcString string) + { + Check(this); Check(&string); + strcpy(&firstByte, &string.firstByte); return *this; + } + rString + operator=(char byte) + {Check(this); firstByte = byte; return *this;} + + + rString + operator+=(const char* string) + { + Check(this); Check_Pointer(string); + strcat(&firstByte, string); return *this; + } + rString + operator+=(char chr); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Comparison functions + // + public: + int + Compare(const char *string) const + {return strcmp(&firstByte, string);} + int + Compare( + const char *string, + size_t length + ) const + {return strncmp(&firstByte, string, length);} + int + CaselessCompare(const char *string) const + {return stricmp(&firstByte, string);} + int + CaselessCompare( + const char *string, + size_t length + ) const + {return strnicmp(&firstByte, string, length);} + + Logical + operator<(const char* string) const + {return Compare(string) < 0;} + Logical + operator<=(const char* string) const + {return Compare(string) <= 0;} + Logical + operator>(const char* string) const + {return Compare(string) > 0;} + Logical + operator>=(const char* string) const + {return Compare(string) >= 0;} + Logical + operator==(const char* string) const + {return Compare(string) == 0;} + Logical + operator!=(const char* string) const + {return Compare(string) != 0;} + + Logical + operator<(char chr) const + {return firstByte < chr;} + Logical + operator<=(char chr) const + {return firstByte <= chr;} + Logical + operator>(char chr) const + {return firstByte > chr;} + Logical + operator>=(char chr) const + {return firstByte >= chr;} + Logical + operator==(char chr) const + {return firstByte == chr;} + Logical + operator!=(char chr) const + {return firstByte != chr;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Stream functions + // + public: + friend ostream& + operator <<( + ostream &strm, + rcString str + ) + {return strm << &str.firstByte;} + + friend MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + StringRepresentation *str + ); + + friend MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const StringRepresentation *str + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test support + // + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const StringRepresentation *p); + #endif + + Logical + TestInstance() const + {return True;} + }; + + //########################################################################## + //########################### pString ################################ + //########################################################################## + + class pString SIGNATURED + { + friend class pcString; + + protected: + StringRepresentation* stringText; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructors + // + public: + pString(char *string = NULL) + {stringText = (StringRepresentation*)string;} + pString(rString string) + {stringText = &string;} + pString(const pString& string) + {stringText = string.stringText;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Assignment functions + // + public: + pString& + operator=(char *string) + {stringText = (StringRepresentation*)string; return *this;} + pString& + operator=(rString string) + {stringText = &string; return *this;} + pString& + operator=(const pString& string) + {stringText = string.stringText; return *this;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Search functions + // + public: + pString& + operator++() + {++SKIPPY_CAST(char*,stringText); return *this;} + pString + operator++(int) + {return pString(SKIPPY_CAST(char*,stringText)++);} + pString& + operator--() + {--SKIPPY_CAST(char*,stringText); return *this;} + pString + operator--(int) + {return pString(SKIPPY_CAST(char*,stringText)--);} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessor functions + // + public: + rString + operator*() const + {return *stringText;} + StringRepresentation* + operator->() const + {return stringText;} + + char& + operator[](size_t index) const + {Check(this); return (*stringText)[index];} + + operator char*() const + {Check(this); return (char*)stringText;} + Logical + operator!() const + {return !stringText;} + + char** + GetTextPtr() + {return (char**)&stringText;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Stream functions + // + public: + friend MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + pString str + ) + {return MemoryStream_Read(stream, str.stringText);} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test support + // + public: + Logical + TestInstance() const + {return True;} + }; + + //########################################################################## + //####################### pcString ############################# + //########################################################################## + + class pcString SIGNATURED + { + protected: + const StringRepresentation* stringText; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructors + // + public: + pcString(const char *string = NULL) + {stringText = (const StringRepresentation*)string;} + pcString(rcString string) + {stringText = &string;} + pcString(const pString& string) + {stringText = string.stringText;} + pcString(const pcString& string) + {stringText = string.stringText;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Assignment functions + // + public: + pcString& + operator=(const char *string) + {stringText = (const StringRepresentation*)string; return *this;} + pcString& + operator=(rcString string) + {stringText = &string; return *this;} + pcString& + operator=(const pString& string) + {stringText = string.stringText; return *this;} + pcString& + operator=(const pcString& string) + {stringText = string.stringText; return *this;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Search functions + // + public: + pcString& + operator++() + {++SKIPPY_CAST(const char*,stringText); return *this;} + pcString + operator++(int) + {return pcString(SKIPPY_CAST(const char*,stringText)++);} + pcString& + operator--() + {--SKIPPY_CAST(const char*,stringText); return *this;} + pcString + operator--(int) + {return pcString(SKIPPY_CAST(const char*,stringText)--);} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessor functions + // + public: + rcString + operator*() const + {return *stringText;} + const StringRepresentation* + operator->() const + {return stringText;} + + const char& + operator[](size_t index) const + {Check(this); return (*stringText)[index];} + + operator const char*() const + {Check(this); return (const char*)stringText;} + Logical + operator!() const + {return !stringText;} + + const char** + GetTextPtr() + {return (const char**)&stringText;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test support + // + public: + Logical + TestInstance() const + {return True;} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ASCII Conversions + // + void + Convert_From_Ascii( + const char* str, + char* value + ); + void + Convert_From_Ascii( + const char* str, + Byte* value + ); + void + Convert_From_Ascii( + const char* str, + short* value + ); + void + Convert_From_Ascii( + const char* str, + Word* value + ); + void + Convert_From_Ascii( + const char* str, + int* value + ); + void + Convert_From_Ascii( + const char* str, + unsigned* value + ); + void + Convert_From_Ascii( + const char* str, + long* value + ); + void + Convert_From_Ascii( + const char* str, + LWord* value + ); + + //########################################################################## + //##################### CStringRepresentation ######################## + //########################################################################## + + class CStringRepresentation SIGNATURED + { + friend CString; + + friend CString + operator + ( + const CString &str1, + const CString &str2 + ); + + friend CString + operator + ( + const CString &str1, + char ch + ); + + friend MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + CString *str + ); + + friend void + Convert_From_Ascii( + const char *str, + CString *value + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction + // + private: + CStringRepresentation(); + CStringRepresentation(const CStringRepresentation &str); + CStringRepresentation(const char *cstr); + + public: + ~CStringRepresentation(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Length, Size + // + private: + // + // Length returns strlen of string + // + size_t + Length() const; + // + // Size returns memory allocation size + // + size_t + Size() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accesors & Manipulation + // + private: + // + // create a c-string from CStringRepresentation method + // HACK - ECH 11/1/95 - Remove const to support 3rd party libs + // + operator char*() const; + + // + // assignment method + // + CStringRepresentation + operator = (const CStringRepresentation &str); + CStringRepresentation + operator = (const char *cstr); + + // + // concatenation methods + // + friend CStringRepresentation + operator + ( + const CStringRepresentation &str1, + const CStringRepresentation &str2 + ); + + friend CStringRepresentation + operator + ( + const CStringRepresentation & str1, + char ch + ); + + void + operator += (const CStringRepresentation &str); + void + operator += (char ch); + + // + // comparison methods + // + int + Compare(const CStringRepresentation &str) const; + + int + operator < (const CStringRepresentation &str) const; + int + operator > (const CStringRepresentation &str) const; + int + operator <= (const CStringRepresentation &str) const; + int + operator >= (const CStringRepresentation &str) const; + int + operator == (const CStringRepresentation &str) const; + int + operator != (const CStringRepresentation &str) const; + + // + // character retrieval method + // + char + operator [] (size_t pos) const; + + CStringRepresentation + GetNthToken( + size_t nth_token, + char *delimiters=NULL + ) const; + + // + // case-modification methods + // + #if 0 + void + ToUpper(); + void + ToLower(); + #endif + + // + // stream input/output methods + // + friend ostream& + operator << ( + ostream &strm, + const CStringRepresentation &str + ); + + friend MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + CStringRepresentation *str + ); + + friend MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const CStringRepresentation& str + ); + + friend void + Convert_From_Ascii( + const char *str, + CStringRepresentation *value + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Reference count methods + // + private: + void + IncrementReferenceCount(); + + void + DecrementReferenceCount(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + // + // class constant + // + static size_t + allocationIncrement; + + // + // calc alloc size for needed bytes + // + static size_t + CalculateSize(size_t needed); + + // + // instance variables + // + size_t + stringSize; + size_t + stringLength; + char + *stringText; + + // + // reference count + // + int + referenceCount; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ CStringRepresentation inlines ~~~~~~~~~~~~~~~~~~~ + + // value return methods + inline size_t + CStringRepresentation::Length() const + { + Check(this); + return stringLength; + } + + inline size_t + CStringRepresentation::Size() const + { + Check(this); + return stringSize; + } + + // create a c-string from CStringRepresentation method + // HACK - ECH 11/1/95 - Remove const to support 3rd party libs + inline + CStringRepresentation::operator char*() const + { + Check(this); + return stringText; + } + + // concatenation methods + inline void + CStringRepresentation::operator += (const CStringRepresentation &str) + { + Check(this); + *this = *this + str; + } + + inline void + CStringRepresentation::operator += (char ch) + { + Check(this); + *this = *this + ch; + } + + // comparison methods + inline int + CStringRepresentation::operator < (const CStringRepresentation &str) const + { + return (Compare(str) < 0); + } + + inline int + CStringRepresentation::operator > (const CStringRepresentation &str) const + { + return (Compare(str) > 0); + } + + inline int + CStringRepresentation::operator <= (const CStringRepresentation &str) const + { + return !(Compare(str) > 0); + } + + inline int + CStringRepresentation::operator >= (const CStringRepresentation &str) const + { + return !(Compare(str) < 0); + } + + inline int + CStringRepresentation::operator == (const CStringRepresentation &str) const + { + return (Compare(str) == 0); + } + + inline int + CStringRepresentation::operator != (const CStringRepresentation &str) const + { + return (Compare(str) != 0); + } + + // character retrieval method + inline char + CStringRepresentation::operator [] (size_t pos) const + { + Check(this); + return (pos >= stringLength) ? ('\x00') : (stringText[pos]); + } + + // stream input/output methods + inline ostream& + operator << (ostream &strm, const CStringRepresentation &str) + { + Check(&str); + strm << str.stringText; + return strm; + } + + // Reference count methods + inline void + CStringRepresentation::IncrementReferenceCount() + { + Check(this); + Verify(referenceCount >= 0); + referenceCount++; + } + + inline void + CStringRepresentation::DecrementReferenceCount() + { + Check(this); + Verify(referenceCount > 0); + if (--referenceCount == 0) + { + Unregister_Object(this); + delete this; + } + } + + //########################################################################## + //############################ CString ############################### + //########################################################################## + + class CString SIGNATURED + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction + // + public: + CString(); + CString(const CString &str); + CString(const char *cstr); + + ~CString(); + + Logical + TestInstance() const; + static Logical + TestClass(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Length, Size + // + public: + // + // Length returns strlen of string + // + size_t + Length() const; + // + // Size returns memory allocation size + // + size_t + Size() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accesors & Manipulation + // + public: + // + // create a c-string from CString method + // HACK - ECH 11/1/95 - Remove const to support 3rd party libs + // + operator char*() const; + + // + // assignment method + // + CString + operator = (const CString &str); + CString + operator = (const char *cstr); + + // + // concatenation methods + // + friend CString + operator + ( + const CString &str1, + const CString &str2 + ); + + friend CString + operator + ( + const CString & str1, + char ch + ); + + void + operator += (const CString &str); + void + operator += (char ch); + + // + // comparison methods + // + int + Compare(const CString &str) const; + + int + operator < (const CString &str) const; + int + operator > (const CString &str) const; + int + operator <= (const CString &str) const; + int + operator >= (const CString &str) const; + int + operator == (const CString &str) const; + int + operator != (const CString &str) const; + + // + // character retrieval method + // + char + operator [] (size_t pos) const; + + CString + GetNthToken( + size_t nth_token, + char *delimiters=NULL + ) const; + + // + // stream input/output methods + // + friend + ostream & operator << ( + ostream &strm, + const CString &str + ); + + friend MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + CString* str + ); + + friend MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const CString* str + ); + + friend void + Convert_From_Ascii( + const char *str, + CString *value + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + CStringRepresentation + *representation; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ CString inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // construction, destruction, testing + inline + CString::CString() + { + representation = new CStringRepresentation; + Register_Object(representation); + representation->IncrementReferenceCount(); + Verify(representation->referenceCount == 1); + } + + inline + CString::CString(const CString &str) + { + Check(&str); + representation = str.representation; + Check(representation); + representation->IncrementReferenceCount(); + } + + inline + CString::CString(const char *cstr) + { + representation = new CStringRepresentation(cstr); + Register_Object(representation); + representation->IncrementReferenceCount(); + Verify(representation->referenceCount == 1); + } + + inline + CString::~CString() + { + Check(representation); + representation->DecrementReferenceCount(); + } + + inline Logical + CString::TestInstance() const + { + Check(representation); + return True; + } + + // length, size + inline size_t + CString::Length() const + { + Check(representation); + return representation->Length(); + } + + inline size_t + CString::Size() const + { + Check(representation); + return representation->Size(); + } + + // create a c-string from CString method + // HACK - ECH 11/1/95 - Remove const to support 3rd party libs + inline + CString::operator char*() const + { + Check(representation); + return representation->stringText; + } + + // concatenation methods + inline CString + operator + ( + const CString &str1, + const CString &str2 + ) + { + Check(&str1); + Check(&str2); + CStringRepresentation temp = *str1.representation + *str2.representation; + return CString(temp.stringText); + } + + inline CString + operator + ( + const CString &str1, + char ch + ) + { + Check(&str1); + CStringRepresentation temp = *str1.representation + ch; + return CString(temp.stringText); + } + + inline void + CString::operator += (const CString &str) + { + Check(this); + Check(&str); + *this = *this + str; + } + + inline void + CString::operator += (char ch) + { + Check(this); + *this = *this + ch; + } + + // comparison methods + inline int + CString::Compare(const CString &str) const + { + Check(&str); + Check(representation); + return representation->Compare(*str.representation); + } + + inline int + CString::operator < (const CString &str) const + { + return (Compare(str) < 0); + } + + inline int + CString::operator > (const CString &str) const + { + return (Compare(str) > 0); + } + + inline int + CString::operator <= (const CString &str) const + { + return !(Compare(str) > 0); + } + + inline int + CString::operator >= (const CString &str) const + { + return !(Compare(str) < 0); + } + + inline int + CString::operator == (const CString &str) const + { + return (Compare(str) == 0); + } + + inline int + CString::operator != (const CString &str) const + { + return (Compare(str) != 0); + } + + // character retrieval method + inline char + CString::operator [] (size_t pos) const + { + Check(representation); + return (*representation)[pos]; + } + + inline CString + CString::GetNthToken( + size_t nth_token, + char *delimiters + ) const + { + Check(representation); + CStringRepresentation temp = + representation->GetNthToken(nth_token, delimiters); + return CString(temp.stringText); + } + + // stream input/output methods + inline ostream& + operator << ( + ostream &strm, + const CString &str + ) + { + Check(&str); + strm << *str.representation; + return strm; + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const CString* str + ) + { + return MemoryStream_Write(stream, *str->representation); + } + +#endif diff --git a/CODE/RP/MUNGA/CSTR.TCP b/CODE/RP/MUNGA/CSTR.TCP new file mode 100644 index 0000000..2943322 --- /dev/null +++ b/CODE/RP/MUNGA/CSTR.TCP @@ -0,0 +1,79 @@ + +#define TEST_STRING "Test String" +#define TEST_STRING_2 "Test StringTest String" +#define TEST_STRING_3 "Test StringZ" + +Logical + CString::TestClass() +{ +#if 1 + CString string_a; + + //Verify(string_a.stringSize == 0); + //Verify(string_a.stringLength == 0); + //Verify(string_a.stringText == NULL); + + CString string_b(TEST_STRING); + CString string_c(string_b); + + Verify(string_b.Length() == strlen(TEST_STRING)); + Verify(string_b.Length() == strlen(string_c)); + Verify(string_b == string_c); + + CString string_d(TEST_STRING_2); + CString string_e; + + string_e = string_b + string_c; + Verify(string_e == string_d); + + CString string_f(TEST_STRING_3); + CString string_g; + + string_g = string_b + 'Z'; + Verify(string_g == string_f); + + CString string_h(TEST_STRING); + + string_h += string_b; + Verify(string_h == string_d); + + CString string_i(TEST_STRING); + + string_i += 'Z'; + Verify(string_i == string_f); + + CString string_j("aaa"); + CString string_k("aab"); + CString string_l("abb"); + CString string_m("bbb"); + CString string_n("aaa"); + + Verify(string_j < string_k); + Verify(string_l > string_k); + Verify(string_l <= string_m); + Verify(string_m >= string_j); + Verify(string_j == string_n); + Verify(string_j != string_k); + + Verify(string_k[0] == 'a'); + Verify(string_k[1] == 'a'); + Verify(string_k[2] == 'b'); + + CString string_o("0.1,0.2,0.3"); + CString string_p("0.1 0.2 0.3"); + CString string_q("0.1"); + CString string_r("0.2"); + CString string_s("0.3"); + + Verify(string_o.GetNthToken(0) == string_q); + Verify(string_o.GetNthToken(1) == string_r); + Verify(string_o.GetNthToken(2) == string_s); + + Verify(string_p.GetNthToken(0) == string_q); + Verify(string_p.GetNthToken(1) == string_r); + Verify(string_p.GetNthToken(2) == string_s); +#endif + + return True; +} + diff --git a/CODE/RP/MUNGA/CULTURAL.HPP b/CODE/RP/MUNGA/CULTURAL.HPP new file mode 100644 index 0000000..2c5722d --- /dev/null +++ b/CODE/RP/MUNGA/CULTURAL.HPP @@ -0,0 +1,388 @@ +//===========================================================================// +// File: cultural.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for Cultural Icon Class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/11/95 JM Initial coding. // +// 01/10/96 JM Added Landmark Terrain // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined (CULTURAL_HPP) +# define CULTURAL_HPP + +#if !defined(TERRAIN_HPP) +# include +#endif + +#if !defined(MEMSTRM_HPP) +# include +#endif + +#if !defined(RESOURCE_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +#if !defined(TEAM_HPP) +# include +#endif + + class ScenarioRole; + + + + //########################################################################## + //################## CulturalIcon::ModelResource ####################### + //########################################################################## + + struct CulturalIcon__ModelResource + { + Scalar + destroyedYTranslation; + + Scalar + timeDelay; + + ResourceDescription::ResourceID + explosionResourceID; + + ResourceDescription::ResourceID + crunchExplosionResourceID; + + Logical + sinkCollisionVolume, stoppingCollisionVolume; + }; + + //########################################################################## + //##################### Class CulturalIcon ########################## + //########################################################################## + + class CulturalIcon : + public UnscalableTerrain + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation ClassDerivations; + + static SharedData DefaultData; + + + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + public: + enum { + SetBurningStateMessageID = UnscalableTerrain::NextMessageID, + NextMessageID + }; + + void + TakeDamageMessageHandler(TakeDamageMessage *damage_message); + void + SetBurningStateMessageHandler(Message *burning_message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Collision Volume Support + // + protected: + + void + UpdateCollisionVolumes(); + + enum { + RemoveCollisionVolumeOnDeathBit = UnscalableTerrain::NextBit, + StoppingCollisionVolumeBit, + NextBit + }; + + enum { + RemoveCollisionVolumeOnDeathFlag = 1 << RemoveCollisionVolumeOnDeathBit, + StoppingCollisionVolumeFlag = 1 << StoppingCollisionVolumeBit + }; + + void + SetRemoveCollisionVolumeFlag() + {Check(this); simulationFlags |= RemoveCollisionVolumeOnDeathFlag;} + + Logical + RemoveCollisionVolumeOnDeath() const + {Check(this); return (simulationFlags&RemoveCollisionVolumeOnDeathFlag);} + + void + SetStoppingCollisionVolumeFlag() + {Check(this); simulationFlags |= StoppingCollisionVolumeFlag; } + + ResourceDescription::ResourceID + explosionResourceID; + + ResourceDescription::ResourceID + crunchExplosionResourceID; + + + Scalar + destroyedYTranslation; + + Scalar + timeDelay; + + + public: + + Logical + IsStoppingCollisionVolume() const + {Check(this); return (simulationFlags&StoppingCollisionVolumeFlag);} + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + + enum { + TeamNameAttributeID = UnscalableTerrain::NextAttributeID, + NextAttributeID + }; + + enum { + BurningState = UnscalableTerrain::StateCount, + WaitingToBurn, + StateCount + }; + + char + teamName[64]; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + + typedef CulturalIcon__ModelResource ModelResource; + + CulturalIcon( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~CulturalIcon(); + + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + Logical + TestInstance() const; + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static CulturalIcon* + Make(MakeMessage *creation_message); + + static int + CreateModelResource ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + + static int + CreateDamageZoneStream ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + }; + //########################################################################## + //################## Landmark::MakeMessage ############################# + //########################################################################## + class Landmark__MakeMessage : + public CulturalIcon::MakeMessage + { + public: + + int + landmarkID; + + char + roleName[64]; + char + landmarkName[64]; + char + teamName[64]; + + Landmark__MakeMessage(); + Landmark__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + char *team_name, + int landmark_ID, + CString role_name + + ) : + CulturalIcon::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + EntityID::Null, + resource_ID, + instance_flags, + origin + ), + landmarkID(landmark_ID) + { + Str_Copy(teamName, team_name, sizeof(teamName)); + Str_Copy(roleName, (const char*)role_name, sizeof(roleName)); + } + }; + + //########################################################################## + //################## Landmark::ModelResource ####################### + //########################################################################## + + struct Landmark__ModelResource : + public CulturalIcon::ModelResource + { +#if 0 + ResourceDescription::ResourceID + roleResourceID; +#endif + }; + //########################################################################## + //##################### Class Landmark ########################## + //########################################################################## + + class Landmark : + public CulturalIcon + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + public: + + void + TakeDamageMessageHandler(TakeDamageMessage *damage_message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local Data support + // + protected: + + ScenarioRole + *scenarioRole; + + int + landmarkID; + + Team + *owningTeam; + + char + teamName[64]; + + public: + + const ScenarioRole* + GetScenarioRole() const + {Check(this); return scenarioRole; } + + void + SetScenarioRole(ScenarioRole *scenario_role) + { Check(this); scenarioRole = scenario_role; } + + int + GetLandmarkID() const + {Check(this); return landmarkID; } + + Team* + GetOwningTeam() + {Check(this); return owningTeam; } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor / Destructor support + // + public: + + typedef Landmark__MakeMessage MakeMessage; + typedef Landmark__ModelResource ModelResource; + + Landmark( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + + ~Landmark(); + + Logical + TestInstance() const; + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static Landmark* + Make(MakeMessage *creation_message); + + static int + CreateModelResource ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + + + }; +#endif diff --git a/CODE/RP/MUNGA/DAMAGE.CPP b/CODE/RP/MUNGA/DAMAGE.CPP new file mode 100644 index 0000000..03d2ba8 --- /dev/null +++ b/CODE/RP/MUNGA/DAMAGE.CPP @@ -0,0 +1,834 @@ +//===========================================================================// +// File: damage.cpp // +// Project: MUNGA Brick: Entity Manager // +// Contents: Damage Details // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/01/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SEGMENT_HPP) +# include +#endif + +#if !defined(EXPTBL_HPP) +# include +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(JMOVER_HPP) +# include +#endif + +#if !defined(SCHAIN_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MaterialList::MaterialList() : + materialList(NULL) +{ + listIterator = new CStringSocketIterator(materialList); + Register_Object(listIterator); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MaterialList::~MaterialList() +{ + DeletePlugs(); + + Unregister_Object(listIterator); + delete listIterator; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Damage::Damage() +{ + damageAmount = 0.0f; + damageForce = Vector3D::Identity; + surfaceNormal.x = 0.0f; + surfaceNormal.y = 1.0f; + surfaceNormal.z = 0.0f; + impactPoint = Point3D::Identity; + burstCount = 1.0f; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +EntitySegment* + DamageZone::GetCurrentEffectSite(Enumeration effect_site_type) +{ + Check(this); + EntitySegment *return_segment; + switch(effect_site_type) + { +Return_Default_Effect: + case DefaultEffectSite: + default: + { + SChainIteratorOf iterator(defaultEffectSiteChain); + Check(iterator.GetCurrent()); + return iterator.GetCurrent(); + } + case InternalVideoEffectSite: + { + SChainIteratorOf iterator(internalVideoEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + case ExternalVideoEffectSite: + { + SChainIteratorOf iterator(externalVideoEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + case InternalAudioEffectSite: + { + SChainIteratorOf iterator(internalAudioEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + case ExternalAudioEffectSite: + { + SChainIteratorOf iterator(externalAudioEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::Reset(Logical ) +{ + SetDamageZoneState(DefaultState); + damageZoneGraphicState.SetState(ExistsGraphicState); + damageLevel = 0.0f; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::WriteUpdateRecord(UpdateRecord *update_record) +{ + Check(this); + Check_Pointer(update_record); + update_record->damageLevel = damageLevel; + update_record->damageZoneState = damageZoneState.GetState(); + update_record->damageZoneGraphicState = damageZoneGraphicState.GetState(); + update_record->damageZoneIndex = damageZoneIndex; + update_record->changedFlags = changedFlags; + update_record->recordLength = sizeof(*update_record); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Clear Flags here for MasterInstance DamageZones! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResetChangedFlags(); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::ReadUpdateRecord(UpdateRecord *update_record) +{ + Check(this); + Check_Pointer(update_record); + Verify(damageZoneIndex == update_record->damageZoneIndex); + + damageLevel = update_record->damageLevel; + damageZoneState.SetState(update_record->damageZoneState); + damageZoneGraphicState.SetState(update_record->damageZoneGraphicState); + changedFlags = update_record->changedFlags; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DamageZone::DamageZone(Simulation *owner, int damage_zone_index) : + Node(DamageZoneClassID), + materialTable(NULL, False), + damageZoneState(DamageStateCount), + damageZoneGraphicState(GraphicStateCount), + defaultEffectSiteChain(NULL), + internalVideoEffectSiteChain(NULL), + externalVideoEffectSiteChain(NULL), + internalAudioEffectSiteChain(NULL), + externalAudioEffectSiteChain(NULL) +{ + Check(owner); + damageZoneIndex = damage_zone_index; + owningSimulation = owner; + damageLevel = 0.0f; + explosionTable = NULL; + for(int ii=0;ii> damageZoneName; + + if (owningSimulation->IsDerivedFrom(JointedMover::ClassDerivations)) + { + JointedMover *jointed_mover = Cast_Object( + JointedMover*, + owningSimulation + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in all Effect Sites + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int effect_site_count; + int effect_site_index; + EntitySegment *effect_site_segment; + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Read in External Video + //~~~~~~~~~~~~~~~~~~~~~~~ + // + for (int jj=0;jj> effect_site_count; + for(int ii=0;ii> effect_site_index; + effect_site_segment = jointed_mover->GetSegment(effect_site_index); + Check(effect_site_segment); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Add the Segment to the Appropriate Chain + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + switch (jj) + { + case DefaultEffectSite: + defaultEffectSiteChain.Add(effect_site_segment); + break; + case ExternalVideoEffectSite : + externalVideoEffectSiteChain.Add(effect_site_segment); + break; + case InternalVideoEffectSite : + internalVideoEffectSiteChain.Add(effect_site_segment); + break; + case ExternalAudioEffectSite : + externalAudioEffectSiteChain.Add(effect_site_segment); + break; + case InternalAudioEffectSite : + internalAudioEffectSiteChain.Add(effect_site_segment); + break; + + } + } + } + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in these for consistancy + // and for later improvements for + // not Jointed Mover Objects! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int filler_int; + for (int jj=0;jj> filler_int; + } + } + + *stream >> defaultArmorPoints; + + int ii; + for (ii=0; ii> damageScale[ii]; + } + + int skeleton_count; + EntitySegment::SkeletonType skl_type; + + *stream >> skeleton_count; + + for(ii=0;ii> skl_type; + + int material_count; + *stream >> material_count; + if(!material_count) + { + continue; + } + MaterialList *material_list = new MaterialList; + Register_Object(material_list); + for(int jj=0;jj> new_material; + MaterialList::CStringPlug *new_plug = + new MaterialList::CStringPlug(new_material); + Register_Object(new_plug); + material_list->Add(new_plug); + } + material_list->First(); + materialTable.AddValue(material_list, skl_type); + } + + changedFlags = 0; + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DamageZone::~DamageZone() +{ + MaterialTableIterator iterator(materialTable); + iterator.DeletePlugs(); + + if (explosionTable) + { + Unregister_Object(explosionTable); + delete explosionTable; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExplosionTable* + DamageZone::CreateExplosionTable(MemoryStream *explosion_stream) +{ + Check(this); + explosionTable = new ExplosionTable(explosion_stream); + Register_Object(explosionTable); + Check_Fpu(); + return explosionTable; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::TakeDamage(Damage &damage) +{ + Check(this); + Check_Pointer(&damage); + + damageLevel += damage.damageAmount * damageScale[damage.damageType]; + Clamp(damageLevel, 0.0f, 1.0f); + SetDamageLevelChangedFlag(); + if (damageLevel >= 1.0f) + { + SetDamageZoneState(BurningState); + SetGraphicState(DestroyedGraphicState); + SetGraphicStateChangedFlag(); + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DamageZone::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DamageZone::CreateStreamedDamageZone( + NotationFile *model_file, + const char *, + NotationFile *skl_file, + CString damage_zone_name, + MemoryStream *damage_zone_stream, + NotationFile *dmg_file, + const ResourceDirectories *directories + ) +{ + Check_Pointer(damage_zone_name); + Check_Pointer(&damage_zone_stream); + Check_Pointer(directories); + Check(dmg_file); + + *damage_zone_stream << damage_zone_name; + + // + // Find dzone name in .dmg file + // + if(!dmg_file->PageExists(damage_zone_name)) + { + cerr << damage_zone_name <<" listed in .skl, does not exist in .dmg file"<GetEntry( + damage_zone_name, + "WeaponDamagePoints", + &default_points + ) + ) + { + cerr<GetEntry( + damage_zone_name, + "CollisionDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + if (point_data == 0.0f) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + Check_Fpu(); + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "BallisticDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "ExplosiveDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "LaserDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "EnergyDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get dzm filename + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *dzm_namelist = model_file->MakeEntryList("video","dzm"); + if(!dzm_namelist) + { + int zero_scalar(0.0f); + *damage_zone_stream << zero_scalar; + return True; + } + Register_Object(dzm_namelist); + int dzm_filecount; + dzm_filecount = dzm_namelist->EntryCount(); + *damage_zone_stream << dzm_filecount; + + if(dzm_filecount) + { + NameList::Entry *dzm_fileentry = dzm_namelist->GetFirstEntry(); + while(dzm_fileentry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // write out the skeleton type of the material + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + // + CString dzm_entry_name; + dzm_entry_name = dzm_fileentry->GetName(); + + EntitySegment::SkeletonType skeleton_type; + if (! dzm_entry_name.Compare("dzm") ) + { + skeleton_type = EntitySegment::SkeletonType_N; + } + else if (! dzm_entry_name.Compare("dzms") ) + { + skeleton_type = EntitySegment::SkeletonType_S; + } + else if (! dzm_entry_name.Compare("dzmt") ) + { + skeleton_type = EntitySegment::SkeletonType_T; + } + else if (! dzm_entry_name.Compare("dzmo") ) + { + skeleton_type = EntitySegment::SkeletonType_O; + } + else if (! dzm_entry_name.Compare("dzma") ) + { + skeleton_type = EntitySegment::SkeletonType_A; + } + else if (! dzm_entry_name.Compare("dzmb") ) + { + skeleton_type = EntitySegment::SkeletonType_B; + } + else if (! dzm_entry_name.Compare("dzmc") ) + { + skeleton_type = EntitySegment::SkeletonType_C; + } + else if (! dzm_entry_name.Compare("dzmd") ) + { + skeleton_type = EntitySegment::SkeletonType_D; + } + *damage_zone_stream << skeleton_type; + + // + // Get the name of the dzm File + // + char *filename = MakePathedFilename( + directories->videoDirectory, + dzm_fileentry->GetChar() + ); + Register_Pointer(filename); + // + // Create a Notation file from the dzm ASCII File + // + NotationFile *dzm_file = new NotationFile(filename); + Register_Object(dzm_file); + + NameList *material_list; + material_list = dzm_file->MakeEntryList(damage_zone_name, "material"); + int entry_count(0); + if(material_list) + { + + Register_Object(material_list); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write out how many materials + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + entry_count = material_list->EntryCount(); + *damage_zone_stream << entry_count; + if(entry_count) + { + NameList::Entry *dzm_entry; + dzm_entry = material_list->GetFirstEntry(); + Check(dzm_entry); + CString material_name; + while(dzm_entry) + { + material_name = dzm_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write out the material name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + *damage_zone_stream << material_name; + dzm_entry = dzm_entry->GetNextEntry(); + } + } + Unregister_Object(material_list); + delete material_list; + } + else + { + *damage_zone_stream << entry_count; + } + dzm_fileentry = dzm_fileentry->GetNextEntry(); + Unregister_Pointer(filename); + delete filename; + Unregister_Object(dzm_file); + delete dzm_file; + } + } + Unregister_Object(dzm_namelist); + delete dzm_namelist; + + Check_Fpu(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + DamageZone::WriteEffectSegmentIndicies( + MemoryStream *damage_zone_stream, + const char *damage_zone_name, + NotationFile *dmg_file, + NotationFile *skl_file, + const char *effect_type + ) +{ + Check(dmg_file); + Check(skl_file); + Check_Pointer(damage_zone_name); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an Entry list for this type of effect Site + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int effect_count(0); + NameList::Entry *effect_entry; + NameList *effect_namelist = dmg_file->MakeEntryList(damage_zone_name, effect_type); + if (!effect_namelist) + { + // + //~~~~~~~~~~~ + // No Entries + //~~~~~~~~~~~ + // + *damage_zone_stream << effect_count; + Check_Fpu(); + return 1; + } + else + { + Register_Object(effect_namelist); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write Out number of sites + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + effect_count = effect_namelist->EntryCount(); + *damage_zone_stream << effect_count; + effect_entry = effect_namelist->GetFirstEntry(); + CString site_page_name; + int effect_site_index; + while(effect_entry) + { + site_page_name = effect_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get SegmentIndex for this effect site Name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + effect_site_index = + JointedMover::GetSegmentIndex(site_page_name, skl_file); + if (effect_site_index == -1) + { + cerr<GetNextEntry(); + } + Unregister_Object(effect_namelist); + delete effect_namelist; + } + Check_Fpu(); + return 1; +} diff --git a/CODE/RP/MUNGA/DAMAGE.HPP b/CODE/RP/MUNGA/DAMAGE.HPP new file mode 100644 index 0000000..0b10c50 --- /dev/null +++ b/CODE/RP/MUNGA/DAMAGE.HPP @@ -0,0 +1,428 @@ +//===========================================================================// +// File: damage.hpp // +// Project: MUNGA Brick: Entity Manager // +// Contents: Damage Definitions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/01/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(DAMAGE_HPP) +# define DAMAGE_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(NORMAL_HPP) +# include +# endif + +# if !defined(CSTR_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + + class MaterialList; + class EntitySegment; + class ExplosionTable; + class Simulation; + class MemoryStream; + class NotationFile; + class ResourceDirectories; + class Entity; + + //########################################################################## + //########################### Damage ################################# + //########################################################################## + + class Damage + { + public: + enum { + CollisionDamageType, + BallisticDamageType, + ExplosiveDamageType, + LaserDamageType, + EnergyDamageType, + DamageTypeCount + }; + Enumeration + damageType; + Scalar + damageAmount; + + Vector3D + damageForce; + Normal + surfaceNormal; + + // impact point should be in the global coordinate space. + Point3D + impactPoint; + // + // burst count should be thought of as number of times + // to apply the damage. + // + + int + burstCount; + + + Damage(); + }; + + //########################################################################## + //######################### MaterialList ############################# + //########################################################################## + + class MaterialList : + public Plug + { + public: + + typedef PlugOf CStringPlug; + + typedef SChainOf + CStringSocket; + + typedef SChainIteratorOf + CStringSocketIterator; + + protected: + + CStringSocketIterator* + listIterator; + + CStringSocket + materialList; + + public: + + MaterialList(); + ~MaterialList(); + + void + DeletePlugs() + {Check(this); listIterator->DeletePlugs();} + + void + Add(CStringPlug *new_plug) + {Check(this); materialList.Add(new_plug);} + + void + First() + { Check(this);listIterator->First();} + + void + Last() + {Check(this); listIterator->Last(); } + + CString* + ReadAndNext() + { + Check(this); + if (!listIterator->GetCurrent()) + return NULL; + else + return listIterator->ReadAndNext()->GetPointer(); + } + + CString* + GetCurrent() + { + Check(this); + if (!listIterator->GetCurrent()) + return NULL; + else + return listIterator->GetCurrent()->GetPointer(); + } + + void + Next() + {Check(this); if(listIterator->GetCurrent()) listIterator->Next();} + }; + //########################################################################## + //################# DamageZone::UpdateRecord ######################### + //########################################################################## + + struct DamageZone__UpdateRecord + { + public: + size_t recordLength; + int damageZoneIndex; + Scalar damageLevel; + Enumeration damageZoneState; + Enumeration damageZoneGraphicState; + LWord changedFlags; + }; + + //########################################################################## + //######################### DamageZone ############################### + //########################################################################## + + class DamageZone: + public Node + { + protected: + + Simulation* + owningSimulation; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State Support + // + private: + + StateIndicator + damageZoneState; + + StateIndicator + damageZoneGraphicState; + + public: + + enum{ + ExistsGraphicState = 0, + DestroyedGraphicState, + GoneGraphicState, + GraphicStateCount + }; + + enum{ + DefaultState = 0, + BurningState, + DamageStateCount + }; + + StateIndicator* + GetGraphicStatePointer() + {Check(this); return &damageZoneGraphicState;} + + Enumeration + GetDamageZoneState() + {Check(this); return damageZoneState.GetState();} + + void + SetDamageZoneState(Enumeration new_state) + {Check(this); damageZoneState.SetState(new_state); } + + Enumeration + GetGraphicState() + {Check(this); return damageZoneGraphicState.GetState();} + + virtual void + SetGraphicState(Enumeration new_state) + { + Check(this); + damageZoneGraphicState.SetState(new_state); + SetGraphicStateChangedFlag(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Flag Support + // + + public: + + enum { + DamageLevelChangedBit = 2, + GraphicStateChangedBit, + NextBit + }; + + enum { + DamageLevelChangedFlag = 1 << DamageLevelChangedBit, + GraphicStateChangedFlag = 1 << GraphicStateChangedBit + }; + + Logical + DamageLevelChanged() const + {Check(this); return (changedFlags & DamageLevelChangedFlag); } + + Logical + GraphicStateChanged() const + {Check(this); return (changedFlags & GraphicStateChangedFlag); } + + void + SetDamageLevelChangedFlag() + {Check(this); changedFlags |= DamageLevelChangedFlag; } + + void + SetGraphicStateChangedFlag() + {Check(this); changedFlags |= GraphicStateChangedFlag; } + + void + ResetChangedFlags() + {Check(this); changedFlags = 0; } + + LWord + changedFlags; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update Support + // + public: + typedef DamageZone__UpdateRecord UpdateRecord; + + virtual void + ReadUpdateRecord(UpdateRecord *message); + + virtual void + WriteUpdateRecord(UpdateRecord *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Material Support + // + + public: + typedef TableOf + MaterialTable; + + typedef TableIteratorOf + MaterialTableIterator; + + MaterialList* + GetMaterialList(Enumeration skl_type) + { + Check(this); + return materialTable.Find(skl_type); + } + + protected: + + MaterialTable + materialTable; + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Explosion Support + // + + protected: + + ExplosionTable + *explosionTable; + + public: + + ExplosionTable* + CreateExplosionTable(MemoryStream *explosion_stream); + + ExplosionTable* + GetExplosionTable() + {Check(this); return explosionTable; } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Effect Support + // + public: + SChainOf + defaultEffectSiteChain, + internalVideoEffectSiteChain, + externalVideoEffectSiteChain, + internalAudioEffectSiteChain, + externalAudioEffectSiteChain; + + enum { + DefaultEffectSite, + ExternalVideoEffectSite, + InternalVideoEffectSite, + ExternalAudioEffectSite, + InternalAudioEffectSite, + EffectSiteCount + }; + + EntitySegment* + GetCurrentEffectSite(Enumeration effect_site_type = DefaultEffectSite); + + static + WriteEffectSegmentIndicies( + MemoryStream *damage_zone_stream, + const char *damage_zone_name, + NotationFile *dmg_file, + NotationFile *skl_file, + const char *effect_type + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local Support + // + public: + + Simulation* + GetOwningSimulation() + {return owningSimulation;} + + int + damageZoneIndex; + + Scalar + defaultArmorPoints; + + Scalar + damageScale[Damage::DamageTypeCount]; + + Scalar + damageLevel; + + CString damageZoneName; + + virtual void + TakeDamage(Damage &damage); + + void + Reset(Logical full_reset=True); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction Support + // + DamageZone( + Simulation *owner, + int damage_zone_index, + MemoryStream *dzone_res + ); + + DamageZone(Simulation *owner, int damage_zone_index); + + virtual ~DamageZone(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Resource Support + // + static Logical + CreateStreamedDamageZone( + NotationFile *model_file, + const char *model_name, + NotationFile *skl_file, + CString damage_zone_name, + MemoryStream *damage_zone_stream, + NotationFile *dmg_file, + const ResourceDirectories *directories + ); + }; + + +#endif diff --git a/CODE/RP/MUNGA/DEBUG1ON.HPP b/CODE/RP/MUNGA/DEBUG1ON.HPP new file mode 100644 index 0000000..0f21e0e --- /dev/null +++ b/CODE/RP/MUNGA/DEBUG1ON.HPP @@ -0,0 +1,141 @@ +//=======================================================================// +// File: debug1on.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +// 4-12-95 CPB added Str_Cat macro // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(OLD_DEBUG_LEVEL) +# define OLD_DEBUG_LEVEL 1 +#else +# undef OLD_DEBUG_LEVEL +# if DEBUG_LEVEL>=3 +# define OLD_DEBUG_LEVEL 3 +# elif DEBUG_LEVEL==1 +# define OLD_DEBUG_LEVEL 1 +# elif DEBUG_LEVEL==0 +# define OLD_DEBUG_LEVEL 0 +# endif +#endif + +#undef DEBUG_LEVEL +#undef Verify +#undef Verify_And_Dump +#undef Dump +#undef Tell +#undef Warn +#undef Warn_And_Dump +#undef Check_Signature +#undef Check_Pointer +#undef Check +#undef Check_Fpu +#undef Fail +#undef Cast_Object +#undef DEBUG_CODE +#undef Mem_Copy +#undef Str_Copy +#undef Str_Cat +#undef Sqrt +#undef Arctan +#undef Arccos +#undef Arcsin + +#define DEBUG_LEVEL 1 + +#define DEBUG_CODE(x) { x } + +#define Dump(v)\ + (DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl << flush) + +#define Verify(c)\ + if (!(c)) {\ + Verify_Failed(#c,__FILE__,__LINE__);\ + } + +#define Verify_And_Dump(c,v)\ + if (!(c)) {\ + DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\ + Verify_Failed(#c,__FILE__,__LINE__);\ + } + +#define Warn(c)\ + if (c) {\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\ + } + +#define Warn_And_Dump(c,v)\ + if (c) {\ + DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\ + } + +#define Tell(m)\ + (DEBUG_STREAM << m << flush) + +#define Check_Pointer(p) Verify(p) + +#define Check_Fpu() Verify(Fpu_Ok()) + +#define Mem_Copy(destination, source, length, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + memcpy(destination, source, length);\ + } + +#define Str_Copy(destination, source, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + strcpy(destination, source);\ + } + +#define Str_Cat(destination, source, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + strcat(destination, source);\ + } + +#define Sqrt(value)\ + ((value>=0.0f) ? sqrt(value) : (Fail("Bad parameter to sqrt"),0.0f)) + +#define Arctan(y,x)\ + (\ + (!Small_Enough(y) || !Small_Enough(x))\ + ? atan2((y),(x)) :\ + (Fail("Zero Arctan!"),0.0f)\ + ) + +#define Arccos(x)\ + (\ + ((x)>=-1.0f && (x)<=1.0f)\ + ? acos(x) :\ + (Fail("Out of range Arccos!"),0.0f)\ + ) + +#define Arcsin(x)\ + (\ + ((x)>=-1.0f && (x)<=1.0f)\ + ? asin(x) :\ + (Fail("Out of range Arcsin!"),0.0f)\ + ) + +#define Power(x,y)\ + (\ + ((x)<0.0f)\ + ? (Fail("Out of range Power!"),0.0f) :\ + pow(x,y)\ + ) + +#define Check_Signature(p) Check_Pointer(p) +#define Check(p) Check_Pointer(p) + +#define Fail(m)\ + Fail_To_Debugger(m,__FILE__,__LINE__) + +#define Cast_Object(type, ptr) ((type)(ptr)) + diff --git a/CODE/RP/MUNGA/DEBUG2ON.HPP b/CODE/RP/MUNGA/DEBUG2ON.HPP new file mode 100644 index 0000000..8a87f3a --- /dev/null +++ b/CODE/RP/MUNGA/DEBUG2ON.HPP @@ -0,0 +1,185 @@ +//=======================================================================// +// File: debug2on.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +// 4-12-95 CPB added Str_Cat macro // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(OLD_DEBUG_LEVEL) +# define OLD_DEBUG_LEVEL 2 +#else +# undef OLD_DEBUG_LEVEL +# if DEBUG_LEVEL>=3 +# define OLD_DEBUG_LEVEL 3 +# elif DEBUG_LEVEL==1 +# define OLD_DEBUG_LEVEL 1 +# elif DEBUG_LEVEL==0 +# define OLD_DEBUG_LEVEL 0 +# endif +#endif + +#undef DEBUG_LEVEL +#undef Verify +#undef Verify_And_Dump +#undef Dump +#undef Tell +#undef Warn +#undef Warn_And_Dump +#undef Check_Signature +#undef Check_Pointer +#undef Check +#undef Check_Fpu +#undef Fail +#undef Cast_Object +#undef DEBUG_CODE +#undef Mem_Copy +#undef Str_Copy +#undef Str_Cat +#undef Sqrt +#undef Arctan +#undef Arccos +#undef Arcsin +#undef Power + +#define DEBUG_LEVEL 2 + +#define DEBUG_CODE(x) { x } + +#define Dump(v)\ + (DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl << flush) + +#define Verify(c)\ + if (!(c)) {\ + Verify_Failed(#c,__FILE__,__LINE__);\ + } + +#define Verify_And_Dump(c,v)\ + if (!(c)) {\ + DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\ + Verify_Failed(#c,__FILE__,__LINE__);\ + } + +#define Warn(c)\ + if (c) {\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\ + } + +#define Warn_And_Dump(c,v)\ + if (c) {\ + DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\ + } + +#define Tell(m)\ + (DEBUG_STREAM << m << flush) + +#define Check_Pointer(p) Verify(p) + +#define Check_Fpu() Verify(Fpu_Ok()) + +#define Mem_Copy(destination, source, length, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + Verify((length) <= (available));\ + Verify(abs((char*)destination - (char*)source) >= length);\ + memcpy(destination, source, length);\ + } + +#define Str_Copy(destination, source, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + Verify((strlen(source) + 1) <= (available));\ + Verify(abs(destination - source) >= (strlen(source) + 1));\ + strcpy(destination, source);\ + } + +#define Str_Cat(destination, source, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + Verify((strlen(destination) + strlen(source) + 1) <= (available));\ + strcat(destination, source);\ + } + +#define Sqrt(value)\ + ((value>=0.0f) ? sqrt(value) : (Fail("Bad parameter to sqrt"),0.0f)) + +#define Arctan(y,x)\ + (\ + (!Small_Enough(y) || !Small_Enough(x))\ + ? atan2((y),(x)) :\ + (Fail("Zero Arctan!"),0.0f)\ + ) + +#define Arccos(x)\ + (\ + ((x)>=-1.0f && (x)<=1.0f)\ + ? acos(x) :\ + (Fail("Out of range Arccos!"),0.0f)\ + ) + +#define Arcsin(x)\ + (\ + ((x)>=-1.0f && (x)<=1.0f)\ + ? asin(x) :\ + (Fail("Out of range Arcsin!"),0.0f)\ + ) + +#define Power(x,y)\ + (\ + ((x)<0.0f)\ + ? (Fail("Out of range Power!"),0.0f) :\ + pow(x,y)\ + ) + +#if defined(USE_SIGNATURE) +# define Check_Signature(p) {\ + Check_Pointer(p);\ + Verify_And_Dump(!Is_Signature_Bad(p),Is_Signature_Bad(p));\ + } +#else +# define Check_Signature(p) Check_Pointer(p) +#endif + +#if defined(USE_SIGNATURE) +# define Check(p) {Check_Signature(p);Verify(!((LWord)p & 3));Check_Fpu();} +#else +# define Check(p) {Check_Pointer(p);Verify(!((LWord)p & 3));Check_Fpu();} +#endif + +#define Fail(m)\ + Fail_To_Debugger(m,__FILE__,__LINE__) + +#if defined(USE_SIGNATURE) +# define Cast_Object(type, ptr) (\ + (!ptr)\ + ? (\ + Verify_Failed(#ptr,__FILE__,__LINE__),(type)NULL\ + )\ + : (\ + (Is_Signature_Bad((type)ptr))\ + ? (\ + Verify_Failed(\ + "Is_Signature_Bad(("#type")"#ptr")",\ + __FILE__,\ + __LINE__\ + ),(type)NULL\ + )\ + : ((type)(ptr))\ + )\ + ) +#else +# define Cast_Object(type, ptr) (\ + (!ptr)\ + ? (\ + Verify_Failed(#ptr,__FILE__,__LINE__),(type)NULL\ + )\ + : ((type)(ptr))\ + ) +#endif + diff --git a/CODE/RP/MUNGA/DEBUGOFF.HPP b/CODE/RP/MUNGA/DEBUGOFF.HPP new file mode 100644 index 0000000..57c3006 --- /dev/null +++ b/CODE/RP/MUNGA/DEBUGOFF.HPP @@ -0,0 +1,72 @@ +//=======================================================================// +// File: debugoff.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +// 4-12-95 CPB added Str_Cat macro // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(OLD_DEBUG_LEVEL) +# define OLD_DEBUG_LEVEL 0 +#else +# undef OLD_DEBUG_LEVEL +# if DEBUG_LEVEL>=3 +# define OLD_DEBUG_LEVEL 3 +# elif DEBUG_LEVEL==2 +# define OLD_DEBUG_LEVEL 2 +# elif DEBUG_LEVEL==1 +# define OLD_DEBUG_LEVEL 1 +# endif +#endif + +#undef DEBUG_LEVEL +#undef Verify +#undef Verify_And_Dump +#undef Warn +#undef Warn_And_Dump +#undef Dump +#undef Tell +#undef Check_Signature +#undef Check_Pointer +#undef Mem_Copy +#undef Str_Copy +#undef Str_Cat +#undef Check +#undef Check_Fpu +#undef Fail +#undef Cast_Object +#undef DEBUG_CODE +#undef Sqrt +#undef Arctan +#undef Arccos +#undef Arcsin + +#define DEBUG_LEVEL 0 +#define DEBUG_CODE(x) +#define Verify(c) +#define Verify_And_Dump(c,v) +#define Warn(c) +#define Warn_And_Dump(c,v) +#define Dump(v) +#define Tell(m) +#define Check_Pointer(p) +#define Check_Fpu() +#define Mem_Copy(destination, source, length, available)\ + memcpy(destination, source, length) +#define Str_Copy(destination, source, available)\ + strcpy(destination, source); +#define Str_Cat(destination, source, available)\ + strcat(destination, source); +#define Sqrt(value) sqrt(value) +#define Arctan(y,x) atan2(y,x) +#define Arccos(x) acos(x) +#define Arcsin(x) asin(x) +#define Power(x,y) pow(x,y) + +#define Check(p) +#define Check_Signature(p) +#define Fail(m) Fail_To_Debugger(m,__FILE__,__LINE__) +#define Cast_Object(type, ptr) ((type)(ptr)) + diff --git a/CODE/RP/MUNGA/DEBUGOLD.HPP b/CODE/RP/MUNGA/DEBUGOLD.HPP new file mode 100644 index 0000000..1603baf --- /dev/null +++ b/CODE/RP/MUNGA/DEBUGOLD.HPP @@ -0,0 +1,24 @@ +//=======================================================================// +// File: debug2on.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +// 4-12-95 CPB added Str_Cat macro // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(OLD_DEBUG_LEVEL) +# error Cannot revert to old debug level! +#else +# if OLD_DEBUG_LEVEL>=3 +# include "debug3on.hpp" +# elif OLD_DEBUG_LEVEL==2 +# include "debug2on.hpp" +# elif OLD_DEBUG_LEVEL==1 +# include "debug1on.hpp" +# else +# include "debugoff.hpp" +# endif +#endif + diff --git a/CODE/RP/MUNGA/DIRECTOR.CPP b/CODE/RP/MUNGA/DIRECTOR.CPP new file mode 100644 index 0000000..2fad2f7 --- /dev/null +++ b/CODE/RP/MUNGA/DIRECTOR.CPP @@ -0,0 +1,346 @@ +//===========================================================================// +// File: director.cc // +// Project: Munga // +// Contents: Chooses from a Selection of Camerea's and provides information // +// to any number of cameraship's as to which player to follow // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/09/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +// Munga Includes +// + +#include +#pragma hdrstop + +#if !defined(DIRECTOR_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(PLAYER_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +#if !defined(NTTMGR_HPP) + #include +#endif + +//############################################################################# +// Shared Data support +// +Derivation + CameraDirector::ClassDerivations( + Player::ClassDerivations, + "CameraDirector" + ); + +CameraDirector::SharedData + CameraDirector::DefaultData( + CameraDirector::ClassDerivations, + CameraDirector::MessageHandlers, + CameraDirector::AttributeIndex, + CameraDirector::StateCount, + (Entity::MakeHandler) CameraDirector::Make + ); + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraDirector::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraDirector, AttachCameraShip) +}; + +CameraDirector::MessageHandlerSet + CameraDirector::MessageHandlers( + ELEMENTS(CameraDirector::MessageHandlerEntries), + CameraDirector::MessageHandlerEntries, + Player::MessageHandlers + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::AttachCameraShipMessageHandler( + AttachCameraShipMessage *in_message + ) +{ + Check(in_message); + Check(application); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the cameraship ID to attach to + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + HostManager *host = application->GetHostManager(); + Check(host); + Entity *entity_ptr = host->GetEntityPointer(in_message->cameraShipID); + Check(entity_ptr); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the cameraShip Pointer Object + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CameraShip *camera_ship; + camera_ship = Cast_Object(CameraShip*, entity_ptr); + Check(this); + Check(camera_ship); + cameraShip = camera_ship; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::UpdateHUD( + Scalar time_slice + ) +{ + Check(this); + Check(application); + + // + //~~~~~~~~~~~~ + // HUD Support + //~~~~~~~~~~~~ + // + if (GetGoalEntity()) + { + Check(GetGoalEntity()); + Player *goal_player = GetGoalEntity()->GetPlayerLink(); + if (goal_player) + { + Check(goal_player); + goalPlayerIndex = goal_player->playerBitmapIndex; + } + } + + if ( + application->GetApplicationState() == Application::StoppingMission || + application->GetApplicationState() == Application::EndingMission + ) + { + displayRankingWindow = False; + return; + } + else if (application->GetSecondsRemainingInGame() <= 30.0f) + { + displayRankingWindow = True; + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Check times for Ranking Window Display + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (displayRankingWindow) + { + timeDisplayed += time_slice; + if(timeDisplayed >= displayIntervalOn) + { + timeTillDisplayed = displayIntervalOff; + displayRankingWindow = False; + } + } + else + { + timeTillDisplayed -= time_slice; + if (timeTillDisplayed <= 0.0f) + { + timeDisplayed = 0.0f; + displayRankingWindow = True; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::BeADirector(Scalar time_slice) +{ + Check(this); + + Player::PlayerSimulation(time_slice); + UpdateHUD(time_slice); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Time To Cut To a new Player? + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if ( + timeLeftOnPlayer > 0.0f + && application->GetApplicationState() == Application::RunningMission) + { + timeLeftOnPlayer -= time_slice; + return; + } + + Player *top_dog = FindPlayerByRank(0); + if (top_dog) + { + Check(top_dog); + Entity *vehicle = top_dog->GetPlayerVehicle(); + if (vehicle) + { + Check(vehicle); + if ((GetGoalEntity() != vehicle)) + { + SetGoalEntity(vehicle); + timeLeftOnPlayer = 10.0f; + Check(cameraShip); + CameraShip::DirectionMessage direction_message( + CameraShip::DirectionMessageID, + sizeof(CameraShip::DirectionMessage), + GetGoalEntity()->GetEntityID(), + 0.0f, + Point3D::Identity + ); + Check(cameraShip); + cameraShip->Dispatch(&direction_message); + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::CreateCameraShip(Scalar) +{ + CreatePlayerVehicle(localOrigin); + PlayerLinkMessage player_link_message ( + PlayerLinkMessageID, + sizeof(PlayerLinkMessage), + this->GetEntityID() + ); + Check(playerVehicle); + playerVehicle->Dispatch(&player_link_message); + playerVehicle->DispatchToReplicants(&player_link_message); + SetPerformance(&CameraDirector::BeADirector); + deathCount = 0; + + CameraDirector::AttachCameraShipMessage + message( + CameraDirector::AttachCameraShipMessageID, + sizeof(CameraDirector::AttachCameraShipMessage), + playerVehicle->GetEntityID() + ); + Dispatch(&message); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraDirector::CameraDirector( + CameraDirector::MakeMessage *creation_message, + CameraDirector::SharedData &virtual_data +) : + Player(creation_message, virtual_data), + goalEntity(this) +{ + cameraShip = NULL; + SetValidFlag(); + timeLeftOnPlayer = -1.0f; + if (GetInstance() != ReplicantInstance) + { + SetPerformance(&CameraDirector::CreateCameraShip); + } + // + //~~~~~~~~~~~~ + // HUD Support + //~~~~~~~~~~~~ + // + goalPlayerIndex = -1; + displayRankingWindow = False; + displayIntervalOn = 10.0f; + displayIntervalOff = 15.0f; + timeDisplayed = 0.0f; + timeTillDisplayed = displayIntervalOff; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraDirector* + CameraDirector::Make(MakeMessage *creation_message) +{ + return new CameraDirector(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraDirector::~CameraDirector() +{ + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Player* + CameraDirector::FindPlayerByRank(int rank_to_find) +{ + Check(application); + + // + //--------------------------------------- + // Get all players from the entity group + //--------------------------------------- + // + EntityGroup *player_group = + application->GetEntityManager()->FindGroup("Players"); + if(player_group) + { + Player *leading_player; + + // + //----------------------------------------------------- + // Iterate through the players find the leading player + //----------------------------------------------------- + // + ChainIteratorOf iterator(player_group->groupMembers); + while ((leading_player = (Player*) iterator.ReadAndNext()) != NULL) + { + Check(leading_player); + if (leading_player->playerRanking == rank_to_find) + { + return leading_player; + } + } + } + return NULL; +} + +Logical + CameraDirector::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/DIRECTOR.HPP b/CODE/RP/MUNGA/DIRECTOR.HPP new file mode 100644 index 0000000..ec0836e --- /dev/null +++ b/CODE/RP/MUNGA/DIRECTOR.HPP @@ -0,0 +1,192 @@ +//===========================================================================// +// File: director.hh // +// Project: Munga // +// Contents: Chooses from a Selection of Camerea's and provides information // +// to any number of cameraship's as to which player to follow // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/09/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(DIRECTOR_HPP) +# define DIRECTOR_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(PLAYER_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(CAMSHIP_HPP) +# include +# endif + +# if !defined(GRAPH2D_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + + //########################################################################## + //################# CameraDirector::AttachCameraShip ################# + //########################################################################## + + class CameraDirector__AttachCameraShipMessage: + public Player::Message + { + public: + + EntityID + cameraShipID; + + CameraDirector__AttachCameraShipMessage( + Receiver::MessageID message_ID, + size_t length, + EntityID camera_ship_ID + ): + Entity::Message(message_ID, length), + cameraShipID(camera_ship_ID) + {} + }; + + //########################################################################## + //############################# CameraDirector ############################# + //########################################################################## + + class CameraDirector: + public Player + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messaging support + // + public: + friend class CameraDirector__AttachCameraShipMessage; + + enum{ + AttachCameraShipMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef CameraDirector__AttachCameraShipMessage AttachCameraShipMessage; + + void + AttachCameraShipMessageHandler(AttachCameraShipMessage *message); + + protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Simulation Support + // + public: + typedef void + (CameraDirector::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + CreateCameraShip(Scalar time_slice); + void + BeADirector(Scalar time_slice); + void + UpdateHUD(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + public: + CameraDirector( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + + static CameraDirector* + CameraDirector::Make(CameraDirector::MakeMessage *creation_message); + + ~CameraDirector(); + + Logical + TestInstance() const; + + enum { + DefaultFlags = Entity::DefaultFlags | PreRunFlag | CameraShipPlayerFlag + }; + + static Player* + FindPlayerByRank(int rank_to_find); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Simulation Support Data & Functions + // + protected: + + SlotOf + goalEntity; + + void + SetGoalEntity(Entity *goal_entity) + { + Check(this); + goalEntity.Remove(); + Check(goal_entity); + goalEntity.Add(goal_entity); + } + + Entity* + GetGoalEntity() + {Check(this); return goalEntity.GetCurrent(); } + + Scalar + timeLeftOnPlayer; + + CameraShip + *cameraShip; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // HUD Support + // + public: + + int + goalPlayerIndex; + + Logical + displayRankingWindow; + + Scalar + timeDisplayed, + timeTillDisplayed, + displayIntervalOn, + displayIntervalOff; + }; + +#endif diff --git a/CODE/RP/MUNGA/DOOR.CPP b/CODE/RP/MUNGA/DOOR.CPP new file mode 100644 index 0000000..6643020 --- /dev/null +++ b/CODE/RP/MUNGA/DOOR.CPP @@ -0,0 +1,566 @@ +//===========================================================================// +// File: door.cc // +// Project: Red Planet // +// Contents: Door subsystem for managing door operation // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(DOOR_HPP) +# include +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(DOORFRAM_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +//############################################################################# +// Shared Data Support +// +Door::SharedData + Door::DefaultData( + Door::ClassDerivations, + Door::MessageHandlers, + Door::AttributeIndex, + Door::StateCount + ); + +Derivation + Door::ClassDerivations( + Subsystem::ClassDerivations, + "Door" + ); + + +//############################################################################# +// Messaging Support +// + + +//############################################################################# +// Attribute Support +// + +const Door::IndexEntry + Door::AttributePointers[]= +{ + { + Door::CurrentPositionAttributeID, + "CurrentPosition", + (Simulation::AttributePointer)&Door::currentPosition + }, + { + Door::VideoResourceAttributeID, + "VideoResource", + (Simulation::AttributePointer)&Door::videoResource + }, + { + Door::PercentOpenAttributeID, + "PercentOpen", + (Simulation::AttributePointer)&Door::percentOpen + }, + { + Door::CurrentVelocityAttributeID, + "CurrentVelocity", + (Simulation::AttributePointer)&Door::currentVelocity + } +}; + +Door::AttributeIndexSet + Door::AttributeIndex( + ELEMENTS(Door::AttributePointers), + Door::AttributePointers, + Subsystem::AttributeIndex + ); + +//############################################################################# +// Model Support +// +void + Door::ReadUpdateRecord(Simulation::UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + Subsystem::ReadUpdateRecord(message); + UpdateRecord* record = (UpdateRecord*) message; + + percentOpen = record->percentOpen; + switch (GetSimulationState()) + { + case Opening: + case Closing: + phaseTimeRemaining = travelTime; + break; + case Opened: + case Closed: + phaseTimeRemaining = deadTime; + break; + } +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door updated to state " +// << GetSimulationState() << " @ " +// << application->GetSecondsRemainingInGame() << endl; + MoveCollisionVolume(percentOpen); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Door::WriteUpdateRecord(Simulation::UpdateRecord *record, int update_model) +{ + Check(this); + Check_Pointer(record); + + Subsystem::WriteUpdateRecord(record, update_model); + + UpdateRecord *update = (UpdateRecord*)record; + update->percentOpen = percentOpen; + update->recordLength = sizeof(*update); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Door::SlideDoor(Scalar time_slice) +{ + Check(this); + + // + //------------------------------------------------------------ + // Advance the clock, then branch based upon our current state + //------------------------------------------------------------ + // + int new_state; + if (time_slice > 1.0f) + { + Check_Fpu(); + return; + } + phaseTimeRemaining -= time_slice; + Scalar percent_open; + switch (GetSimulationState()) + { + + // + //------------------------------------------------------------------------ + // If the door is not done opening, set its new position, otherwise branch + // to the opened state + //------------------------------------------------------------------------ + // + case Opening: +Door_Opening: + new_state = Opening; + if (phaseTimeRemaining > 0.0f) + { + percent_open = 1.0f - phaseTimeRemaining/travelTime; + } + else + { + phaseTimeRemaining += deadTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opened @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Opened; + } + currentVelocity.Subtract( + worldExtent, + GetEntity()->localOrigin.linearPosition + ); + currentVelocity /= travelTime; + Check_Fpu(); + break; + + // + //------------------------------------------------------------- + // If the door is ready to start closing, jump to closing state + //------------------------------------------------------------- + // + case Opened: +Door_Opened: + new_state = Opened; + if (phaseTimeRemaining <= 0.0f) + { + phaseTimeRemaining += travelTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closing @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Closing; + } + percent_open = 1.0f; + currentVelocity = Vector3D::Identity; + Check_Fpu(); + break; + + // + //------------------------------------------------------------------------ + // If the door is not done closing, set its new position, otherwise branch + // to the closed state + //------------------------------------------------------------------------ + // + case DefaultState: + phaseTimeRemaining = travelTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door default @ " +// << application->GetSecondsRemainingInGame() << endl; + case Closing: +Door_Closing: + new_state = Closing; + if (phaseTimeRemaining > 0.0f) + { + percent_open = phaseTimeRemaining/travelTime; + } + else + { + phaseTimeRemaining += deadTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closed @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Closed; + } + currentVelocity.Subtract( + GetEntity()->localOrigin.linearPosition, + worldExtent + ); + currentVelocity /= travelTime; + Check_Fpu(); + break; + + // + //------------------------------------------------------------- + // If the door is ready to start opening, jump to opening state + //------------------------------------------------------------- + // + case Closed: +Door_Closed: + new_state = Closed; + if (phaseTimeRemaining <= 0.0f) + { + phaseTimeRemaining += travelTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opening @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Opening; + } + percent_open = 0.0f; + currentVelocity = Vector3D::Identity; + Check_Fpu(); + break; + + } + + // + //------------------------------------------------- + // Move the collision volumes and set the new state + //------------------------------------------------- + // + MoveCollisionVolume(percent_open); + SetSimulationState(new_state); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Door::MoveCollisionVolume(Scalar percent_open) +{ + Check(this); + + // + //--------------------------------------------------------- + // If the door hasn't moved, don't bother updating anything + //--------------------------------------------------------- + // + Entity *entity = GetEntity(); + Check(entity); + + if ( + GetSimulationState() != simulationState.GetOldState() + && entity->GetInstance() == Entity::MasterInstance + && entity->IsDynamic() + ) + { + ForceUpdate(); + } + if (percent_open == percentOpen) + { + return; + } + + // + //----------------------------------- + // Otherwise, lerp the local position + //----------------------------------- + // + percentOpen = percent_open; + currentPosition.Lerp(Point3D::Identity, localExtent, percentOpen); + + // + //----------------------------------------------------------- + // Now, lerp the world position and set the collision volumes + //----------------------------------------------------------- + // + Point3D world; + world.Lerp( + GetEntity()->localOrigin.linearPosition, + worldExtent, + percentOpen + ); + + BoxedSolid* temp = collisionTemplates; + BoxedSolid* vol = collisionVolumes; + while (temp) + { + Check(temp); + Check(vol); + + vol->minX = temp->minX + world.x; + vol->maxX = temp->maxX + world.x; + vol->minY = temp->minY + world.y; + vol->maxY = temp->maxY + world.y; + vol->minZ = temp->minZ + world.z; + vol->maxZ = temp->maxZ + world.z; + + vol = vol->GetNextSolid(); + temp = temp->GetNextSolid(); + } + Verify(!vol); + Check_Fpu(); +} + +//############################################################################# +// Constructer/Destructor Support +// + +Door::Door( + DoorFrame *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + Subsystem(entity, subsystem_ID, subsystem_resource, DefaultData) +{ + Check_Pointer(this); + Check(entity); + Check_Pointer(subsystem_resource); + + // + // GetStream data NOTE::This must be in the same order as below!!! + // + localExtent = subsystem_resource->motionExtent; + travelTime = subsystem_resource->travelTime; + deadTime = subsystem_resource->deadTime; + + // + // Initialize variables + // + phaseTimeRemaining = 0.0f; + currentPosition = Point3D::Identity; + + SetPerformance(&Door::SlideDoor); + SetSimulationState(DefaultState); + + collisionVolumeCount = 0; + collisionTemplates = NULL; + collisionVolumes = NULL; + percentOpen = -1.0f; + + // + //------------------------------------- + // Establish the worldspace coordinates + //------------------------------------- + // + worldExtent.Multiply(localExtent, entity->localToWorld); + Origin local_origin = entity->localOrigin; + local_origin.linearPosition = Point3D::Identity; + + // + //------------------------------ + // Read in the collision volumes + //------------------------------ + // + Check(application); + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + ResourceDescription *res = + res_file->FindResourceDescription(subsystem_resource->collisionID); + Check(res); + res->Lock(); + BoxedSolidResource* box = + (BoxedSolidResource*)res->resourceAddress; + Check_Pointer(box); + collisionVolumeCount = res->resourceSize / sizeof(BoxedSolidResource); + + for (int i=0; ilocalOrigin); + local_box.Instance(*box,local_origin); + + collisionTemplates = + BoxedSolid::MakeBoxedSolid(&local_box, this, collisionTemplates); + Register_Object(collisionTemplates); + + collisionVolumes = + BoxedSolid::MakeBoxedSolid(&world_box, this, collisionVolumes); + Register_Object(collisionVolumes); + + ++box; + } + res->Unlock(); + + MoveCollisionVolume(0.0f); + Check(this); +} + +Door::~Door() +{ + BoxedSolid *box = collisionTemplates; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } + box = collisionVolumes; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateStreamedSubsystem +// +Logical + Door::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char* subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + ResourceFile *res_file + ) +{ + if ( + !Subsystem::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + directories + ) + ) + { + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::DoorClassID; + + // + // Get the motion Extent + // + const char *extent_data; + if( + !subsystem_file->GetEntry( + subsystem_name, + "MotionExtent", + &extent_data + ) + ) + { + cerr << subsystem_name << " missing MotionExtent!!\n"; + return -1; + } + sscanf( + extent_data, + "%f %f %f", + &subsystem_resource->motionExtent.x, + &subsystem_resource->motionExtent.y, + &subsystem_resource->motionExtent.z + ); + + // + // Get the travelTime + // + + if( + !subsystem_file->GetEntry( + subsystem_name, + "TravelTime", + &subsystem_resource->travelTime + ) + ) + { + cerr << subsystem_name << " missing TravelTime!\n"; + return -1; + } + + // + // Read in the Deadtime + // + if( + !subsystem_file->GetEntry( + subsystem_name, + "DeadTime", + &subsystem_resource->deadTime + ) + ) + { + cerr << subsystem_name << " missing DeadTime!\n"; + return False; + } + + const char* collision_file; + if ( + !subsystem_file->GetEntry( + subsystem_name, + "Collision", + &collision_file + ) + ) + { + cerr << subsystem_name << " missing Collision!\n"; + return False; + } + subsystem_resource->collisionID = + BoxedSolidResource::CreateBoxedSolidStream( + collision_file, + res_file, + directories + ); + + return True; +} + +Logical + Door::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/DOOR.HPP b/CODE/RP/MUNGA/DOOR.HPP new file mode 100644 index 0000000..de4d32e --- /dev/null +++ b/CODE/RP/MUNGA/DOOR.HPP @@ -0,0 +1,185 @@ +//===========================================================================// +// File: door.hh // +// Project: RP // +// Contents: A terrain subsystem for management of door operation // +// // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined (DOOR_HPP) +# define DOOR_HPP + +# if !defined(SUBSYSTM_HPP) +# include +# endif + +# if !defined(BOXSOLID_HPP) +# include +# endif + + class DoorFrame; + + //########################################################################## + //##################### Door::SubsystemResource ################### + //########################################################################## + + struct Door__SubsystemResource: + public Subsystem::SubsystemResource + { + Vector3D motionExtent; + Scalar + travelTime, + deadTime; + ResourceDescription::ResourceID + collisionID; + }; + + //########################################################################## + //##################### Chute::UpdateRecord ##################### + //########################################################################## + + struct Door__UpdateRecord : + public Subsystem::UpdateRecord + { + Scalar + percentOpen; + }; + + //########################################################################## + //######################### CLASS Door ######################## + //########################################################################## + + class Door : + public Subsystem + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messaging Support + // + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + PercentOpenAttributeID = Subsystem::NextAttributeID, + CurrentPositionAttributeID, + VideoResourceAttributeID, + CurrentVelocityAttributeID, + NextAttributeID + }; + + private: + + static const IndexEntry AttributePointers[]; + + protected: + + static AttributeIndexSet AttributeIndex; + + public: + + Scalar percentOpen; + ResourceDescription::ResourceID videoResource; + Point3D currentPosition; + Vector3D currentVelocity; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + enum { + Opening = Subsystem::StateCount, + Opened, + Closing, + Closed, + StateCount + }; + + typedef void + (Door::*Performance)(Scalar time_slice); + typedef Door__UpdateRecord UpdateRecord; + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + SlideDoor(Scalar time_slice); + + void + MoveCollisionVolume(Scalar open_percent); + BoxedSolid* + GetFirstBoxedSolid() + {Check(this); return collisionVolumes;} + + protected: + void + WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + + public: + typedef Door__SubsystemResource SubsystemResource; + + Door( + DoorFrame *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Door(); + + Logical + TestInstance() const; + + static Logical + CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + ResourceFile *res_file + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local Support + // + private: + Point3D + localExtent, + worldExtent; + + Scalar + phaseTimeRemaining, + travelTime, + deadTime; + + int collisionVolumeCount; + + BoxedSolid + *collisionTemplates, + *collisionVolumes; + }; + +#endif diff --git a/CODE/RP/MUNGA/DOORFRAM.CPP b/CODE/RP/MUNGA/DOORFRAM.CPP new file mode 100644 index 0000000..e4298cc --- /dev/null +++ b/CODE/RP/MUNGA/DOORFRAM.CPP @@ -0,0 +1,309 @@ +//===========================================================================// +// File: Doorfram.cc // +// Project: Red Planet // +// Contents: Implementation details of well head doors // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(DOORFRAM_HPP) +# include +#endif + +#if !defined(DOOR_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +//############################################################################# +// Shared Data Support +// +Derivation + DoorFrame::ClassDerivations(UnscalableTerrain::ClassDerivations,"DoorFrame"); + +DoorFrame::SharedData + DoorFrame::DefaultData( + DoorFrame::ClassDerivations, + DoorFrame::MessageHandlers, + DoorFrame::AttributeIndex, + DoorFrame::StateCount, + (Entity::MakeHandler)DoorFrame::Make + ); +//############################################################################# +// Test Support +// +Logical + DoorFrame::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DoorFrame::DoorFrame( + DoorFrame::MakeMessage *creation_message, + DoorFrame::SharedData &virtual_data +): + UnscalableTerrain(creation_message, virtual_data) +{ + Check_Pointer(this); + Check(creation_message); + Check(&virtual_data); + + SetValidFlag(); + SetPerformance(&DoorFrame::DoNothing); + + // + // Get the subsystem_resource from the resource file + // + Check(application); + ResourceDescription *subsystem_resource = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::SubsystemModelStreamResourceType + ); + Check(subsystem_resource); + subsystem_resource->Lock(); + Check_Pointer(subsystem_resource->resourceAddress); + MemoryStream subsystem_stream( + subsystem_resource->resourceAddress, + subsystem_resource->resourceSize); + + subsystemCount = *(int*)subsystem_stream.GetPointer(); + subsystem_stream.AdvancePointer(sizeof(int)); + Verify(subsystemCount); + + // + // Set up Subsystems + // + subsystemArray = new (Subsystem(*[subsystemCount])); + Register_Pointer(subsystemArray); + + // + // Attach the doors as defined in the mod file + // + for (int ii=BasicSubsystemCount; iisubsystemModelSize); + } + + subsystem_resource->Unlock(); + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DoorFrame* + DoorFrame::Make(DoorFrame::MakeMessage *creation_message) +{ + return new DoorFrame(creation_message); +} + +int + DoorFrame::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if ( + !UnscalableTerrain::CreateMakeMessage( + creation_message, + model_file, + directories + ) + ) + { + return False; + } + + creation_message->classToCreate = RegisteredClass::DoorFrameClassID; + creation_message->instanceFlags = + MasterInstance|DynamicFlag|MapFlag|TrappedFlag; + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DoorFrame::~DoorFrame() +{ +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + DoorFrame::CreateSubsystemStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .sub file + //------------------- + // + const char* entry_data; + if ( + !model_file->GetEntry( + "gamedata", + "Subsystems", + &entry_data + ) + ) + { + cerr << model_name << " is missing .sub file specification!\n"; + return -1; + } + + char *sub_filename = MakePathedFilename(directories->modelDirectory, entry_data); + Register_Pointer(sub_filename); + + NotationFile *sub_file = new NotationFile(sub_filename); + Register_Object(sub_file); + NameList *sub_namelist = sub_file->MakePageList(); + Register_Object(sub_namelist); + int subsystem_count = sub_file->PageCount(); + if (!subsystem_count) + { + cerr << sub_filename << " empty of missing!\n"; +Dump_And_Die: + Unregister_Pointer(sub_filename); + delete sub_filename; + Unregister_Object(sub_file); + delete sub_file; + Unregister_Object(sub_namelist); + delete sub_namelist; + return -1; + } + int buf_size = + subsystem_count * sizeof(Door::SubsystemResource) + sizeof(int); + char *buffer = new char[buf_size]; + Register_Pointer(buffer); + MemoryStream subsystem_stream(buffer, buf_size); + + *(int*)subsystem_stream.GetPointer() = subsystem_count; + subsystem_stream.AdvancePointer(sizeof(int)); + + NameList::Entry *sub_entry = sub_namelist->GetFirstEntry(); + while(sub_entry) + { + char subsystem_name[32]; + Str_Copy(subsystem_name, sub_entry->GetName(), sizeof(subsystem_name)); + const char *sub_type; + if(!sub_file->GetEntry( + subsystem_name, + "Type", + &sub_type + ) + ) + { + cerr << model_name << ':' << subsystem_name << " missing Type!\n"; +Dump_And_Die_2: + Unregister_Pointer(buffer); + delete[] buffer; + goto Dump_And_Die; + } + + Subsystem::SubsystemResource *sub_res = + (Subsystem::SubsystemResource*)subsystem_stream.GetPointer(); + if (!strcmp(sub_type, "DoorClassID")) + { + if ( + Door::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + (Door::SubsystemResource*)sub_res, + sub_file, + directories, + resource_file + ) == -1 + ) + { + goto Dump_And_Die_2; + } + } + else + { + cerr << model_name << ':' << subsystem_name + << " has an unknown component type of " << sub_type << endl; + goto Dump_And_Die_2; + } + subsystem_stream.AdvancePointer(sub_res->subsystemModelSize); + sub_entry = sub_entry->GetNextEntry(); + } + ResourceDescription *res_desc = resource_file-> + ResourceFile::AddResourceMemoryStream( + model_name, + ResourceDescription::SubsystemModelStreamResourceType, + 1, + ResourceDescription::Preload, + &subsystem_stream + ); + ResourceDescription::ResourceID res_id; + + if(!res_desc) + { + res_id = ResourceDescription::NullResourceID; + } + else + { + res_id = res_desc->resourceID; + } + + Unregister_Pointer(sub_filename); + delete sub_filename; + Unregister_Object(sub_file); + delete sub_file; + Unregister_Object(sub_namelist); + delete sub_namelist; + Unregister_Pointer(buffer); + delete[] buffer; + return res_id; + +} diff --git a/CODE/RP/MUNGA/DOORFRAM.HPP b/CODE/RP/MUNGA/DOORFRAM.HPP new file mode 100644 index 0000000..00e0873 --- /dev/null +++ b/CODE/RP/MUNGA/DOORFRAM.HPP @@ -0,0 +1,90 @@ +//===========================================================================// +// File: Doorfram.hh // +// Project: Red Planet // +// Contents: Interface specification for doors // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(DOORFRAM_HPP) +# define DOORFRAM_HPP + +# if !defined(TERRAIN_HPP) +# include +# endif + + + //########################################################################## + //############################# DoorFrame ################################ + //########################################################################## + + class DoorFrame: + public UnscalableTerrain + { + public: + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test Instance support + // + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model support + // + enum{ + BasicSubsystemCount + }; + + public: + typedef void + (DoorFrame::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + static ResourceDescription::ResourceID + CreateSubsystemStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static DoorFrame* + Make(MakeMessage *creation_message); + + DoorFrame( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~DoorFrame(); + }; + +#endif diff --git a/CODE/RP/MUNGA/DROPZONE.HPP b/CODE/RP/MUNGA/DROPZONE.HPP new file mode 100644 index 0000000..9bbb147 --- /dev/null +++ b/CODE/RP/MUNGA/DROPZONE.HPP @@ -0,0 +1,174 @@ +//===========================================================================// +// File: mover.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(DROPZONE_HPP) +# define DROPZONE_HPP + +# if !defined(ENTITY_HPP) +# include +# endif + +# if !defined(CSTR_HPP) +# include +# endif + + //########################################################################## + //##################### Mover::ModelResource ######################### + //########################################################################## + + class DropZone__MakeMessage: + public Entity::MakeMessage + { + public: + char dropZoneName[32]; + int dropZoneCount; + }; + + //########################################################################## + //################# DropZone::AssignDropZoneMessage ################## + //########################################################################## + + class DropZone__AssignDropZoneMessage: + public Entity::Message + { + public: + EntityID + requestingEntity; + Receiver::MessageID + replyMessageID; + int + deathCount; + + DropZone__AssignDropZoneMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &reply_to, + Receiver::MessageID reply_ID, + int death_count + ): + Entity::Message(message_ID, length), + requestingEntity(reply_to), + replyMessageID(reply_ID), + deathCount(death_count) + {} + }; + + //########################################################################## + //##################### DropZone::ReplyMessage ########################## + //########################################################################## + + class DropZone__ReplyMessage: + public Entity::Message + { + public: + Origin + dropZoneLocation; + int + deathCount; + + DropZone__ReplyMessage( + Receiver::MessageID message_ID, + size_t length, + const Origin &location, + int death_count + ): + Entity::Message(message_ID, length), + dropZoneLocation(location), + deathCount(death_count) + {} + }; + + //########################################################################## + //########################### DropZone ################################ + //########################################################################## + + class DropZone: + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum { + AssignDropZoneMessageID = Entity::NextMessageID, + NextMessageID + }; + + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef DropZone__MakeMessage MakeMessage; + + static DropZone* + Make(MakeMessage *creation_message); + + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + const char* model_name, + const char* resource_name, + NotationFile *map_file + ); + + DropZone( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~DropZone(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Dropzone assignment + // + public: + typedef DropZone__AssignDropZoneMessage AssignDropZoneMessage; + typedef DropZone__ReplyMessage ReplyMessage; + + const char* + GetDropZoneName() + {Check(this); return dropZoneName;} + + Logical + IsAvailable(int index); + + protected: + int dropZoneCount; + char dropZoneName[32]; + Origin *dropZones; + Time *lastUsageTime; + EntityID *lastUsedBy; + int *lastDeathCount; + + void + AssignDropZoneMessageHandler(AssignDropZoneMessage *message); + }; + +#endif diff --git a/CODE/RP/MUNGA/ENTITY.CPP b/CODE/RP/MUNGA/ENTITY.CPP new file mode 100644 index 0000000..6116296 --- /dev/null +++ b/CODE/RP/MUNGA/ENTITY.CPP @@ -0,0 +1,1622 @@ +//===========================================================================// +// File: entity.cc // +// Project: MUNGA Brick: Entity Manager // +// Contents: Implementation details of the entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(ENTITY_HPP) +# include +#endif + +#if !defined(INTEREST_HPP) +# include +#endif + +#if !defined(EXPTBL_HPP) +# include +#endif + +#if !defined(HOSTMGR_HPP) +# include +#endif + +#if !defined(PLAYER_HPP) +# include +#endif + +#if !defined(AUDIO_HPP) +# include +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(REGISTRY_HPP) +# include +#endif + +#if !defined(EVENT_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NTTMGR_HPP) + #include +#endif + +#if !defined(SUBSYSTM_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +#if defined(TRACE_EXECUTE_ENTITY) + static BitTrace Execute_Entity("Execute Entity"); + #define SET_EXECUTE_ENTITY() Execute_Entity.Set() + #define CLEAR_EXECUTE_ENTITY() Execute_Entity.Clear() +#else + #define SET_EXECUTE_ENTITY() + #define CLEAR_EXECUTE_ENTITY() +#endif + +#if defined(TRACE_PERFORM_ENTITY) + static BitTrace Perform_Entity("Perform Entity"); + #define SET_PERFORM_ENTITY() Perform_Entity.Set() + #define CLEAR_PERFORM_ENTITY() Perform_Entity.Clear() +#else + #define SET_PERFORM_ENTITY() + #define CLEAR_PERFORM_ENTITY() +#endif + +#if defined(TRACE_PERFORM_SUBSYSTEMS) + static BitTrace Perform_Subsystems("Perform Subsystems"); + #define SET_PERFORM_SUBSYSTEMS() Perform_Subsystems.Set() + #define CLEAR_PERFORM_SUBSYSTEMS() Perform_Subsystems.Clear() +#else + #define SET_PERFORM_SUBSYSTEMS() + #define CLEAR_PERFORM_SUBSYSTEMS() +#endif + +//############################################################################# +//############################## Entity ################################# +//############################################################################# + +//############################################################################# +// Virtual Data support +// +Derivation + Entity::ClassDerivations(Simulation::ClassDerivations,"Entity"); + +Entity::SharedData + Entity::DefaultData( + Entity::ClassDerivations, + Entity::MessageHandlers, + Entity::AttributeIndex, + Entity::StateCount, + Entity::Make + ); + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Entity::MessageHandlerEntries[]= +{ + { + Entity::MakeMessageID, + "Make", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::MakeReadyMessageID, + "MakeReady", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeEntityMessageID, + "RemakeEntity", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeReadyMessageID, + "RemakeReady", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeCompleteMessageID, + "RemakeComplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeIncompleteMessageID, + "RemakeIncomplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + MESSAGE_ENTRY(Entity, DestroyEntity), + { + Entity::TransferEntityMessageID, + "TransferEntity", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::TransferCompleteMessageID, + "TransferComplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::TransferIncompleteMessageID, + "TransferIncomplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + MESSAGE_ENTRY(Entity, BecomeInteresting), + MESSAGE_ENTRY(Entity, BecomeUninteresting), + MESSAGE_ENTRY(Entity, Update), + { + Entity::SubscribeReplicantMessageID, + "SubscribeReplicant", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::UnsubscribeReplicantMessageID, + "UnsubscribeReplicant", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + MESSAGE_ENTRY(Entity, TakeDamage), + MESSAGE_ENTRY(Entity, PlayerLink), + MESSAGE_ENTRY(Entity, TakeDamageStream) +}; + +Entity::MessageHandlerSet + Entity::MessageHandlers( + ELEMENTS(Entity::MessageHandlerEntries), + Entity::MessageHandlerEntries, + Receiver::MessageHandlers + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::Receive(Event* event) +{ + Check(this); + Check(event); + + // + //------------------------------------------------------------------------- + // If the entity is being transferred, post the message to the new owner of + // the entity + //------------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------------- + // If the object is not valid, filter the message to determine which ones to + // defer and which ones to immediately process + //-------------------------------------------------------------------------- + // + if (!IsValid()) + { + switch (event->messageToSend->messageID) + { + // + //---------------------------------------------------------------------- + // The messages which should be allowed through should just break out of + // this switch + //---------------------------------------------------------------------- + // + + default: + // + //------------------- + // Defer the messages + //------------------- + // + event->Defer(); + return; + } + } + + // + //------------------------------------------------ + // Go ahead and dispatch the message to the entity + //------------------------------------------------ + // + Receiver::Receive(event); + + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + Receiver::MessageHandlerSet *handlers = + shared_data->activeMessageHandlers; + DEBUG_STREAM << derivation->className << ',' << GetInstance() << endl; + DEBUG_STREAM << handlers->GetName(event->messageToSend->messageID) + << endl; + Fail("Event corrupted FPU!"); + } + #else + Check_Fpu(); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::Dispatch(Receiver::Message* incoming) +{ + Message *message = (Message*) incoming; + Check(this); + Check(message); + + // + // Call Receiver if it is not entity aware!!!!! + // + if (message->messageID < Receiver::NextMessageID) + { + Receiver::Dispatch(message); + } + + // + //----------------------------------------- + // Initialize the entity information fields + //----------------------------------------- + // + message->entityID = entityID; + message->interestZoneID = interestZoneID; + + // + //------------------------------------------------------------------- + // If this is a replicant instance, reroute the message to the master + //------------------------------------------------------------------- + // + if (GetInstance() == ReplicantInstance) + { + application->SendMessage( + ownerID, + EntityManager::EntityManagerClientID, + message + ); + } + + // + //-------------------------------------------------------- + // If this entity is invalid, post the message as an event + //-------------------------------------------------------- + // + else if (!IsValid()) + { + // ECH 1/28/96 - application->Post(DefaultEventPriority, this, message); + application->Post(EntityInvalidEventPriority, this, message); + } + + // + //-------------------------------------------- + // Otherwise, go ahead and receive the message + //-------------------------------------------- + // + else + { + Receiver::Receive(message); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::DispatchToReplicants(Message *what) +{ + Check(this); + Check(what); + + what->entityID = entityID; + what->interestZoneID = interestZoneID; + Check(application); + InterestManager *int_mgr = application->GetInterestManager(); + Check(int_mgr); + int_mgr->EntityBroadcastToReplicants(this, what); + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const Entity::IndexEntry + Entity::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Entity, LocalToWorld, localToWorld), + ATTRIBUTE_ENTRY(Entity, LocalOrigin, localOrigin), + ATTRIBUTE_ENTRY(Entity, DamageZoneCount, damageZoneCount), + ATTRIBUTE_ENTRY(Entity, DamageZones, damageZones) +}; + +Entity::AttributeIndexSet + Entity::AttributeIndex( + ELEMENTS(Entity::AttributePointers), + Entity::AttributePointers, + Simulation::AttributeIndex + ); + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::WriteUpdateRecord( + Simulation::UpdateRecord *record, + int update_model + ) +{ + Check(this); + Check_Pointer(record); + + switch (update_model) + { + case DefaultUpdateModelBit: + { + Simulation::WriteUpdateRecord(record, update_model); + + // + //---------------------------- + // Write out the record update + //---------------------------- + // + UpdateRecord *update = (UpdateRecord*)record; + update->localOrigin = localOrigin; + updateOrigin = localOrigin; + update->recordLength = sizeof(*update); + } + break; + case DamageZoneUpdateModelBit: + record->timeStamp = lastPerformance; + record->recordID = (Word)update_model; + WriteDamageUpdateRecord(record); + break; + + default: + Simulation::WriteUpdateRecord(record, update_model); + break; + } + record->subsystemID = (Word)(EntitySubsystemID + 1); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::UpdateMessageHandler(UpdateMessage *message) +{ + Check(this); + Check(message); + + // + //------------------------------------------------------ + // Position to the beginning of the update record blocks + //------------------------------------------------------ + // + MemoryStream stream(message, message->messageLength, sizeof(*message)); + + // + //------------------------------------------------------------------------ + // Step through each block until there are no more remaining, and send the + // update out the the simulation indicated by the subsystemID + //------------------------------------------------------------------------ + // + while (stream.GetBytesRemaining()) + { + Simulation::UpdateRecord *update = + (Simulation::UpdateRecord*)stream.GetPointer(); + Check_Pointer(update); + Simulation *simulation = GetSimulation((int)update->subsystemID-1); + Check(simulation); + simulation->ReadUpdateRecord(update); + stream.AdvancePointer(update->recordLength); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::ReadUpdateRecord(Simulation::UpdateRecord *record) +{ + Check(this); + Check_Pointer(record); + + switch(record->recordID) + { + case DefaultUpdateModelBit: + { + // + //----------------------- + // Read the record update + //----------------------- + // + UpdateRecord *update = (UpdateRecord*)record; + updateOrigin = update->localOrigin; + + // + //------------------------------------------------------------------ + // If we aren't able to run yet, we must update local origin as well + //------------------------------------------------------------------ + // + Check(application); + int app_state = application->GetApplicationState(); + if ( + app_state < Application::RunningMission + || app_state == Application::CreatingMission + ) + { + localOrigin = updateOrigin; + localToWorld = localOrigin; + } + Simulation::ReadUpdateRecord(record); + } + break; + case DamageZoneUpdateModelBit: + ReadDamageUpdateRecord(record); + break; + default: + Simulation::ReadUpdateRecord(record); + } + + + + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::ReadDamageUpdateRecord(Simulation::UpdateRecord *update_record) +{ + // + //------------------------------------------------------------------------ + // Step through each block until there are no more remaining, and send the + // update out the the damageZone indicated by the damageZoneIndex + //------------------------------------------------------------------------ + // + MemoryStream stream( + update_record, + update_record->recordLength, + sizeof(*update_record) + ); + + while (stream.GetBytesRemaining()) + { + DamageZone::UpdateRecord *damage_zone_record = + (DamageZone::UpdateRecord*)stream.GetPointer(); + int damage_zone_index = damage_zone_record->damageZoneIndex; + damageZones[damage_zone_index]->ReadUpdateRecord(damage_zone_record); + stream.AdvancePointer(damage_zone_record->recordLength); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define MAX_UPDATE_LENGTH 1400 + +static long Update_Buffer[MAX_UPDATE_LENGTH >> 2]; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::WriteDamageUpdateRecord(Simulation::UpdateRecord *update_record) +{ + Check(this); + Check_Pointer(update_record); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make a memory stream this size of a network packet + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + MemoryStream stream( + update_record, + sizeof(Update_Buffer) - ((char*)update_record - (char*)Update_Buffer), + sizeof(*update_record) + ); + DamageZone::UpdateRecord *record_start = + (DamageZone::UpdateRecord*)stream.GetPointer(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update Every DamageZone For NOW + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;iiWriteUpdateRecord(damage_zone_update); + stream.AdvancePointer(damage_zone_update->recordLength); + } + + // + //----------------------------------------------- + // Check to see if an update message is necessary + //----------------------------------------------- + // + if (stream.GetPointer() != record_start) + { + Simulation::UpdateRecord *damage_update = + (Simulation::UpdateRecord*)update_record; + damage_update->recordLength = + (char*)stream.GetPointer() - (char*)update_record; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity::UpdateMessage* + Entity::Execute(const Time& till) +{ + SET_EXECUTE_ENTITY(); + Check(this); + Check(&till); + + MemoryStream + stream(Update_Buffer, sizeof(Update_Buffer), sizeof(UpdateMessage)); + char *record_start = (char*)stream.GetPointer(); + + // + //----------------------------------------------------------------------- + // Check to see if the application will let us run. If We are starting a + // mission, only the player class objects can execute + //----------------------------------------------------------------------- + // + Check(application); + if ( + application->GetApplicationState() == Application::RunningMission + || application->GetApplicationState() == Application::EndingMission + || IsPreRunnable() + ) + { + PerformAndWatch(till, &stream); + } + else + { + WriteSimulationUpdate(&stream); + } + + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + DEBUG_STREAM << derivation->className << ',' << GetInstance() << endl; + Fail("Simulation corrupted FPU!"); + } + #endif + + // + //----------------------------------------------- + // Check to see if an update message is necessary + //----------------------------------------------- + // + if (stream.GetPointer() != record_start) + { + UpdateMessage *update = (UpdateMessage*)Update_Buffer; + update->messageID = UpdateMessageID; + update->messageLength = (char*)stream.GetPointer() - (char*)Update_Buffer; + update->messageFlags = 0; + CLEAR_EXECUTE_ENTITY(); + return update; + } + + // + //------------------------------------- + // Otherwise, return NULL for no update + //------------------------------------- + // + Check_Fpu(); + CLEAR_EXECUTE_ENTITY(); + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation* + Entity::GetSimulation(int index) +{ + Check(this); + + if (index == EntitySubsystemID) + { + return this; + } + + Check_Fpu(); + if ((unsigned)index < subsystemCount) + { + return subsystemArray[index]; + } + else + { + return NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Subsystem* + Entity::FindSubsystem(const char* name) +{ + Check(this); + Check_Pointer(name); + + for (int i=0; iGetName(), name)) + { + return subsystemArray[i]; + } + } + } + Check_Fpu(); + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define MAX_SUB_FILE_NAME (256) + +int + Entity::FindSubsytemID + ( +#if DEBUG_LEVEL>0 + const char *model_name, + const char *subsystem_name +#else + const char *, + const char *subsystem_name +#endif + ) +{ + Check_Pointer(model_name); + Check_Pointer(subsystem_name); + + int subsytem_id = EntitySubsystemID; + int sub_count = 0; + + CString sub_file_string; + CString sub_directory_string("models\\"); + CString model_name_string("model_name"); + CString sub_post_string(".sub"); + + sub_file_string = + sub_directory_string + model_name_string + sub_post_string; + + NotationFile sub_file(sub_file_string); + Check(&sub_file); + + NameList *page_list = sub_file.MakePageList(); + Register_Object(page_list); + NameList::Entry *entry=page_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + Check_Pointer(entry->GetName()); + if (!stricmp(subsystem_name, entry->GetName())) + { + subsytem_id = sub_count; + break; + } + + ++sub_count; + entry = entry->GetNextEntry(); + } + + Unregister_Object(page_list); + delete page_list; + + return subsytem_id; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::PerformAndWatch( + const Time &till, + MemoryStream *update_stream + ) +{ + Check(this); + Check(&till); + + // + //----------------------------------------- + // Execute all the subsystems, then ourself + //----------------------------------------- + // + SET_PERFORM_SUBSYSTEMS(); + if (subsystemArray) + { + Check_Pointer(subsystemArray); + + // + //--------------------------------------------------- + // If this is not a replicant, execute all subsystems + //--------------------------------------------------- + // + if (GetInstance() != ReplicantInstance) + { + for (int i=0; iIsNonReplicantExecutable()) + { + subsystem->PerformAndWatch(till, update_stream); + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + DEBUG_STREAM << derivation->className + << "\nExecuting subsystem[" << i << "], " + << subsystem->GetName() << endl; + Fail("Simulation corrupted FPU!"); + } + #endif + } + } + } + } + + // + //-------------------------------------------------------------------- + // If this is a replicant, execute only those subsystems which need to + //-------------------------------------------------------------------- + // + else + { + for (int i=0; iIsReplicantExecutable()) + { + subsystem->PerformAndWatch(till, update_stream); + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + DEBUG_STREAM << derivation->className + << " replicant\nExecuting subsystem[" << i << "], " + << subsystem->GetName() << endl; + Fail("Simulation corrupted FPU!"); + } + #endif + } + } + } + } + } + CLEAR_PERFORM_SUBSYSTEMS(); + + SET_PERFORM_ENTITY(); + Simulation::PerformAndWatch(till, update_stream); + Check_Fpu(); + CLEAR_PERFORM_ENTITY(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::PlayerLinkMessageHandler(PlayerLinkMessage *message) +{ + Check(application); + HostManager *host = application->GetHostManager(); + Check(host); + playerLink =(Player*) host->GetEntityPointer(message->playerID); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::TakeDamageStreamMessageHandler(TakeDamageStreamMessage *message) +{ + Check(this); + Check(message); + + // + //------------------------------------------------- + // Extract the common information out of the stream + //------------------------------------------------- + // + Damage damage_data; + EntityID shooting_entity = message->shootingEntity; + int damage_zone_index = message->damageZoneIndex; + damage_data.impactPoint = message->impactPoint; + + // + //--------------------------------------------------- + // Figure out how many damage messages there are here + //--------------------------------------------------- + // + DynamicMessage damage_stream( + message, + message->messageLength, + sizeof(*message) + ); + int entry_count; + damage_stream >> entry_count; + + for (int i=0; i> damage_data.damageType >> damage_data.damageAmount; + int subsystem; + damage_stream >> subsystem; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Apply the damage to the appropriate damageZone + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + TakeDamageMessage + message( + TakeDamageMessageID, + sizeof(TakeDamageMessage), + shooting_entity, + damage_zone_index, + damage_data, + subsystem + ); + Dispatch(&message); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::TakeDamageMessageHandler(TakeDamageMessage *message) +{ + // + //------------------------------------- + // YOU MUST CHECK FOR -1 DamageZone!!!! + //------------------------------------- + // + if (!damageZones || message->damageZone == -1) + { + return; + } + + // + //---------------------------------------------------------------------- + // If we have no damage zones allocated, we ignore any damage sent to us + //---------------------------------------------------------------------- + // + Verify(message->damageZone < damageZoneCount); + Verify(message->damageZone >= 0 ); + Check_Pointer(damageZones); + Check(damageZones[message->damageZone]); + damageZones[message->damageZone]->TakeDamage(message->damageData); + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity::Entity( + Entity::MakeMessage *creation_message, + Entity::SharedData &virtual_data +): + Simulation(creation_message->classToCreate,virtual_data), + staticVideoSocket(NULL), + dynamicVideoSocket(NULL), + audioSocket(NULL) +{ + Check_Pointer(this); + Check(creation_message); + + // + // Get host manager pointer + // + HostManager *host_manager; + + Check(application); + host_manager = application->GetHostManager(); + Check(host_manager); + + // + //----------------------------- + // Initialize the entity fields + //----------------------------- + // + playerLink = NULL; + resourceID = creation_message->resourceID; + owningPlayer = (Player*)host_manager->GetEntityPointer( + creation_message->owningPlayerID + ); + simulationFlags = creation_message->instanceFlags; + entityID = creation_message->entityID; + ownerID = creation_message->ownerID; + creationTime = Now(); + interestZoneID = creation_message->interestZoneID; + interestCount = 0; + + // initialize attributes + localOrigin = creation_message->localOrigin; + updateOrigin = localOrigin; + localToWorld = localOrigin; + + // initialize camera stuff + cameraOffset = Origin::Identity; + + SetInvalidFlag(); + + // initialize model stuff + lastPerformance = creationTime; + subsystemCount = 0; + subsystemArray = NULL; + damageZones = NULL; + damageZoneCount = 0; + + // + //-------------------------------- + // Allocate the damageZones array + //-------------------------------- + // + + // + // Read In DamageZones and Create DamageZoneID's + // + if (resourceID != ResourceDescription::NullResourceID) + { + ResourceDescription *dmg_res = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::DamageZoneStreamResourceType + ); + + // + //-------------------------------------------- + // Allocate damageZones for this entity only + // if they were defined in the resource + //-------------------------------------------- + // + if (dmg_res) + { + dmg_res->Lock(); + DynamicMemoryStream damage_zone_stream( + dmg_res->resourceAddress, + dmg_res->resourceSize); + + damage_zone_stream >> damageZoneCount; + damageZones = new (::DamageZone(*[damageZoneCount])); + Register_Pointer(damageZones); + dmg_res->Unlock(); + } + } + + // + //--------------------------------------------------------- + // Create a new entity ID and assign ownership to this host + // If (this is a master entity) or + // (this is a dynamic hermit) or + // (this is the initial independent) + //--------------------------------------------------------- + // + if ( + (GetInstance() == MasterInstance) || + (GetInstance() == HermitInstance && IsDynamic()) || + ( + (GetInstance() == IndependantInstance) && + (creation_message->ownerID == NullHostID || + creation_message->ownerID == MapHostID) + ) + ) + { + entityID = host_manager->MakeUniqueEntityID(); + ownerID = host_manager->GetLocalHostID(); + creation_message->entityID = entityID; + creation_message->ownerID = ownerID; + } + + // + //-------------------------------------------- + // Tell the host manager about this new entity + //-------------------------------------------- + // + Check(host_manager); + host_manager->NotifyOfEntityCreation(this, creation_message); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity* + Entity::Make(Entity::MakeMessage *creation_message) +{ + return new Entity(creation_message,DefaultData); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Entity::CreateMakeMessage( + MakeMessage *creation_message, +#if DEBUG_LEVEL>0 + NotationFile *model_file, +#else + NotationFile *, +#endif + const ResourceDirectories * + ) +{ + Check(creation_message); + Check(model_file); + char *p; + + creation_message->messageLength = sizeof(Entity::MakeMessage); + creation_message->messageID = Entity::MakeMessageID; + creation_message->owningPlayerID = EntityID::Null; + creation_message->messageFlags = 0; + creation_message->classToCreate = RegisteredClass::TrivialEntityClassID; + creation_message->instanceFlags = 0; //DefaultFlags; + + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "X position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.x = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Y position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.y = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Z position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.z = atof(p); + + EulerAngles pyr; + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Pitch missing!\n"; + return False; + } + pyr.pitch = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Yaw missing!\n"; + return False; + } + pyr.yaw = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Roll missing!\n"; + return False; + } + pyr.roll = atof(p); + creation_message->localOrigin.angularPosition = pyr; + return True; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Entity::CreateMakeMapMessage( + MakeMapMessage *creation_message, + ResourceDescription::ResourceID resource_id, +#if DEBUG_LEVEL>0 + NotationFile *model_file, +#else + NotationFile *, +#endif + const ResourceDirectories * + ) +{ + Check(creation_message); + Check(model_file); + char *p; + + creation_message->messageLength = sizeof(Entity::MakeMapMessage); + creation_message->messageID = Entity::MakeMessageID; + creation_message->messageFlags = Entity::MakeMessage::MapStreamMarkerFlag; + + + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "X position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.x = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Y position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.y = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Z position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.z = atof(p); + + EulerAngles pyr = EulerAngles::Identity; +#if 0 + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Pitch missing!\n"; + return False; + } + pyr.pitch = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Yaw missing!\n"; + return False; + } + pyr.yaw = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + cerr << "Roll missing!\n"; + return False; + } + pyr.roll = atof(p); +#endif + + creation_message->localOrigin.angularPosition = pyr; + creation_message->resourceID = resource_id; + + return True; + +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::DestroyEntityMessageHandler(Message *) +{ + CondemnToDeathRow(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity::~Entity() +{ + // + // Notify the host manager that we are going away + // + Check(application); + application->GetHostManager()->NotifyOfEntityDestruction(this); + + // + // Delete the subsystem array + // + if (subsystemArray) + { + Check_Pointer(subsystemArray); + for (int i=0; iGetEntityManager(); + Check(entity_manager); + + // + //------------------------------------------------- + // Make sure we are not entered into deathrow twice + //------------------------------------------------- + // + if (!IsCondemned()) + { + entity_manager->deathRow->Add(this); + SetCondemnedFlag(); + NeverExecute(); + } + Check_Fpu(); +} + +//############################################################################# +// Test Support +// + +Logical + Entity::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +//########################################################################## +// Renderer Support +// +void + Entity::AddStaticVideoComponent(Component *component) +{ + Check(component); + Check(&staticVideoSocket); + staticVideoSocket.Add(component); + Check_Fpu(); +} + +void + Entity::AddDynamicVideoComponent(Component *component) +{ + Check(component); + Check(&dynamicVideoSocket); + dynamicVideoSocket.Add(component); + Check_Fpu(); +} + +void + Entity::AddAudioComponent(Component *component) +{ + Check(component); + Check(&audioSocket); + audioSocket.Add(component); + Check_Fpu(); +} + +Enumeration + Entity::GetAudioRepresentation(Entity *linked_entity) +{ + Check(this); + Check(linked_entity); + + return + (linked_entity == this) ? + InternalAudioRepresentation : ExternalAudioRepresentation; +} + +//############################################################################# +// Interest Support +// +void + Entity::BecomeInteresting() +{ + BecomeInterestingMessage + message( + Entity::BecomeInterestingMessageID, + sizeof(BecomeInterestingMessage) + ); + + Receiver::Dispatch(&message); + Check_Fpu(); +} + +void + Entity::BecomeInterestingMessageHandler() +{ + ++interestCount; + Check_Fpu(); +} + +void + Entity::BecomeUninterestingMessageHandler() +{ + --interestCount; + Check_Fpu(); +} + +Enumeration + Entity::GetInterestPriority(Entity *linked_entity) +{ + Check(this); + Check(linked_entity); + + return (linked_entity == this) ? HighInterestPriority : LowInterestPriority; +} + + + +int + Entity::GetDamageZoneIndex(const CString &damage_zone_name) const +{ + + for(int ii=0;iidamageZoneName.Compare(damage_zone_name) == 0) + { + return ii; + } + } + return -1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + Entity::CreateDamageZoneStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .dmg file + //------------------- + // + const char* dmg_file_cname; + if ( + !model_file->GetEntry( + "gamedata", + "DamageZones", + &dmg_file_cname + ) + ) + { + cerr << model_name << " is missing .dmg file specification!\n"; + return -1; + } + + CString dmg_filename = + MakePathedFilename(directories->modelDirectory, dmg_file_cname); + + NotationFile *dmg_file = new NotationFile(dmg_filename); + Register_Object(dmg_file); + int page_count = dmg_file->PageCount(); + if (!page_count) + { + cerr << dmg_filename << " is empty or missing!\n"; + Unregister_Object(dmg_file); + delete dmg_file; + return -1; + } + + DynamicMemoryStream damage_stream; + + damage_stream << page_count; + NameList *dmg_namelist = dmg_file->MakePageList(); + Register_Object(dmg_namelist); + + NameList::Entry *dmg_entry = dmg_namelist->GetFirstEntry(); + + CString dmg_page_name; + while(dmg_entry) + { + dmg_page_name = dmg_entry->GetName(); + DamageZone::CreateStreamedDamageZone( + model_file, + model_name, + NULL, + dmg_page_name, + &damage_stream, + dmg_file, + directories + ); + dmg_entry = dmg_entry->GetNextEntry(); + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Add Stream to Resource + //~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *new_res = + resource_file->AddResourceMemoryStream( + model_name, + ResourceDescription::DamageZoneStreamResourceType, + 1, + ResourceDescription::Preload, + &damage_stream + ); + Check(new_res); + + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dmg_namelist); + delete dmg_namelist; + + return new_res->resourceID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + Entity::CreateExplosionTableStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + // + //~~~~~~~~~~~~~~~~~ + // Find *.dmg file + //~~~~~~~~~~~~~~~~~ + // + const char *entry_data; + if (!model_file->GetEntry( + "gamedata", + "DamageZones", + &entry_data + ) + ) + { + DEBUG_STREAM << model_name << " is missing .dmg file specification!\n"; + return -1; + } + CString filename = + MakePathedFilename(directories->modelDirectory, entry_data); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make a notation file of the DMG Entries + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NotationFile *dmg_file = new NotationFile(filename); + Register_Object(dmg_file); + + if(dmg_file->IsEmpty()) + { + DEBUG_STREAM << model_name << " *.dmg file is empty or missing!\n"; + Unregister_Object(dmg_file); + delete dmg_file; + return -1; + } + + DynamicMemoryStream explosion_stream; + NameList *dmg_namelist = dmg_file->MakePageList(); + Register_Object(dmg_namelist); + + NameList::Entry *dmg_entry = dmg_namelist->GetFirstEntry(); + while(dmg_entry) + { + const char *entry_data; + if (dmg_file->GetEntry( + dmg_entry->GetName(), + "ExplosionTable", + &entry_data + ) + ) + { + CString filename = + MakePathedFilename(directories->modelDirectory, entry_data); + + NotationFile *exp_file = new NotationFile(filename); + Register_Object(exp_file); + + if(exp_file->IsEmpty()) + { + cerr<GetNextEntry(); + } + + ResourceDescription *new_res = + resource_file->AddResourceMemoryStream( + model_name, + ResourceDescription::ExplosionTableStreamResourceType, + 1, + ResourceDescription::Preload, + &explosion_stream + ); + Check(new_res); + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dmg_namelist); + delete dmg_namelist; + return new_res->resourceID; +} + +#if defined(TEST_CLASS) +# include "entity.tcp" +#endif diff --git a/CODE/RP/MUNGA/ENTITY.HPP b/CODE/RP/MUNGA/ENTITY.HPP new file mode 100644 index 0000000..874f829 --- /dev/null +++ b/CODE/RP/MUNGA/ENTITY.HPP @@ -0,0 +1,645 @@ +//===========================================================================// +// File: entity.hpp // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification for entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ENTITY_HPP) +# define ENTITY_HPP + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(ORIGIN_HPP) +# include +# endif + +# if !defined(LINMTRX_HPP) +# include +# endif + + class Player; + class NotationFile; + class DamageZone; + class Damage; + class Subsystem; + +# define ENTITY_CONTINUATION +# include + + //########################################################################## + //########################### Entity ################################# + //########################################################################## + + class Entity: + public Simulation + { + friend class Entity__StaticVideoSocketIterator; + friend class Entity__DynamicVideoSocketIterator; + friend class Entity__AudioSocketIterator; + friend class Entity__GaugeSocketIterator; + friend class Entity__AudioLocationIterator; + + //########################################################################## + // Shared Data support + // + public: + typedef Entity__SharedData SharedData; + SharedData* + GetSharedData(); + + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //########################################################################## + // Message Support + // + public: + enum { + MakeMessageID = Simulation::NextMessageID, + MakeReadyMessageID, + RemakeEntityMessageID, + RemakeReadyMessageID, + RemakeCompleteMessageID, + RemakeIncompleteMessageID, + DestroyEntityMessageID, + TransferEntityMessageID, + TransferCompleteMessageID, + TransferIncompleteMessageID, + BecomeInterestingMessageID, + BecomeUninterestingMessageID, + UpdateMessageID, + SubscribeReplicantMessageID, + UnsubscribeReplicantMessageID, + TakeDamageMessageID, + TakeDamageStreamMessageID, + PlayerLinkMessageID, + NextMessageID + }; + + typedef Entity__Message Message; + typedef Entity__MakeMessage MakeMessage; + typedef Entity__MakeReadyMessage MakeReadyMessage; + typedef Entity__RemakeEntityMessage RemakeEntityMessage; + typedef Entity__RemakeReadyMessage RemakeReadyMessage; + typedef Entity__RemakeCompleteMessage RemakeCompleteMessage; + typedef Entity__RemakeIncompleteMessage RemakeIncompleteMessage; + typedef Entity__DestroyEntityMessage DestroyEntityMessage; + typedef Entity__TransferEntityMessage TransferEntityMessage; + typedef Entity__TransferCompleteMessage TransferCompleteMessage; + typedef Entity__TransferIncompleteMessage TransferIncompleteMessage; + typedef Entity__BecomeInterestingMessage BecomeInterestingMessage; + typedef Entity__BecomeUninterestingMessage BecomeUninterestingMessage; + typedef Entity__UpdateMessage UpdateMessage; + typedef Entity__SubscribeReplicantMessage SubscribeReplicantMessage; + typedef Entity__UnsubscribeReplicantMessage UnsubscribeReplicantMessage; + typedef Entity__TakeDamageMessage TakeDamageMessage; + typedef Entity__TakeDamageStreamMessage TakeDamageStreamMessage; + typedef Entity__PlayerLinkMessage PlayerLinkMessage; + typedef Entity__DynamicMessage DynamicMessage; + typedef Entity__MakeMapMessage MakeMapMessage; + + + void + Receive(Event *event); + + void + LocalDispatch(Message *what) + {Receiver::Receive(Cast_Object(Receiver::Message*,what));} + + void + Dispatch(Receiver::Message *what); + + void + DispatchToReplicant( + Message *what, + HostID host + ); + + void + DispatchToReplicants(Message *what); + + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + //########################################################################## + // Attribute Support + // + public: + enum { + LocalToWorldAttributeID = Simulation::NextAttributeID, + LocalOriginAttributeID, + DamageZoneCountAttributeID, + DamageZonesAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + LinearMatrix localToWorld; + Origin localOrigin; + int damageZoneCount; + DamageZone **damageZones; + + + int + GetDamageZoneIndex(const CString &damage_zone_name) const; + + + // + // virtual access + // + public: + virtual Vector3D + GetWorldLinearVelocity() + {return Vector3D(0.0f, 0.0f, 0.0f);} + virtual Vector3D + GetWorldLinearAcceleration() + {return Vector3D(0.0f, 0.0f, 0.0f);} + + //########################################################################## + // Model Support + // + public: + UpdateMessage* + Execute(const Time &till); + + Subsystem* + GetSubsystem(int index) + { + Check(this); Verify((unsigned)index < subsystemCount); + return subsystemArray[index]; + } + Simulation* + GetSimulation(int index); + int + GetSubsystemCount() + {Check(this); return subsystemCount;} + Subsystem* + FindSubsystem(const char* name); + + typedef void + (Entity::*Performance)(Scalar time_slice); + + typedef Entity__UpdateRecord UpdateRecord; + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + enum { + EntitySubsystemID = -1 + }; + + static int + FindSubsytemID( + const char *model_name, + const char *subsystem_name + ); + public: + + enum { + DamageZoneUpdateModelBit = Simulation::NextUpdateModelBit, + NextUpdateModelBit + }; + + enum { + DamageZoneUpdateModelFlag = 1 << DamageZoneUpdateModelBit + }; + + Logical + DamageZoneUpdateModelFlagSet() + {Check(this); return (updateModel & DamageZoneUpdateModelFlag); } + + protected: + + void + WriteUpdateRecord( + Simulation::UpdateRecord *message, + int update_model + ); + void + UpdateMessageHandler(UpdateMessage *message); + + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + void + ReadDamageUpdateRecord(Simulation::UpdateRecord *update_record); + + void + WriteDamageUpdateRecord(Simulation::UpdateRecord *update_record); + + void + PerformAndWatch( + const Time &till, + MemoryStream *update_stream + ); + + int + subsystemCount; + Subsystem + **subsystemArray; + Origin + updateOrigin; + + void + TakeDamageStreamMessageHandler(TakeDamageStreamMessage *message); + void + TakeDamageMessageHandler(TakeDamageMessage *message); + void + PlayerLinkMessageHandler(PlayerLinkMessage *message); + + //########################################################################## + // Renderer Support + // + public: + void + AddStaticVideoComponent(Component *component); + void + AddDynamicVideoComponent(Component *component); + void + AddAudioComponent(Component *component); + + typedef Entity__StaticVideoSocketIterator + StaticVideoSocketIterator; + typedef Entity__DynamicVideoSocketIterator + DynamicVideoSocketIterator; + typedef Entity__AudioSocketIterator + AudioSocketIterator; + + virtual Enumeration + GetAudioRepresentation(Entity *linked_entity); + + private: + SChainOf + staticVideoSocket; + SChainOf + dynamicVideoSocket; + SChainOf + audioSocket; + + //########################################################################## + // Flag Support + // + public: + // + // MasterInstance - created on owning host, replicated on remote hosts, + // sends updates to replicants + // ReplicantInstance - created on remote hosts, receives updates from + // MasterInstance + // IndependantInstance - created on owning host, replicated on remote + // hosts, never receives updates from MasterInstance + // HermitInstance - created on owning host, is not replicated, does + // send updates + // + enum { + InstanceBits = Simulation::NextBit, + ValidBit = InstanceBits+2, + TransferableBit, + InterestBit, + InterestLockedBit, + DynamicBit, + TrappedBit, + StatueBit, + MapBit, + PreRunBit, + CondemnedBit, + NextBit + }; + enum Instance + { + MasterInstance=0, + ReplicantInstance=1<entityID = entityID; + message->interestZoneID = interestZoneID; + message->ownerID = ownerID; + } + + + +# include +# undef ENTITY_CONTINUATION + +#endif + diff --git a/CODE/RP/MUNGA/ENTITY.TCP b/CODE/RP/MUNGA/ENTITY.TCP new file mode 100644 index 0000000..40d09ea --- /dev/null +++ b/CODE/RP/MUNGA/ENTITY.TCP @@ -0,0 +1,255 @@ +//===========================================================================// +// File: entity.tst // +// Project: MUNGA Brick: Entity Manager // +// Contents: Implementation details of the entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/28/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "entity.thp" + +//############################################################################# +// Shared Data Support +// +Derivation + TestEntity::ClassDerivations(Entity::ClassDerivations,"TestEntity"); + +TestEntity::SharedData + TestEntity::DefaultData( + TestEntity::ClassDerivations, + TestEntity::MessageHandlers, + TestEntity::AttributeIndex, + 1, + (Entity::MakeHandler)TestEntity::Make + ); + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + TestEntity::MessageHandlerEntries[]= +{ + { + TestEntity::TestMessageID, + "Test", + (TestEntity::Handler)&TestEntity::TestMessageHandler + } +}; + +TestEntity::MessageHandlerSet + TestEntity::MessageHandlers( + ELEMENTS(TestEntity::MessageHandlerEntries), + TestEntity::MessageHandlerEntries, + Entity::MessageHandlers + ); + +void + TestEntity::TestMessageHandler(TestEntity::Message *) +{ + localOrigin = Point3D(2.0,2.0,2.0); +}; + +void + TestEntity::Tester() +{ + TestEntity::Message message( + TestEntity::TestMessageID, + sizeof(TestEntity::Message) + ); + Dispatch(&message); +} + +//############################################################################# +// Attribute Support +// +const TestEntity::IndexEntry + TestEntity::AttributePointers[]= +{ + { + TestEntity::VelocityVectorAttributeID, + "VelocityVector", + (Entity::AttributePointer)&TestEntity::velocityVector + } +}; + +TestEntity::AttributeIndexSet + TestEntity::AttributeIndex( + ELEMENTS(TestEntity::AttributePointers), + TestEntity::AttributePointers, + Entity::AttributeIndex + ); + +//############################################################################# +// Model Support +// +void + TestEntity::Model( + Scalar time_slice, + MemoryStream &update_stream + ) +{ + Vector3D diff; + diff.Multiply(velocityVector,time_slice); + localOrigin.linearPosition += diff; + localToWorld = localOrigin.linearPosition; + if (diff.LengthSquared() >= 0.009f) + { + UpdateRecord* update = (UpdateRecord*)update_stream.GetPointer(); + WriteUpdateRecord(update, 0); + update_stream.AdvancePointer(update->recordLength); + } +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestEntity::TestEntity( + TestEntity::MakeMessage *creation_message, + TestEntity::SharedData &virtual_data +): + Entity(creation_message,virtual_data) +{ + SetValidFlag(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestEntity* + TestEntity::Make(TestEntity::MakeMessage *creation_message) +{ + return new TestEntity(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestEntity::~TestEntity() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Entity::TestClass() +{ + DEBUG_STREAM << "Starting Entity test...\n"; + + // + //------------------ + // Test construction + //------------------ + // + TestEntity::MakeMessage + message1( + TestEntity::MakeMessageID, + sizeof(TestEntity::MakeMessage), + TestEntity::TrivialEntityClassID, + EntityID::Null, + 0, + TestEntity::DefaultFlags, + Origin::Identity + ); + TestEntity *test_entity = TestEntity::Make(&message1); + Register_Object(test_entity); + + // + //--------------- + // Test messaging + //--------------- + // + test_entity->Tester(); + Test(test_entity->localOrigin.linearPosition == Point3D(2.0f,2.0f,2.0f)); + + // + //------------------------------------------------------------ + // Try posting a message through the application to the object + //------------------------------------------------------------ + // + application->ProcessAllEvents(); + test_entity->localOrigin.linearPosition.x = 3.0f; + TestEntity::Message message2( + TestEntity::TestMessageID, + sizeof(TestEntity::Message) + ); + application->Post(0, test_entity, &message2); + application->ProcessOneEvent(); + Test(test_entity->localOrigin.linearPosition == Point3D(2.0f,2.0f,2.0f)); + + // + //------------------------------------------------ + // Try sending a timed event through to the object + //------------------------------------------------ + // + test_entity->localOrigin.linearPosition.x = 3.0f; + Time t = Now(); + t += 0.5f; + application->Post(0, test_entity, &message2, t); + Time t2 = t; + t2 += 0.1f; + while (!application->ProcessOneEvent()) + { + Test(Now() < t2); + } + Scalar f = Now() - t; + Test(test_entity->localOrigin.linearPosition == Point3D(2.0f,2.0f,2.0f)); + Test(Abs(f) < 0.06f); + + // + //------------------------ + // Test attribute pointers + //------------------------ + // + test_entity->localOrigin = Point3D(1.0f,1.0f,1.0f); + Origin *origin = + (Origin*)test_entity->GetAttributePointer(LocalOriginAttributeID); + Test(origin->linearPosition == Point3D(1.0f,1.0f,1.0f)); + + test_entity->velocityVector = Vector3D(0.0f,0.0f,1.0f); + Vector3D *velocity = + (Vector3D*)test_entity-> + GetAttributePointer(TestEntity::VelocityVectorAttributeID); + Test(*velocity == Vector3D(0.0f,0.0f,1.0f)); + + // + //--------------------- + // Test Model execution + //--------------------- + // + test_entity->Perform(0.1f); + Test(origin->linearPosition == Point3D(1.0f,1.0f,1.0f)); + test_entity->SetPerformance(&TestEntity::Model); + test_entity->Perform(0.05f); + Test(origin->linearPosition == Point3D(1.0f,1.0f,1.05f)); + + // + //------------------------------- + // Test Update message generation + //------------------------------- + // + t = test_entity->creationTime; + t += 0.1f; + UpdateMessage *update = test_entity->Execute(t); + Test(update); +// Test(update->localOrigin.linearPosition == Point3D(1.0f,1.0f,1.15f)); +// Unregister_Object(update); +// delete update; + + // + //----------------- + // Test destruction + //----------------- + // + Unregister_Object(test_entity); + delete test_entity; + + return True; +} + diff --git a/CODE/RP/MUNGA/ENTITY.THP b/CODE/RP/MUNGA/ENTITY.THP new file mode 100644 index 0000000..4708379 --- /dev/null +++ b/CODE/RP/MUNGA/ENTITY.THP @@ -0,0 +1,118 @@ +//===========================================================================// +// File: tstentty.hh // +// Project: MUNGA Brick: Entity Manager // +// Contents: class definition of test entity // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/28/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(TSTENTTY_HPP) +# define TSTENTTY_HPP + +# if !defined(ENTITY_HPP) +# include "entity.hpp" +# endif + + class TestEntity: + public Entity + { + //########################################################################## + // Shared Data Support + // + public: + SharedData* + GetSharedData() + {return (SharedData*)sharedData;} + + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //########################################################################## + // Message Support + // + public: + enum { + TestMessageID = Entity::NextMessageID, + NextMessageID + }; + + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + public: + void TestMessageHandler(Message *message); + void Tester(); + + //########################################################################## + // Attribute Support + // + public: + enum { + VelocityVectorAttributeID = Entity::NextAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + static const HandlerEntry AttributeHandlerEntries[]; + + public: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Vector3D velocityVector; + + //########################################################################## + // Model Support + // + public: + typedef void + (TestEntity::*Performance)( + Scalar time_slice, + MemoryStream &update_stream + ); + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + Model( + Scalar time_slice, + MemoryStream &update_stream + ); + + //########################################################################## + // Construction and Destruction + // + public: + static TestEntity* + Make(MakeMessage *creation_message); + + protected: + TestEntity( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + + public: + ~TestEntity(); + }; + +#endif + diff --git a/CODE/RP/MUNGA/ENTITY2.CPP b/CODE/RP/MUNGA/ENTITY2.CPP new file mode 100644 index 0000000..d660c17 --- /dev/null +++ b/CODE/RP/MUNGA/ENTITY2.CPP @@ -0,0 +1,129 @@ +//===========================================================================// +// File: entity2.cc // +// Project: MUNGA Brick: Entity Manager // +// Contents: Implementation details of the entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(HOSTMGR_HPP) +# include +#endif + +#if !defined(REGISTRY_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +//########################################################################## +//############# Entity::StaticVideoSocketIterator #################### +//########################################################################## + +Entity__StaticVideoSocketIterator::Entity__StaticVideoSocketIterator( + Entity *entity +): + SChainIteratorOf(&entity->staticVideoSocket) +{ +} + +Entity__StaticVideoSocketIterator::Entity__StaticVideoSocketIterator( + const Entity__StaticVideoSocketIterator &iterator +): + SChainIteratorOf(iterator) +{ +} + +Entity__StaticVideoSocketIterator::~Entity__StaticVideoSocketIterator() +{ +} + +//########################################################################## +//############# Entity::DynamicVideoSocketIterator ################### +//########################################################################## + +Entity__DynamicVideoSocketIterator::Entity__DynamicVideoSocketIterator( + Entity *entity +): + SChainIteratorOf(&entity->dynamicVideoSocket) +{ +} + +Entity__DynamicVideoSocketIterator::Entity__DynamicVideoSocketIterator( + const Entity__DynamicVideoSocketIterator &iterator +): + SChainIteratorOf(iterator) +{ +} + +Entity__DynamicVideoSocketIterator::~Entity__DynamicVideoSocketIterator() +{ +} + +//########################################################################## +//################ Entity::AudioSocketIterator ####################### +//########################################################################## + +Entity__AudioSocketIterator::Entity__AudioSocketIterator(Entity *entity): + SChainIteratorOf(&entity->audioSocket) +{ +} + +Entity__AudioSocketIterator::~Entity__AudioSocketIterator() +{ +} + +int + Find_Subsystem_Index( + NotationFile *file, + const char* name + ) +{ + Check(file); + Check_Pointer(name); + + NameList *namelist = file->MakePageList(); + Register_Object(namelist); + NameList::Entry *entry = namelist->GetFirstEntry(); + + int count = 0; + while (entry) + { + if (!strcmp(name, entry->GetName())) + { + Unregister_Object(namelist); + delete namelist; + return count; + } + ++count; + entry = entry->GetNextEntry(); + } + + Unregister_Object(namelist); + delete namelist; + return (!strcmp(name, "None")) ? count : -1; +} + diff --git a/CODE/RP/MUNGA/ENTITY2.HPP b/CODE/RP/MUNGA/ENTITY2.HPP new file mode 100644 index 0000000..6766f8f --- /dev/null +++ b/CODE/RP/MUNGA/ENTITY2.HPP @@ -0,0 +1,163 @@ +//===========================================================================// +// File: entity2.hh // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification for entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if defined(ENTITY_CONTINUATION) + +# if !defined(ENTITYID_HPP) +# include +# endif + + class Entity; + class Entity__SharedData; + class Entity__MakeMessage; + class Entity__TakeDamageMessage; + class Entity__PlayerLinkMessage; + class Entity__DynamicMessage; + class Entity__UpdateMessage; + class Entity__MakeMapMessage; + class Entity__TakeDamageStreamMessage; + class Entity__DestroyEntityMessage; + + class EntityID; + + // + //--------------------------------------------------- + // Support types for entity identity and host manager + //--------------------------------------------------- + // + + //########################################################################## + //####################### Entity::Message ############################ + //########################################################################## + + class Entity__Message: + public Receiver::Message + { + public: + // + // The following fields need to be filled in by the sending manager + // + enum { + DontSpoolBit = Receiver::Message::NextBit, + NextBit + }; + + enum { + DontSpoolFlag = 1 << DontSpoolBit + }; + + + // This field will be already set for map entities + EntityID + entityID; + + InterestZoneID + interestZoneID; + HostID + ownerID; + + Entity__Message( + Receiver::MessageID messageID, + size_t length + ): + Receiver::Message(messageID, length), + entityID(EntityID::Null), + interestZoneID(NullInterestZoneID), + ownerID(NullHostID) + {} + + // This constructor exists for constructing map entities + Entity__Message( + Receiver::MessageID messageID, + size_t length, + const EntityID &entity_ID + ): + Receiver::Message(messageID, length), + entityID(entity_ID), + interestZoneID(NullInterestZoneID), + ownerID(NullHostID) + {} + }; + + // + // Various typedefs for unimplemented messages + // + typedef Entity__Message Entity__MakeReadyMessage; + typedef Entity__Message Entity__RemakeEntityMessage; + typedef Entity__Message Entity__RemakeReadyMessage; + typedef Entity__Message Entity__RemakeCompleteMessage; + typedef Entity__Message Entity__RemakeIncompleteMessage; + typedef Entity__Message Entity__TransferEntityMessage; + typedef Entity__Message Entity__TransferCompleteMessage; + typedef Entity__Message Entity__TransferIncompleteMessage; + typedef Entity__Message Entity__BecomeInterestingMessage; + typedef Entity__Message Entity__BecomeUninterestingMessage; + typedef Entity__Message Entity__SubscribeReplicantMessage; + typedef Entity__Message Entity__UnsubscribeReplicantMessage; + + //########################################################################## + //############# Entity::StaticVideoSocketIterator #################### + //########################################################################## + + class Entity__StaticVideoSocketIterator: + public SChainIteratorOf + { + public: + Entity__StaticVideoSocketIterator(Entity *entity); + Entity__StaticVideoSocketIterator( + const Entity__StaticVideoSocketIterator &iterator + ); + ~Entity__StaticVideoSocketIterator(); + }; + + //########################################################################## + //############ Entity::DynamicVideoSocketIterator #################### + //########################################################################## + + class Entity__DynamicVideoSocketIterator: + public SChainIteratorOf + { + public: + Entity__DynamicVideoSocketIterator(Entity *entity); + Entity__DynamicVideoSocketIterator( + const Entity__DynamicVideoSocketIterator &iterator + ); + ~Entity__DynamicVideoSocketIterator(); + }; + + //########################################################################## + //################ Entity::AudioSocketIterator ####################### + //########################################################################## + + class Entity__AudioSocketIterator: + public SChainIteratorOf + { + public: + Entity__AudioSocketIterator(Entity *entity); + ~Entity__AudioSocketIterator(); + }; + + //########################################################################## + //#################### Entity::UpdateRecord ########################## + //########################################################################## + + struct Entity__UpdateRecord: + public Simulation__UpdateRecord + { + public: + Origin localOrigin; + }; + +#endif + diff --git a/CODE/RP/MUNGA/ENTITY3.HPP b/CODE/RP/MUNGA/ENTITY3.HPP new file mode 100644 index 0000000..3523d82 --- /dev/null +++ b/CODE/RP/MUNGA/ENTITY3.HPP @@ -0,0 +1,341 @@ +//===========================================================================// +// File: entity3.hh // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification for entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +// 12/14/95 GDU Revised TakeDamage message // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if defined(ENTITY_CONTINUATION) + + #if !defined(DAMAGE_HPP) + #include + #endif + + //########################################################################## + //#################### Entity::SharedData ########################### + //########################################################################## + + class Entity__SharedData: + public Simulation::SharedData + { + public: + Entity__SharedData( + Derivation& derivation, + Receiver::MessageHandlerSet &message_handlers, + Entity::AttributeIndexSet &attribute_index, + int state_count, + Entity::MakeHandler make_handler + ): + Simulation::SharedData( + derivation, + message_handlers, + attribute_index, + state_count + ), + makeHandler(make_handler) + {} + + Entity::MakeHandler makeHandler; + }; + + inline Entity::SharedData* + Entity::GetSharedData() + {return Cast_Object(SharedData*,sharedData);} + + //########################################################################## + //##################### Entity::MakeMessage ########################## + //########################################################################## + + class Entity__MakeMessage: + public Entity::Message + { + public: + enum { + MapStreamMarkerBit = Entity::Message::NextBit, + NextBit + }; + + enum { + MapStreamMarkerFlag = 1 << MapStreamMarkerBit + }; + + Entity::ClassID + classToCreate; + EntityID + owningPlayerID; + ResourceDescription::ResourceID + resourceID; + LWord + instanceFlags; + Origin + localOrigin; + + Entity__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin + ): + Entity::Message(message_ID, length), + classToCreate(class_ID), + owningPlayerID(owner_ID), + resourceID(resource_ID), + instanceFlags(instance_flags), + localOrigin(origin) + {} + Entity__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin + ): + Entity::Message(message_ID, length, entity_ID), + classToCreate(class_ID), + owningPlayerID(owner_ID), + resourceID(resource_ID), + instanceFlags(instance_flags), + localOrigin(origin) + {} + }; + + //########################################################################## + //#################### Entity::UpdateMessage ######################### + //########################################################################## + + class Entity__UpdateMessage: + public Entity::Message + { + public: + Entity__UpdateMessage( + Receiver::MessageID message_ID, + size_t length + ): + Entity::Message(message_ID, length) + {messageFlags &= ~ReliableFlag;} + }; + + //########################################################################## + //################## Entity::TakeDamageMessage ####################### + //########################################################################## + + class Entity__TakeDamageMessage: + public Entity::Message + { + public: + EntityID + inflictingEntity; + + // WARNING: + // Since the current collision system cannot resolve the damage zone of + // entities with multiple damage zones, specializations of Entity's + // TakeDamage message handler are responsible for handling an invalid zone. + // Mechs use cylinder lookup table. + // For BattleTech, damage zones are only valid via reticle based weapons. + // Due to existing RP implementation, damageZone is not an optional + // arg to the constructor. + + int + damageZone; + Logical invalidDamageZone; + + Damage + damageData; + + + // NOTE: + // BattleTech's message manager needs to know the subsystemID of the + // inflicting weapon in order to bundle explosion resource IDs. + + int inflictingSubsystemID; + Logical invalidSubsystem; + + Entity__TakeDamageMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + int damage_zone, + Damage &damage + ): + Entity::Message(message_ID, length), + inflictingEntity(entity_ID), + damageZone(damage_zone), + damageData(damage), + invalidDamageZone(damageZone<0), + inflictingSubsystemID(-1), + invalidSubsystem(inflictingSubsystemID<0) + + { } + + Entity__TakeDamageMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + int damage_zone, + Damage &damage, + int inflicting_subsystem_ID + ): + Entity::Message(message_ID, length), + inflictingEntity(entity_ID), + damageZone(damage_zone), + damageData(damage), + invalidDamageZone(damageZone<0), + inflictingSubsystemID(inflicting_subsystem_ID), + invalidSubsystem(inflictingSubsystemID<0) + { } + }; + + //########################################################################## + //############### Entity::TakeDamageStreamMessage ##################### + //########################################################################## + + class Entity__TakeDamageStreamMessage : + public Entity::Message + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Holds A Group Of Damage Messages with some Common Fields + // used for instantaneous hit weapons + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + public: + Point3D + impactPoint; + int + damageZoneIndex; + EntityID + shootingEntity; + + Entity__TakeDamageStreamMessage( + Entity::MessageID message_ID, + size_t message_size, + const EntityID &shooting_entity, + int damage_zone_index, + const Point3D &impact_point + ): + Entity::Message(message_ID, message_size), + shootingEntity(shooting_entity), + damageZoneIndex(damage_zone_index), + impactPoint(impact_point) + {} + + ~Entity__TakeDamageStreamMessage() + {} + }; + + //########################################################################## + //################## Entity::PlayerLinkMessage ####################### + //########################################################################## + + + class Entity__PlayerLinkMessage: + public Entity::Message + { + public: + EntityID + playerID; + + Entity__PlayerLinkMessage( + Receiver::MessageID message_ID, + size_t length, + EntityID player_id + ): + Entity::Message(message_ID, length) + {playerID = player_id;} + }; + // Tool support function + + extern int + Find_Subsystem_Index( + NotationFile *file, + const char* name + ); + + //########################################################################## + //################## Entity::PlayerLinkMessage ####################### + //########################################################################## + + class Entity__DestroyEntityMessage: + public Entity::Message + { + public: + Entity__DestroyEntityMessage( + Receiver::MessageID message_ID, + size_t length + ): + Entity::Message(message_ID, length) + {} + }; + + //########################################################################## + //################# Entity::DynamicMessage ########################### + //########################################################################## + + class Entity__DynamicMessage : + public Receiver::DynamicMessage + { + public: + Entity__DynamicMessage() + { } + + Entity__DynamicMessage( + Entity::MessageID message_ID, + size_t message_size = sizeof(Entity::Message) + ) : Receiver::DynamicMessage(message_ID, message_size) + { } + + Entity__DynamicMessage( + void *message_ptr, + size_t stream_size, + size_t initial_offset = sizeof(Entity::Message) + ) : Receiver::DynamicMessage(message_ptr, stream_size, initial_offset) + { } + + ~Entity__DynamicMessage() + { } + + }; + + + + //########################################################################## + //####################### Entity::MakeMapMessage ##################### + //########################################################################## + + class Entity__MakeMapMessage: + public Receiver::Message + { + public: + // + // The following fields need to be filled in by the sending manager + // + + ResourceDescription::ResourceID + resourceID; + Origin + localOrigin; + + Entity__MakeMapMessage( + Receiver::MessageID messageID, + size_t length + ): + Receiver::Message(messageID, length) + {} + }; + +#endif + diff --git a/CODE/RP/MUNGA/ENTITYID.CPP b/CODE/RP/MUNGA/ENTITYID.CPP new file mode 100644 index 0000000..33c50a8 --- /dev/null +++ b/CODE/RP/MUNGA/ENTITYID.CPP @@ -0,0 +1,226 @@ +//===========================================================================// +// File: entity2.cc // +// Project: MUNGA Brick: Entity Manager // +// Contents: Implementation details of the entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(ENTITYID_HPP) +# include +#endif + +//############################################################################# +//############################# EntityID ################################ +//############################################################################# + +EntityID + EntityID::Null; + +EntityID::LocalID + EntityID::LocalNull = 0; + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile EntityID *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID(): + hostID(NullHostID), + localID(LocalNull) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID(const EntityID &entityID): + hostID(entityID.hostID), + localID(entityID.localID) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID(HostID hostID) +{ + this->hostID = hostID; + this->localID = LocalNull; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID( + HostID hostID, + LocalID localID +) +{ + this->hostID = hostID; + this->localID = localID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator=(const EntityID &entityID) +{ + hostID = entityID.hostID; + localID = entityID.localID; + + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator+=(const EntityID &entityID) +{ + Check(this); + Check(&entityID); + + hostID += entityID.hostID; + localID += entityID.localID; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID + EntityID::operator-(const EntityID &entityID) const +{ + Check(this); + Check(&entityID); + + return EntityID( + (HostID)(hostID - entityID.hostID), + (HostID)(localID - entityID.localID) + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator-=(const EntityID &entityID) +{ + Check(this); + Check(&entityID); + + hostID -= entityID.hostID; + localID -= entityID.localID; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator+=(LocalID i) +{ + Check(this); + + localID += i; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator-=(LocalID i) +{ + Check(this); + + localID -= i; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator<(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID < entityID.localID) : + (hostID < entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator<=(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID <= entityID.localID) : + (hostID < entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator>(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID > entityID.localID) : + (hostID > entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator>=(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID >= entityID.localID) : + (hostID > entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator==(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID && + localID == entityID.localID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator!=(const EntityID &entityID) const +{ + return + (hostID != entityID.hostID || + localID != entityID.localID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::operator int() const +{ + return int(localID); +} + diff --git a/CODE/RP/MUNGA/ENTITYID.HPP b/CODE/RP/MUNGA/ENTITYID.HPP new file mode 100644 index 0000000..144f57d --- /dev/null +++ b/CODE/RP/MUNGA/ENTITYID.HPP @@ -0,0 +1,101 @@ +//===========================================================================// +// File: entity2.hh // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification for entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ENTITYID_HPP) + #define ENTITYID_HPP + + #if !defined(NETWORK_HPP) + #include + #endif + + //########################################################################## + //########################## EntityID ################################ + //########################################################################## + + class EntityID + { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile EntityID *); + #endif + + typedef Enumeration LocalID; + + EntityID(); + EntityID(const EntityID&); + EntityID(HostID); + EntityID(HostID, LocalID); + + Logical + TestInstance() const; + HostID + GetHostID() + {return hostID;} + + Logical + operator!() const + {Check(this); return operator==(Null);} + EntityID& + operator=(const EntityID&); + + EntityID + operator-(const EntityID&) const; + + EntityID& + operator+=(const EntityID&); + EntityID& + operator-=(const EntityID&); + + EntityID& + operator+=(LocalID); + EntityID& + operator-=(LocalID); + + Logical + operator<(const EntityID&) const; + Logical + operator<=(const EntityID&) const; + Logical + operator>(const EntityID&) const; + Logical + operator>=(const EntityID&) const; + Logical + operator==(const EntityID&) const; + Logical + operator!=(const EntityID&) const; + + operator int() const; + + static EntityID + Null; + static LocalID + LocalNull; + + friend ostream& + operator<<( + ostream& stream, + const EntityID& v + ) + {return stream << v.hostID << ':' << v.localID;} + + private: + HostID + hostID; + LocalID + localID; + }; + +#endif + diff --git a/CODE/RP/MUNGA/ENVIRNMT.CPP b/CODE/RP/MUNGA/ENVIRNMT.CPP new file mode 100644 index 0000000..84cac83 --- /dev/null +++ b/CODE/RP/MUNGA/ENVIRNMT.CPP @@ -0,0 +1,125 @@ +//===========================================================================// +// File: envirnmt.cc // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for environment variables // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/13/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(ENVIRNMT_HPP) +# include +#endif + +#if !defined(CSTR_HPP) + #include +#endif + +//############################################################################# +//########################### Environment ############################### +//############################################################################# + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const Environment *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Environment::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Environment functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Convert_From_Ascii( + const char *str, + Environment *environment + ) +{ + Check_Pointer(str); + Check_Signature(environment); + + CString parse_string(str); + Check(&parse_string); + + Check_Pointer(parse_string.GetNthToken(0)); + environment->gravityConstant = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + environment->airDensity = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + environment->audioReverbTime = atof(parse_string.GetNthToken(2)); + + Check_Pointer(parse_string.GetNthToken(3)); + environment->audioAverageSurfaceReflectivity = atof(parse_string.GetNthToken(3)); + + Check_Pointer(parse_string.GetNthToken(4)); + environment->audioAirAbsorption = atof(parse_string.GetNthToken(4)); + + Check_Pointer(parse_string.GetNthToken(5)); + environment->windVelocity.x = atof(parse_string.GetNthToken(5)); + + Check_Pointer(parse_string.GetNthToken(6)); + environment->windVelocity.y = atof(parse_string.GetNthToken(6)); + + Check_Pointer(parse_string.GetNthToken(7)); + environment->windVelocity.z = atof(parse_string.GetNthToken(7)); + + Check_Pointer(parse_string.GetNthToken(8)); + environment->ambientTemperature = atof(parse_string.GetNthToken(8)); + + Check(environment); +} + +//############################################################################# +//######################### EnvironmentList ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EnvironmentList::EnvironmentList(int environments) +{ + Verify(environments > 0); + + environmentCount = environments; + environmentArray = new Environment[environments]; + Register_Pointer(environmentArray); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EnvironmentList::~EnvironmentList() +{ + Unregister_Pointer(environmentArray); + delete[] environmentArray; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EnvironmentList::TestInstance() const +{ + return True; +} + +EnvironmentList *Environments; + + diff --git a/CODE/RP/MUNGA/ENVIRNMT.HPP b/CODE/RP/MUNGA/ENVIRNMT.HPP new file mode 100644 index 0000000..e87137b --- /dev/null +++ b/CODE/RP/MUNGA/ENVIRNMT.HPP @@ -0,0 +1,131 @@ +//===========================================================================// +// File: envirnmt.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for environment variables // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/13/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ENVIRNMT_HPP) +# define ENVIRNMT_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(VECTOR3D_HPP) +# include +# endif + + //########################################################################## + //######################## Environment ############################### + //########################################################################## + + class Environment + { + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const Environment *p); + #endif + + public: + Scalar + gravityConstant, + airDensity, + audioReverbTime, + audioAverageSurfaceReflectivity, + audioAirAbsorption; + Vector3D + windVelocity; + Scalar + ambientTemperature; // Kelvin + + const Vector3D& + GetWindVelocity() + {return windVelocity;} + + Environment() + {} + Environment( + Scalar gravity, + Scalar air_density, + Scalar reverb_time, + Scalar surface_reflectivity, + Scalar air_absorption, + const Vector3D &wind_velocity, + Scalar ambient_temperature + ): + gravityConstant(gravity), + airDensity(air_density), + audioReverbTime(reverb_time), + audioAverageSurfaceReflectivity(surface_reflectivity), + audioAirAbsorption(air_absorption), + windVelocity(wind_velocity), + ambientTemperature(ambient_temperature) + {} + + Logical + TestInstance() const; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ Environment functions ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + Environment *environment + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + Environment *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const Environment *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + //########################################################################## + //###################### EnvironmentList ############################# + //########################################################################## + + class EnvironmentList SIGNATURED + { + protected: + int + environmentCount; + + Environment + *environmentArray; + + public: + EnvironmentList(int environments); + virtual ~EnvironmentList(); + + int + GetEnvironmentCount() + {Check(this); return environmentCount;} + virtual Environment& + GetEnvironment(int index) + { + Check (this); Verify((unsigned)index < environmentCount); + return environmentArray[index]; + } + + Logical + TestInstance() const; + }; + + extern EnvironmentList *Environments; + +#endif diff --git a/CODE/RP/MUNGA/EVENT.CPP b/CODE/RP/MUNGA/EVENT.CPP new file mode 100644 index 0000000..59ff38f --- /dev/null +++ b/CODE/RP/MUNGA/EVENT.CPP @@ -0,0 +1,1110 @@ +//===========================================================================// +// File: event.cc // +// Project: MUNGA Brick: Event Manager // +// Contents: implementation details of event processing // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 11/30/94 JMA Adapted to new style conventions // +// 12/01/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(EVENT_HPP) + #include +#endif + +#if !defined(REGISTRY_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +#if !defined(EVTSTAT_HPP) + #include +#endif + +#if defined(TRACE_PROCESS_EVENT) + static BitTrace Process_Event("Process Event"); +# define SET_PROCESS_EVENT() Process_Event.Set() +# define CLEAR_PROCESS_EVENT() Process_Event.Clear() +#else +# define SET_PROCESS_EVENT() +# define CLEAR_PROCESS_EVENT() +#endif + +//############################################################################# +//########################### AbstractEvent ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AbstractEvent::AbstractEvent( + Receiver::Message *message, + Time time, + ClassID class_id +): + Node(class_id) +{ + Verify(message); + alarmTime = time; + + // + //-------------------------------------------------------- + // Allocate some memory to store the message parameters in + //-------------------------------------------------------- + // + size_t long_size = (message->messageLength+3)>>2; + messageToSend = (Receiver::Message*)new long[long_size]; + Check_Pointer(messageToSend); + Register_Pointer(messageToSend); + + Mem_Copy( + messageToSend, + message, + message->messageLength, + long_size*sizeof(long) + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AbstractEvent::~AbstractEvent() +{ + if (messageToSend) + { + Unregister_Pointer(messageToSend); + delete messageToSend; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + AbstractEvent::Process() +{ + Fail("AbstractEvent::Process should not be called!\n"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + AbstractEvent::DumpData() +{ + Fail("AbstractEvent::DumpData should not be called!\n"); +} + +//############################################################################# +//############################### Event ################################# +//############################################################################# + +MemoryBlock + Event::AllocatedMemory(sizeof(Event), 20, 10, "Events"); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Event::Event( + Receiver *target, + Receiver::Message *message, + Time time +): + AbstractEvent(message, time, EventClassID), + targetReceiver(this) +{ + targetReceiver.Add(target); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Event::~Event() +{ +#if defined(TRACE_EVENT_COUNT) + // + //------------------------------------------- + // Delete the link to the current event queue + //------------------------------------------- + // + PlugIteratorOf + old_queue_link(this); + Node *node; + while ((node = old_queue_link.GetCurrent()) != NULL) + { + Check(node); + if ( + node->GetClassID() == EventQueueClassID + || node->GetClassID() == GeneralEventQueueClassID + ) + { + GeneralEventQueue *q = Cast_Object(GeneralEventQueue*, node); + while (q->priorityLevels < 0) + { + --q; + Check(q); + } + --q->eventCount; + if (q->eventCountTrace) + { + Check(q->eventCountTrace); + q->eventCountTrace->TakeSnapshot(q->eventCount); + } + break; + } + } +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::Repost( + EventQueue* queue, + int priority, + Time new_time + ) +{ + Check(this); + Check(queue); + + // + //------------------------------------------- + // Delete the link to the current event queue + //------------------------------------------- + // + PlugIteratorOf + old_queue_link(this); + Node *node; + while ((node = old_queue_link.GetCurrent()) != NULL) + { + Check(node); + if ( + node->GetClassID() == EventQueueClassID + || node->GetClassID() == GeneralEventQueueClassID + || node->GetClassID() == DeferredEventQueueClassID + ) + { + #if defined(TRACE_EVENT_COUNT) + if (node->GetClassID() != DeferredEventQueueClassID) + { + GeneralEventQueue *q = Cast_Object(GeneralEventQueue*, node); + while (q->priorityLevels < 0) + { + --q; + Check(q); + } + --q->eventCount; + if (q->eventCountTrace) + { + Check(q->eventCountTrace); + q->eventCountTrace->TakeSnapshot(q->eventCount); + } + } + #endif + + old_queue_link.Remove(); + break; + } + else + { + old_queue_link.Next(); + } + } + + // + //----------------------------------------------------------------------- + // Now, if necessary, reset the time and stuff the event in the new event + // queue + //----------------------------------------------------------------------- + // + if (new_time.ticks) + { + alarmTime = new_time; + } + queue->Enqueue(priority,this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::Defer() +{ + // + //----------------------------------------------- + // See if the target has a deferred queue already + //----------------------------------------------- + // + Receiver *target = targetReceiver.GetCurrent(); + Check(target); + PlugIteratorOf + blind_links(target); + DeferredEventQueue + *deferred_queue; + while ((deferred_queue = blind_links.ReadAndNext()) != NULL) + { + if (deferred_queue->GetClassID() == DeferredEventQueueClassID) + { + break; + } + } + + // + //---------------------------------------------------------------------- + // If we couldn't find a deferred queue, then a new one must be created + // and attached to the object + //---------------------------------------------------------------------- + // + if (!deferred_queue) + { + deferred_queue = new DeferredEventQueue(target); + Register_Object(deferred_queue); + } + + // + //------------------------------------------------- + // Now, simply repost the event to this event queue + //------------------------------------------------- + // + Repost(deferred_queue->deferredEvents,0); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::Process() +{ + Check(this); + targetReceiver.GetCurrent()->Receive(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::DumpData() +{ + Check(this); + + Receiver *target = targetReceiver.GetCurrent(); + Check(target); + Check(application); + Registry *registry = application->GetRegistry(); + if (registry) + { + Check(registry); + Receiver::SharedData *shared_data = + registry->GetStaticData(target->GetClassID()); + if (shared_data) + { + Check(shared_data); + Derivation *derivation = shared_data->derivedClasses; + Check(derivation); + Receiver::MessageHandlerSet *handlers = + shared_data->activeMessageHandlers; + Check(handlers); + DEBUG_STREAM << handlers->GetName(messageToSend->messageID) + << " message for class " << derivation->className << endl; + } + else + { + goto Vanilla_Message; + } + } + else + { +Vanilla_Message: + DEBUG_STREAM << "Message " << messageToSend->messageID + << " for object of classID " << target->GetClassID() << endl; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::ReleaseLinkHandler( + Socket*, + Plug* + ) +{ + Unregister_Object(this); + delete this; +} + +//############################################################################# +//########################### NetworkEvent ############################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkEvent::NetworkEvent( + HostID host_ID, + NetworkManager::ClientID client_ID, + EventStyle event_style, + Receiver::Message *message, + Time time +): + AbstractEvent(message, time, NetworkEventClassID) +{ + hostID = host_ID; + clientID = client_ID; + eventStyle = event_style; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkEvent::~NetworkEvent() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NetworkEvent::Process() +{ + Check(this); + switch (eventStyle) + { + case SendStyle: + Check(application); + application->GetNetworkManager()->Send( + messageToSend, + clientID, + hostID + ); + break; + + case BroadcastStyle: + Check(application); + application->GetNetworkManager()->Broadcast( + messageToSend, + clientID + ); + break; + + case ExclusiveBroadcastStyle: + Check(application); + application->GetNetworkManager()->ExclusiveBroadcast( + messageToSend, + clientID + ); + break; + } + + Unregister_Object(this); + delete this; +} + +//############################################################################# +//####################### GeneralEventQueue ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue::GeneralEventQueue(ClassID class_ID): + Node(class_ID), + pendingEvents(this), + timedEvents(this) +{ + priorityLevels = -1; + eventCount = 0; + #if defined(TRACE_EVENT_COUNT) + eventCountTrace = NULL; + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue::GeneralEventQueue(): + Node(GeneralEventQueueClassID), + pendingEvents(this), + timedEvents(this) +{ + priorityLevels = -1; + eventCount = 0; + #if defined(TRACE_EVENT_COUNT) + eventCountTrace = NULL; + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue::~GeneralEventQueue() +{ + #if defined(TRACE_EVENT_COUNT) + if (eventCountTrace) + { + Unregister_Object(eventCountTrace); + delete eventCountTrace; + } + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue* + GeneralEventQueue::Make( + int priorities, + #if defined(TRACE_EVENT_COUNT) + const char* trace_name + #else + const char* + #endif + ) +{ + GeneralEventQueue *queue = new GeneralEventQueue[priorities]; + Register_Object(queue); + + queue->priorityLevels = priorities; + #if defined(TRACE_EVENT_COUNT) + if (trace_name) + { + Check_Pointer(trace_name); + queue->eventCountTrace = + new TraceOf( + trace_name, + 0, + Trace::IntegerType, + TraceSample::IntegerSnapshot + ); + Register_Object(queue->eventCountTrace); + } + #endif + return queue; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::Post( + int priority, + Receiver *target, + Receiver::Message *message, + Time time + ) +{ + Check(this); + Check(target); + Check(message); + + // + //------------------------------------------------------------------------ + // Create a new event, then insert it at the end of the event queue. This + // means that timed events get put in sort of haphazardly!!!! + //------------------------------------------------------------------------ + // + Event *event = new Event(target, message, time); + Register_Object(event); + + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::SendEvent( + int priority, + HostID host_ID, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when + ) +{ + Check(this); + Check(message); + + NetworkEvent *event = + new NetworkEvent( + host_ID, client_id, NetworkEvent::SendStyle, message, when + ); + Register_Object(event); + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::BroadcastEvent( + int priority, + NetworkManager::ClientID client_ID, + Receiver::Message *message, + Time when + ) +{ + Check(this); + Check(message); + + // + // HACK - What is a null network address? + // + NetworkEvent *event = + new NetworkEvent( + (NetworkAddress)0, + client_ID, + NetworkEvent::BroadcastStyle, + message, + when + ); + Register_Object(event); + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::ExclusiveBroadcastEvent( + int priority, + NetworkManager::ClientID client_ID, + Receiver::Message *message, + Time when + ) +{ + Check(this); + Check(message); + + // + // HACK - What is a null network address? + // + NetworkEvent *event = + new NetworkEvent( + (NetworkAddress)0, + client_ID, + NetworkEvent::ExclusiveBroadcastStyle, + message, + when + ); + Register_Object(event); + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::Enqueue( + int priority, + AbstractEvent *event + ) +{ + Check(event); + Verify((unsigned)priority < priorityLevels); + + // + //------------------------------------------------------------ + // If this is not a timed event, stuff it in the pending queue + //------------------------------------------------------------ + // + if (!event->alarmTime.ticks) + { + this[priority].pendingEvents.Add(event); + } + + // + //---------------------------------------- + // Otherwise, sort it into the timed queue + //---------------------------------------- + // + else + { + ChainIteratorOf + timed_events(this[priority].timedEvents); + timed_events.Last(); + AbstractEvent* next_event = timed_events.GetCurrent(); + + // + //--------------------------------------------------------------------- + // If the timed queue is empty, or if we are later than the last entry, + // just add the event to the end + //--------------------------------------------------------------------- + // + if (!next_event || next_event->alarmTime.ticks <= event->alarmTime.ticks) + { + this[priority].timedEvents.Add(event); + } + + // + //-------------------------------------------------------------------- + // Find the event to insert before. If we run off the beginning, stop + // checking and set the iterator to the first event in the queue + //-------------------------------------------------------------------- + // + else + { + do + { + timed_events.Previous(); + next_event = timed_events.GetCurrent(); + if (!next_event) + { + timed_events.First(); + break; + } + } while (next_event->alarmTime.ticks > event->alarmTime.ticks); + + // + //-------------------------------------------------------------------- + // If we didn't run off the queue, we need to insert after the current + // event, so bump the iterator forward one event + //-------------------------------------------------------------------- + // + if (next_event) + { + timed_events.Next(); + } + + // + //------------------------------------------------------------------ + // Insert the new event ahead of where the iterator currently points + //------------------------------------------------------------------ + // + timed_events.Insert(event); + } + } + #if defined(TRACE_EVENT_COUNT) + ++eventCount; + if (eventCountTrace) + { + Check(eventCountTrace); + eventCountTrace->TakeSnapshot(eventCount); + } + #endif + #if defined(USE_EVENT_STATISTICS) + event_statistics_manager.Maintain(Cast_Object(Event*, event)); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AbstractEvent* + GeneralEventQueue::PeekAtNextEvent(int min_priority) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Start at the top of the priority queue, searching backwards until we find + // an available event or run off the minimum queue priority + //-------------------------------------------------------------------------- + // + Verify(min_priority >= 0); + int priority = priorityLevels; + while (--priority >= min_priority) + { + // + //------------------------------------------------------------------- + // See if the first event in the timed queue is ready to go. If not, + // none of the other timed events will be ready to go either + //------------------------------------------------------------------- + // + ChainIteratorOf + timed_events(this[priority].timedEvents); + AbstractEvent + *event = timed_events.GetCurrent(); + if (event) + { + Check(event); + if (event->alarmTime.ticks <= Now().ticks) + { + return event; + } + } + + // + //------------------------------ + // Now look in the untimed queue + //------------------------------ + // + ChainIteratorOf + events(this[priority].pendingEvents); + event = events.GetCurrent(); + if (event) + { + Check(event); + return event; + } + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + GeneralEventQueue::IsPriorityEmpty(int priority) +{ + Check(this); + + Verify(priority >= 0 && priority < priorityLevels); + ChainIteratorOf i(this[priority].pendingEvents); + ChainIteratorOf j(this[priority].timedEvents); + return !i.GetCurrent() && !j.GetCurrent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + GeneralEventQueue::ProcessOneEvent(int min_priority) +{ + Check(this); + Verify(min_priority >= 0); + + AbstractEvent *event=PeekAtNextEvent(min_priority); + if (event) + { + SET_PROCESS_EVENT(); + event->Process(); + CLEAR_PROCESS_EVENT(); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::ProcessAllEvents(int min_priority) +{ + Check(this); + Verify(min_priority >= 0); + while (ProcessOneEvent(min_priority)); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::FlushAllEvents(int max_priority) +{ + Check(this); + Verify(max_priority < priorityLevels); + + // + //----------------------------------------- + // Make sure that max_priority is set right + //----------------------------------------- + // + if (max_priority < 0) + { + max_priority = priorityLevels - 1; + } + + // + //--------------------------------------------------------------------- + // Step through each of the priority queues and delete any events found + // within + //--------------------------------------------------------------------- + // + for (int priority=max_priority; priority>=0; --priority) + { + + // + //--------------------------------------- + // Delete the events from the timed queue + //--------------------------------------- + // + ChainIteratorOf i(this[priority].timedEvents); + AbstractEvent *event; + while ((event = i.ReadAndNext()) != NULL) + { + Unregister_Object(event); + delete event; + } + + // + //----------------------------------------- + // Delete the events from the regular queue + //----------------------------------------- + // + ChainIteratorOf j(this[priority].pendingEvents); + while ((event = j.ReadAndNext()) != NULL) + { + Unregister_Object(event); + delete event; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::FlushMatchingEvents( + Receiver::MessageID target_message, + int max_priority + ) +{ + Check(this); + Verify(max_priority < priorityLevels); + + // + //----------------------------------------- + // Make sure that max_priority is set right + //----------------------------------------- + // + if (max_priority < 0) + { + max_priority = priorityLevels - 1; + } + + // + //--------------------------------------------------------------------- + // Step through each of the priority queues and delete any events found + // within + //--------------------------------------------------------------------- + // + for (int p=max_priority; p>=0; --p) + { + // + //------------------------------------------- + // Delete events from the regular queue first + //------------------------------------------- + // + ChainIteratorOf i(this[p].pendingEvents); + AbstractEvent *event; + while ((event = i.ReadAndNext()) != NULL) + { + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + target_message == Receiver::AnyMessageID + || target_message == event->messageToSend->messageID + ) + { + Unregister_Object(event); + delete event; + } + } + + // + //----------------------------------- + // Delete events from the timed queue + //----------------------------------- + // + ChainIteratorOf j(this[p].timedEvents); + while ((event = j.ReadAndNext()) != NULL) + { + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + target_message == Receiver::AnyMessageID + || target_message == event->messageToSend->messageID + ) + { + Unregister_Object(event); + delete event; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::DumpEventQueue() +{ + Check(this); + + // + //---------------------------------------------------------------------- + // Step through each of the priority queues and display any events found + // within + //---------------------------------------------------------------------- + // + CollectionSize total_count = 0; + for (int priority=priorityLevels - 1; priority>=0; --priority) + { + DEBUG_STREAM << "EventQueue priority " << priority + << "\n--------------------------------------------------------------\n"; + + ChainIteratorOf i(this[priority].pendingEvents); + AbstractEvent *event; + size_t count=0; + while ((event = i.ReadAndNext()) != NULL) + { + ++count; + event->DumpData(); + } + DEBUG_STREAM << count << " priority " << priority << " events\n\n"; + count = 0; + ChainIteratorOf j(this[priority].timedEvents); + while ((event = j.ReadAndNext()) != NULL) + { + ++count; + event->DumpData(); + } + DEBUG_STREAM << count << " priority " << priority << " timed events\n\n"; + total_count += count; + + } + DEBUG_STREAM << total_count << " total events in queues\n\n"; +} + +//############################################################################# +//############################ EventQueue ############################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EventQueue::EventQueue(): + GeneralEventQueue(EventQueueClassID) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EventQueue::~EventQueue() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EventQueue* + EventQueue::Make( + int priorities, + #if defined(TRACE_EVENT_COUNT) + const char* trace_name + #else + const char* + #endif + ) +{ + EventQueue *queue = new EventQueue[priorities]; + Register_Object(queue); + + queue->priorityLevels = priorities; + #if defined(TRACE_EVENT_COUNT) + if (trace_name) + { + Check_Pointer(trace_name); + queue->eventCountTrace = + new TraceOf( + trace_name, + 0, + Trace::IntegerType, + TraceSample::IntegerSnapshot + ); + Register_Object(queue->eventCountTrace); + } + #endif + return queue; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EventQueue::ProcessMatchingEvents( + Receiver *receiver, + Receiver::MessageID message_ID + ) +{ + Check(this); + Check(receiver); + + // + //---------------------------------------------------------------- + // Step through each of the priority queues and process any events + // found within + //---------------------------------------------------------------- + // + for (int p=priorityLevels-1; p>=0; --p) + { + Event *event; + AbstractEvent *abstract_event; + ChainIteratorOf i(this[p].pendingEvents); + while ((abstract_event = i.ReadAndNext()) != NULL) + { + Check(abstract_event); + event = Cast_Object(Event*, abstract_event); + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + (event->targetReceiver.GetCurrent() == receiver) && + (message_ID == Receiver::AnyMessageID || + message_ID == event->messageToSend->messageID) + ) + { + event->Process(); + } + } + + ChainIteratorOf j(this[p].timedEvents); + while ((abstract_event = j.ReadAndNext()) != NULL) + { + Check(abstract_event); + event = Cast_Object(Event*, abstract_event); + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + (event->targetReceiver.GetCurrent() == receiver) && + (message_ID == Receiver::AnyMessageID || + message_ID == event->messageToSend->messageID) + ) + { + event->Process(); + } + } + } +} + +//############################################################################# +//######################## DeferredEventQueue ########################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DeferredEventQueue::DeferredEventQueue(Receiver* target): + Node(DeferredEventQueueClassID), + waitingReceiver(this) +{ + deferredEvents = new EventQueue; + Register_Object(deferredEvents); + + waitingReceiver.Add(target); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DeferredEventQueue::~DeferredEventQueue() +{ + Unregister_Object(deferredEvents); + delete deferredEvents; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DeferredEventQueue::ReleaseLinkHandler( + Socket*, + Plug* + ) +{ + Unregister_Object(this); + delete this; +} + +#if defined(TEST_CLASS) +# include "event.tcp" +#endif + diff --git a/CODE/RP/MUNGA/EVENT.HPP b/CODE/RP/MUNGA/EVENT.HPP new file mode 100644 index 0000000..3150b8c --- /dev/null +++ b/CODE/RP/MUNGA/EVENT.HPP @@ -0,0 +1,375 @@ +//===========================================================================// +// File: event.hh // +// Project: MUNGA Brick: Event Manager // +// Contents: interface specification of event manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 11/30/94 JMA Adapted to new style conventions // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(EVENT_HPP) +# define EVENT_HPP + +# if !defined(TIME_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(NETWORK_HPP) +# include +# endif + + class GeneralEventQueue; + class EventQueue; + class DeferredEventQueue; + class Entity; + + //########################################################################## + //######################## AbstractEvent ############################# + //########################################################################## + + class AbstractEvent: + public Node + { + friend class GeneralEventQueue; + friend class EventStatisticsManager; + + //########################################################################## + // Event Functionality + // + protected: + AbstractEvent( + Receiver::Message *message, + Time time, + ClassID class_id + ); + ~AbstractEvent(); + + public: + virtual void + Process(); + virtual void + DumpData(); + + protected: + Time alarmTime; + Receiver::Message* messageToSend; + }; + + //########################################################################## + //############################ Event ################################# + //########################################################################## + + class Event: + public AbstractEvent + { + friend class GeneralEventQueue; + friend class EventQueue; + friend class Receiver; + friend class DeferredEventQueue; + friend class Entity; + friend class EventStatisticsManager; + + //########################################################################## + // Node Support + // + private: + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + + //########################################################################## + // Memory Allocation Support + // + private: + static MemoryBlock AllocatedMemory; + + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + + + //########################################################################## + // Event Functionality + // + private: + Event( + Receiver *target, + Receiver::Message *message, + Time time + ); + ~Event(); + + public: + void + Repost( + EventQueue *queue, + int priority, + Time new_time=Time::Null + ); + + void + Defer(); + + void + Process(); + void + DumpData(); + + private: + SlotOf targetReceiver; + }; + + //########################################################################## + //######################## NetworkEvent ############################## + //########################################################################## + + class NetworkEvent: + public AbstractEvent + { + friend class GeneralEventQueue; + + //########################################################################## + // Event Functionality + // + private: + enum EventStyle + { + SendStyle, + BroadcastStyle, + ExclusiveBroadcastStyle + }; + + NetworkEvent( + HostID hostID, + NetworkManager::ClientID client_ID, + EventStyle event_style, + Receiver::Message *message, + Time time + ); + ~NetworkEvent(); + + public: + void + Process(); + + private: + HostID + hostID; + NetworkManager::ClientID + clientID; + EventStyle + eventStyle; + }; + + //########################################################################## + //#################### GeneralEventQueue ############################ + //########################################################################## + // + // NOTE: Do not create any static event queues! new must be used to allocate + // all event queue objects + // + class GeneralEventQueue: + public Node + { + friend class Event; + + //########################################################################## + // EventQueue Allocation + // + public: + GeneralEventQueue(ClassID class_ID); + GeneralEventQueue(); + ~GeneralEventQueue(); + + static GeneralEventQueue* + Make( + int priorities, + const char* trace_name=NULL + ); + + protected: + int + priorityLevels; + ChainOf + pendingEvents; + ChainOf + timedEvents; + int + eventCount; + #if defined(TRACE_EVENT_COUNT) + TraceOf + *eventCountTrace; + #endif + + //########################################################################## + // EventQueue Functionality + // + public: + void + Post( + int priority, + Receiver *target, + Receiver::Message *message, + Time when=Time::Null + ); + void + SendEvent( + int priority, + HostID host_ID, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when=Time::Null + ); + void + BroadcastEvent( + int priority, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when=Time::Null + ); + void + ExclusiveBroadcastEvent( + int priority, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when=Time::Null + ); + int + GetEventCount() + {return eventCount;} + + AbstractEvent* + PeekAtNextEvent(int min_priority=0); + Logical + IsPriorityEmpty(int priority); + + Logical + ProcessOneEvent(int min_priority=0); + void + ProcessAllEvents(int min_priority=0); + + void + FlushAllEvents(int max_priority=-1); + void + FlushMatchingEvents( + Receiver::MessageID target_message, + int max_priority=-1 + ); + + void + Enqueue( + int priority, + AbstractEvent *event + ); + + //########################################################################## + // Testing Support + // + public: + void + DumpEventQueue(); + }; + + //########################################################################## + //######################### EventQueue ############################### + //########################################################################## + + class EventQueue: + public GeneralEventQueue + { + //########################################################################## + // EventQueue Allocation + // + public: + EventQueue(); + static EventQueue* + Make( + int priorities, + const char* trace_name=NULL + ); + ~EventQueue(); + + //########################################################################## + // EventQueue Posting & Processing + // + public: + Event* + PeekAtNextEvent(int min_priority=0) + { + return + (Event*)GeneralEventQueue::PeekAtNextEvent(min_priority); + } + + void + ProcessMatchingEvents( + Receiver *receiver, + Receiver::MessageID message_ID=Receiver::AnyMessageID + ); + + //########################################################################## + // Testing Support + // + public: + static Logical + TestClass(); + }; + + //########################################################################## + //##################### DeferredEventQueue ########################### + //########################################################################## + // + // NOTE: Do not create any static event queues! new must be used to allocate + // all event queue objects + // + class DeferredEventQueue: + public Node + { + friend class Event; + + //########################################################################## + // Node Support + // + private: + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + + //########################################################################## + // Deferred Queue Functionality + // + public: + DeferredEventQueue(Receiver *target); + ~DeferredEventQueue(); + + void + ProcessAllEvents() + {Check(this); deferredEvents->ProcessAllEvents();} + + private: + EventQueue + *deferredEvents; + SlotOf + waitingReceiver; + }; + +#endif + diff --git a/CODE/RP/MUNGA/EVENT.TCP b/CODE/RP/MUNGA/EVENT.TCP new file mode 100644 index 0000000..10e2f0b --- /dev/null +++ b/CODE/RP/MUNGA/EVENT.TCP @@ -0,0 +1,174 @@ +//===========================================================================// +// File: event.tst // +// Project: MUNGA Brick: Dynamic Dispatch // +// Contents: Test stuff for Event class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/02/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "testclas.hpp" + +Logical + EventQueue::TestClass() +{ + DEBUG_STREAM << "Starting EventQueue test...\n"; + + // + // Construct Queues + // + EventQueue + *p = EventQueue::Make(5), + *q = new EventQueue; + Register_Object(q); + + Test(p->priorityLevels == 5); + Test(q->priorityLevels == 1); + + // + // Test how a single priority queue works + // + Receiver::Message + m(Alpha::message0ID, sizeof(Receiver::Message)), + n(Alpha::message1ID, sizeof(Receiver::Message)); + Alpha + a,b; + Event + *event; + + q->Post(0, &a, &m); + Test(a.x == -1); + + event = q->PeekAtNextEvent(); + Test(event); + Test(event->targetReceiver.GetCurrent() == &a); + Test(event->messageToSend); + Test(a.x == -1); + PlugIteratorOf + i(&a); + Test(i.GetCurrent() == event); + + event->Process(); + Test(a.x == 0); + Test(!q->PeekAtNextEvent()); + + // + // Test multiple events + // + a.x = -1; + q->Post(0, &a, &m); + event = q->PeekAtNextEvent(); + q->Post(0, &a, &n); + Test(q->PeekAtNextEvent() == event); + Test(q->ProcessOneEvent()); + Test(a.x == 0); + Test(q->ProcessOneEvent()); + Test(a.x == 1); + Test(!q->ProcessOneEvent()); + + // + // Test timed messages + // + a.x = -1; + Time t = Now(); + t += 0.5f; + q->Post(0, &a, &m, t); + Time t2 = t; + t2 += 0.1f; + while (!q->ProcessOneEvent()) + { + Test(Now() < t2); + } + Scalar f = Now() - t; + Test(Abs(f) < 0.06f); + Test(a.x == 0); + Test(!q->PeekAtNextEvent()); + + // + // Test multi-priority Queues + // + a.x = -1; + p->Post(2, &a, &m); + event = p->PeekAtNextEvent(); + Test(event); + p->Post(3, &a, &n); + Test(event != p->PeekAtNextEvent()); + + p->ProcessOneEvent(3); + Test(a.x == 1); + event = p->PeekAtNextEvent(3); + Test(!event); + event = p->PeekAtNextEvent(); + Test(event); + Test(event->targetReceiver.GetCurrent() == &a); + p->ProcessOneEvent(); + Test(a.x == 0); + Test(!p->PeekAtNextEvent()); + + // + // Test Reposting + // + a.x = -1; + q->Post(0, &a, &m); + event = q->PeekAtNextEvent(); + event->Repost(p,2); + Test(!q->PeekAtNextEvent()); + Test(!p->PeekAtNextEvent(3)); + Test(p->PeekAtNextEvent(2)); + p->ProcessOneEvent(); + Test(!p->PeekAtNextEvent()); + Test(a.x == 0); + + // + // Test event deference + // + a.x = -1; + q->Post(0, &a, &m); + event = q->PeekAtNextEvent(); + event->Defer(); + Test(!q->PeekAtNextEvent()); + a.ProcessDeferredQueue(); + Test(a.x == 0); + + // + // Test destroying a receiver + // + Alpha *a2 = new Alpha; + Register_Object(a2); + p->Post(1, a2, &n); + Test(p->PeekAtNextEvent()); + Unregister_Object(a2); + delete a2; + Test(!p->PeekAtNextEvent()); + + // + // Now test the flushing functions + // + q->Post(0, &a, &n); + q->Post(0, &a, &m); + a.FlushMatchingEvents(Alpha::message1ID); + Test(q->PeekAtNextEvent()->messageToSend->messageID == Alpha::message0ID); + a.FlushEvents(); + Test(!q->PeekAtNextEvent()); + + q->Post(0, &a, &n); + q->Post(0, &b, &m); + q->FlushMatchingEvents(Alpha::message1ID); + Test(q->PeekAtNextEvent()->messageToSend->messageID == Alpha::message0ID); + q->FlushAllEvents(); + Test(!q->PeekAtNextEvent()); + + // + // Get rid of the queues + // + Unregister_Object(p); + delete[] p; + + Unregister_Object(q); + delete q; + return True; +} diff --git a/CODE/RP/MUNGA/EVTSTAT.CPP b/CODE/RP/MUNGA/EVTSTAT.CPP new file mode 100644 index 0000000..776c518 --- /dev/null +++ b/CODE/RP/MUNGA/EVTSTAT.CPP @@ -0,0 +1,167 @@ +//===========================================================================// +// File: evtstat.cpp // +// Project: MUNGA Brick: Event Manager // +// Contents: interface specification of event manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/15/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "munga.hpp" + +#if !defined(EVTSTAT_HPP) +# include "evtstat.hpp" +#endif + +#if !defined(APP_HPP) +# include "app.hpp" +#endif + +#if !defined(REGISTRY_HPP) +# include "registry.hpp" +#endif + +#if !defined(ENTITY_HPP) +# include "entity.hpp" +#endif + +//############################################################################# +//########################## EventStatistics ############################ +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +EventStatistics::EventStatistics( + ClassID class_ID, + Receiver::MessageID message_ID +): + classID(class_ID), + messageID(message_ID), + eventCount(0) +{ +} + +//############################################################################# +//######################## EventStatisticsManager ####################### +//############################################################################# + +EventStatisticsManager + event_statistics_manager; + +// +//############################################################################# +//############################################################################# +// +EventStatisticsManager::EventStatisticsManager(): + eventStatisticsSocket(NULL, True) +{ + printedReport = False; +} + +// +//############################################################################# +//############################################################################# +// +void + EventStatisticsManager::Maintain(Event *event) +{ + Check(this); + Check(event); + + // + // If the application is not running then it is not time to collect + // statistics yet + // + Check(application); + if (application->GetApplicationState() != Application::RunningMission) + return; + + // + // Add statistics for this event + // + ClassID + class_ID; + Receiver::MessageID + message_ID; + long + index_value; + EventStatistics + *event_statistics; + + message_ID = event->messageToSend->messageID; + class_ID = event->targetReceiver.GetCurrent()->GetClassID(); + index_value = class_ID * 1000 + message_ID; // HACK to create unique key + if ((event_statistics = eventStatisticsSocket.Find(index_value)) == NULL) + { + event_statistics = new EventStatistics(class_ID, message_ID); + eventStatisticsSocket.AddValue(event_statistics, index_value); + } + Check(event_statistics); + event_statistics->eventCount++; +} + +// +//############################################################################# +//############################################################################# +// +void + EventStatisticsManager::Report() +{ + Check(this); + + // + // Print Report + // + TableIteratorOf + iterator(&eventStatisticsSocket); + EventStatistics + *event_statistics; + + cout << "EventStatisticsManager::Report - event_count=" + << iterator.GetSize() << "\n"; + while ((event_statistics = iterator.ReadAndNext()) != NULL) + { + Check(event_statistics); + + Registry + *registry; + Entity::SharedData + *shared_data; + Derivation + *derivation; + Receiver::MessageHandlerSet + *handlers; + + cout << "EventStatisticsManager::Report -\t"; + cout << event_statistics->classID << "\t"; + cout << event_statistics->messageID << "\t"; + cout << event_statistics->eventCount << "\t"; + + Check(application); + if ((registry = application->GetRegistry()) != NULL) + { + Check(registry); + shared_data = registry->GetStaticData(event_statistics->classID); + if (shared_data != NULL) + { + Check(shared_data); + derivation = shared_data->derivedClasses; + Check(derivation); + handlers = shared_data->activeMessageHandlers; + Check(handlers); + + cout << derivation->className << "::" + << handlers->GetName(event_statistics->messageID) << "\t"; + } + } + cout << "\n"; + } + iterator.DeletePlugs(); +} + diff --git a/CODE/RP/MUNGA/EVTSTAT.HPP b/CODE/RP/MUNGA/EVTSTAT.HPP new file mode 100644 index 0000000..fa0b305 --- /dev/null +++ b/CODE/RP/MUNGA/EVTSTAT.HPP @@ -0,0 +1,92 @@ +//===========================================================================// +// File: evtstat.hpp // +// Project: MUNGA Brick: Event Manager // +// Contents: interface specification of event manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/15/96 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(EVTSTAT_HPP) +# define EVTSTAT_HPP + +# if !defined(STYLE_HPP) +# include "style.hpp" +# endif + +# if !defined(RECEIVER) +# include "receiver.hpp" +# endif + + //######################################################################### + //######################## EventStatistics ########################## + //######################################################################### + + class EventStatistics: + public Plug + { + friend class EventStatisticsManager; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction + // + public: + EventStatistics::EventStatistics( + ClassID class_ID, + Receiver::MessageID message_ID + ); + ~EventStatistics() {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + ClassID + classID; + Receiver::MessageID + messageID; + long + eventCount; + }; + + //######################################################################### + //##################### EventStatisticsManager ###################### + //######################################################################### + + class EventStatisticsManager: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction + // + public: + EventStatisticsManager::EventStatisticsManager(); + ~EventStatisticsManager() {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Statistic collection and reporting + // + public: + void + Maintain(Event *event); + void + Report(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + TableOf + eventStatisticsSocket; + Logical + printedReport; + }; + + extern EventStatisticsManager + event_statistics_manager; + +#endif \ No newline at end of file diff --git a/CODE/RP/MUNGA/EXPLODE.HPP b/CODE/RP/MUNGA/EXPLODE.HPP new file mode 100644 index 0000000..23b8cc4 --- /dev/null +++ b/CODE/RP/MUNGA/EXPLODE.HPP @@ -0,0 +1,216 @@ +//===========================================================================// +// File: mover.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +// 12/27/95 GDU Splash Damage // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(EXPLODE_HPP) +# define EXPLODE_HPP + +# if !defined(ENTITY_HPP) +# include +# endif + +# if !defined(BOXSOLID_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + + //########################################################################## + //##################### Explosion::ModelResource ##################### + //########################################################################## + + struct Explosion__ModelResource + { + ObjectID + resourceTableObjectID; + Scalar + explosionDuration; + }; + + //########################################################################## + //########################### Explosion ############################## + //########################################################################## + + class Explosion__MakeMessage; + + class Damage; + class Mover; + + class Explosion: + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef Explosion__ModelResource + ModelResource; + + typedef void + (Explosion::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + ExplosionSimulation(Scalar time_slice); + + static ResourceDescription::ResourceID + Explosion::CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + + typedef ChainIteratorOf EntityIterator; + + void + SplashDamage( + EntityID inflicting, + Damage &damage, + Scalar collisionRadius, + Vector3D offset = Vector3D::Identity, + Entity *exludedEntities = NULL + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef Explosion__MakeMessage + MakeMessage; + + static Explosion* + Make(MakeMessage *creation_message); + + Explosion( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~Explosion(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + Enumeration + GetInterestPriority(Entity *linked_entity); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected Data + // + protected: + Scalar + explosionDuration; + Entity + *entityHit; + Entity + *creatingEntity; + Point3D + localHitPosition; + }; + + //########################################################################## + //##################### Explosion::MakeMessage ####################### + //########################################################################## + + class Explosion__MakeMessage: + public Entity::MakeMessage + { + public: + EntityID + entityHitID; + EntityID + creatingEntityID; + + Explosion__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID + ): + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + entityHitID(entity_hit_ID), + creatingEntityID(creating_entity_ID) + {} + }; + + //########################################################################## + //###################### ExplosionResourceTable ###################### + //########################################################################## + + class ExplosionResourceTable: + public Plug + { + public: + typedef PlugOf + ResourceIDPlug; + + ExplosionResourceTable(PlugStream *stream); + ~ExplosionResourceTable(); + + static void + BuildFromPage( + ObjectStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + Logical + TestInstance() const; + + ResourceDescription::ResourceID + FindResourceID(Enumeration material_type); + ResourceDescription::ResourceID + FindResourceID(Entity *entity_hit); + + private: + TableOf + resourceIDSocket; + }; + +#endif diff --git a/CODE/RP/MUNGA/EXPTBL.HPP b/CODE/RP/MUNGA/EXPTBL.HPP new file mode 100644 index 0000000..32e1d0c --- /dev/null +++ b/CODE/RP/MUNGA/EXPTBL.HPP @@ -0,0 +1,236 @@ +//===========================================================================// +// File: exptbl.hpp // +// Title: Declaration of ExplosionTable, ExplosionTableEntry // +// Project: BattleTech // +// Purpose: A Structure To hold Explosion Information for An entity // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/23/95 JM Initial Coding // +//===========================================================================// + +#if !defined (EXPTBL_HPP) +# define EXPTBL_HPP + +# if !defined (PLUG_HPP) +# include +# endif + +# if !defined (TABLE_HPP) +# include +# endif + +# if !defined (RESOURCE_HPP) +# include +# endif + +# if !defined(ENTITYID_HPP) +# include +# endif + +# if !defined(CMPNNT_HPP) +# include +# endif + + class Entity; + class NotationFile; + class Point3D; + + //############################################################################## + //###################### Class ExplosionTableEntry ######################## + //############################################################################## + + class ExplosionTableEntry : public Plug + { + + protected: + + Scalar + damageLevel; + + Enumeration + graphicState; + + ResourceDescription::ResourceID + explosionResourceID; + + Scalar + timeDelay; + + public: + + ExplosionTableEntry(MemoryStream *exp_stream); + ~ExplosionTableEntry(); + + static Logical + CreateStreamedExplosion( + ResourceFile *resource_file, + CString exp_file_name, + NotationFile *exp_file, + CString exp_page_name, + MemoryStream *explosion_stream + ); + + ResourceDescription::ResourceID + GetExplosionResourceID() const + {Check(this); return explosionResourceID;} + + Scalar + GetDamageLevel() const + {Check(this); return damageLevel;} + + Enumeration + GetGraphicState() const + {Check(this); return graphicState;} + + Scalar + GetTimeDelay() const + {Check(this); return timeDelay;} + + void + CreateExplosion( + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + const Point3D &explode_position + ); + }; + + //############################################################################## + //######################## Class ExplosionTable ########################### + //############################################################################## + + // (Although sharing instance not fully implemented yet!) + // Note: Explosion tables specifically do not hold any references to any + // specific damage Zone as you will most likely be sharing instances of + // explosion tables across entity's, subsystem's, etc.. + // + class ExplosionTable : public TableOf + { + protected: + + typedef + TableIteratorOf + ExplosionTableIterator; + + public: + + ExplosionTable(MemoryStream *exp_stream); + ~ExplosionTable(); + + ExplosionTableEntry* + SelectDamageLevelEntry(Scalar damage_level); + + ExplosionTableEntry* + SelectGraphicStateEntry(Enumeration graphic_state); + + void + DamageExplosion( + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + Scalar damage_level, + const Point3D &explode_position + ) + { + Check(this); + ExplosionTableEntry *exp_entry = SelectDamageLevelEntry(damage_level); + if (exp_entry) + { + CreateExplosion( + exp_entry, + entity_hit_ID, + creating_entity_ID, + explode_position + ); + } + #if DEBUG_LEVEL>0 + else + { + Tell("DamageLevel = "); + Tell(damage_level); + Warn("not valid for ExplosionTable, no Explosion being created !\n"); + } + #endif + } + + void + CreateExplosion( + ExplosionTableEntry *explosion_entry, + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + Point3D explode_position // world coordinates + ); + + void + GraphicStateExplosion( + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + const Point3D &explode_position, + Enumeration graphic_state + ) + { + Check(this); + ExplosionTableEntry *exp_entry = SelectGraphicStateEntry(graphic_state); + if (exp_entry) + { + CreateExplosion( + exp_entry, + entity_hit_ID, + creating_entity_ID, + explode_position + ); + } + #if DEBUG_LEVEL>0 + else + { + Tell("DamageZone::GraphicState = "); + Tell(graphic_state); + Warn("not valid for ExplosionTable, no Explosion being created !\n"); + } + #endif + } + + Logical + CrossedDamageLevelThreshold(Scalar old_value, Scalar new_value); + + static Logical + CreateStreamedExplosionTable( + ResourceFile *resource_file, + CString model_name, + NotationFile *exp_file, + CString exp_filename, + MemoryStream *explosion_stream + ); + }; + + //########################################################################## + //###################### EntityEffectWatcher ######################### + //########################################################################## + + class EntityEffectWatcher : + public Component + { + protected: + + Scalar + *oldDamageLevel; + + Entity + *entityWatched; + + public: + + EntityEffectWatcher( + Entity *entity_watched + ); + + ~EntityEffectWatcher(); + + + Logical + TestInstance() const; + + void + Execute(); + + }; +#endif diff --git a/CODE/RP/MUNGA/EXTNTBOX.CPP b/CODE/RP/MUNGA/EXTNTBOX.CPP new file mode 100644 index 0000000..1d51057 --- /dev/null +++ b/CODE/RP/MUNGA/EXTNTBOX.CPP @@ -0,0 +1,280 @@ +//===========================================================================// +// File: extntbox.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details of bounding box class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/07/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994,1995 Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(EXTNTBOX_HPP) +# include +#endif + +#if !defined(CSTR_HPP) + #include +#endif + +#if !defined(VECTOR3D_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile ExtentBox *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExtentBox::ExtentBox( + const Vector3D &min, + const Vector3D &max +) +{ + Check_Pointer(this); + Check(&min); + Check(&max); + + if (min.x <= max.x) + { + minX = min.x; + maxX = max.x; + } + else + { + minX = max.x; + maxX = min.x; + } + + if (min.y <= max.y) + { + minY = min.y; + maxY = max.y; + } + else + { + minY = max.y; + maxY = min.y; + } + + if (min.z <= max.z) + { + minZ = min.z; + maxZ = max.z; + } + else + { + minZ = max.z; + maxZ = min.z; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExtentBox::ExtentBox(const ExtentBox &box) +{ + Check_Pointer(this); + Check(&box); + + minX = box.minX; + maxX = box.maxX; + minY = box.minY; + maxY = box.maxY; + minZ = box.minZ; + maxZ = box.maxZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExtentBox& + ExtentBox::Intersect( + const ExtentBox &box_1, + const ExtentBox &box_2 + ) +{ + Check_Pointer(this); + Check(&box_1); + Check(&box_2); + + Verify(box_1.minX <= box_2.maxX); + Verify(box_1.maxX >= box_2.minX); + Verify(box_1.minY <= box_2.maxY); + Verify(box_1.maxY >= box_2.minY); + Verify(box_1.minZ <= box_2.maxZ); + Verify(box_1.maxZ >= box_2.minZ); + + minX = Max(box_1.minX, box_2.minX); + maxX = Min(box_1.maxX, box_2.maxX); + minY = Max(box_1.minY, box_2.minY); + maxY = Min(box_1.maxY, box_2.maxY); + minZ = Max(box_1.minZ, box_2.minZ); + maxZ = Min(box_1.maxZ, box_2.maxZ); + + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Vector3D* + ExtentBox::Constrain(Vector3D *point) const +{ + Check(this); + Check(point); + + Clamp(point->x,minX,maxX); + Clamp(point->y,minY,maxY); + Clamp(point->z,minZ,maxZ); + return point; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::Contains(const Vector3D &point) const +{ + return + minX <= point.x && maxX >= point.x + && minY <= point.y && maxY >= point.y + && minZ <= point.z && maxZ >= point.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::Contains(const ExtentBox &box) const +{ + return + minX <= box.minX && maxX >= box.maxX + && minY <= box.minY && maxY >= box.maxY + && minZ <= box.minZ && maxZ >= box.maxZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::Intersects(const ExtentBox &box) const +{ + return + minX <= box.maxX && maxX >= box.minX + && minY <= box.maxY && maxY >= box.minY + && minZ <= box.maxZ && maxZ >= box.minZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::TestInstance() const +{ + return minX<=maxX && minY<=maxY && minZ<=maxZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ostream& + operator<<( + ostream& stream, + const ExtentBox& e + ) +{ + return stream << '[' << e.minX << ".." << e.maxX << "],[" << e.minY << ".." + << e.maxY << "],[" << e.minZ << ".." << e.maxZ << ']'; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Convert_From_Ascii( + const char *str, + ExtentBox *extent_box + ) +{ + Check_Pointer(str); + Check_Signature(extent_box); + + CString parse_string(str); + Check(&parse_string); + + Check_Pointer(parse_string.GetNthToken(0)); + extent_box->minX = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + extent_box->minY = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + extent_box->minZ = atof(parse_string.GetNthToken(2)); + + Check_Pointer(parse_string.GetNthToken(3)); + extent_box->maxX = atof(parse_string.GetNthToken(3)); + + Check_Pointer(parse_string.GetNthToken(4)); + extent_box->maxY = atof(parse_string.GetNthToken(4)); + + Check_Pointer(parse_string.GetNthToken(5)); + extent_box->maxZ = atof(parse_string.GetNthToken(5)); + + Check(extent_box); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +ExtentBox * + MakeExistanceBoxStream( + NotationFile *notation_file, + int *size + ) +{ + + char page_name[50]; + + if (!notation_file->GetEntry("COLLISION", "extentcount", size)) + { + cerr << "No 'COLLISION' entry!!!!!" << endl; + Exit(AbortExitCodeID); + } + + ExtentBox *extents = new ExtentBox[*size]; + + for (int j=0; j < *size; ++j) + { + sprintf(page_name, "extent %d", j); + + int errorvalue = 0; + + errorvalue |= !notation_file->GetEntry(page_name, "extminX", &extents[j].minX); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxX", &extents[j].maxX); + errorvalue |= !notation_file->GetEntry(page_name, "extminY", &extents[j].minY); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxY", &extents[j].maxY); + errorvalue |= !notation_file->GetEntry(page_name, "extminZ", &extents[j].minZ); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxZ", &extents[j].maxZ); + + if ( errorvalue ) + { + Tell("Extent number : " << j << " is does not have valid slice extents " << endl); + Exit(AbortExitCodeID); + } + + } + + return extents; + +} diff --git a/CODE/RP/MUNGA/EXTNTBOX.HPP b/CODE/RP/MUNGA/EXTNTBOX.HPP new file mode 100644 index 0000000..685eba2 --- /dev/null +++ b/CODE/RP/MUNGA/EXTNTBOX.HPP @@ -0,0 +1,110 @@ +//===========================================================================// +// File: extntbox.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification of bounding box class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/07/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995 Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(EXTNTBOX_HPP) +# define EXTNTBOX_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + + class Vector3D; + class NotationFile; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class ExtentBox + { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile ExtentBox *); + #endif + + Scalar + minX, + maxX, + minY, + maxY, + minZ, + maxZ; + + ExtentBox() {} + ExtentBox( + const Vector3D &min, + const Vector3D &max + ); + ExtentBox(const ExtentBox &box); + + const Scalar& + operator[](int index) const + {Check(this); return (&minX)[index];} + Scalar& + operator[](int index) + {Check(this); return (&minX)[index];} + + ExtentBox& + Intersect( + const ExtentBox &box_1, + const ExtentBox &box_2 + ); + Vector3D* + Constrain(Vector3D *point) const; + + Logical + Contains(const Vector3D &point) const; + Logical + Contains(const ExtentBox &box) const; + Logical + Intersects(const ExtentBox &box) const; + + Logical + TestInstance() const; + static Logical + TestClass(); + friend ostream& + operator<<( + ostream& stream, + const ExtentBox& e + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + ExtentBox *extent_box + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + ExtentBox *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const ExtentBox *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + ExtentBox * + MakeExistanceBoxStream( + NotationFile *notation_file, + int *size + ); + +#endif diff --git a/CODE/RP/MUNGA/EYECANDY.CPP b/CODE/RP/MUNGA/EYECANDY.CPP new file mode 100644 index 0000000..88affd6 --- /dev/null +++ b/CODE/RP/MUNGA/EYECANDY.CPP @@ -0,0 +1,262 @@ +//===========================================================================// +// File: eyecandy.cpp // +// Project: MUNGA Brick: Model Manager // +// Contents: Implementation details of moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JSE Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RANDOM_HPP) +# include +#endif + +#if !defined(EYECANDY_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +//############################################################################# +// Shared Data Support +// +EyeCandy::SharedData + EyeCandy::DefaultData( + EyeCandy::ClassDerivations, + EyeCandy::MessageHandlers, + EyeCandy::AttributeIndex, + EyeCandy::StateCount, + (Entity::MakeHandler)EyeCandy::Make + ); + +Derivation + EyeCandy::ClassDerivations( + Entity::ClassDerivations, + "EyeCandy" + ); + +//############################################################################# +//############################### EyeCandy ################################# +//############################################################################# + +void + EyeCandy::EyeCandySimulation(Scalar) +{ + Check(application); + + if (simulationState.GetState() == effectOn) + { + simulationState.SetState(effectOff); + } + + Scalar now = Now(); + if ((now - lastTrigger) >= waitTime) + { + simulationState.SetState(effectOn); + lastTrigger = now; + + RandomGenerator random_number; + waitTime = minWaitTime + (maxWaitTime - minWaitTime) * random_number; + } +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EyeCandy::EyeCandy( + EyeCandy::MakeMessage *creation_message , + EyeCandy::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + SetPerformance(&EyeCandy::EyeCandySimulation); + SetValidFlag(); + + // + //------------------------------------------------- + // Find the EyeCandy in the resource + //------------------------------------------------- + // + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + ResourceDescription *res = + res_file->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + + ModelResource *eyecandy_res = (ModelResource*)res->resourceAddress; + maxWaitTime = eyecandy_res->maxWaitTime; + minWaitTime = eyecandy_res->minWaitTime; + res->Unlock(); + + waitTime = minWaitTime + (maxWaitTime - minWaitTime) * Random; + + simulationState.SetState(effectOff); + lastTrigger = Now(); + + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EyeCandy* + EyeCandy::Make(EyeCandy::MakeMessage *creation_message) +{ + return new EyeCandy(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EyeCandy::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->classToCreate = RegisteredClass::EyeCandyClassID; + creation_message->instanceFlags = HermitInstance|DynamicFlag|TrappedFlag; + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EyeCandy::~EyeCandy() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +ResourceDescription::ResourceID + EyeCandy::CreateModelResource( +#if DEBUG_LEVEL>0 + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model +#else + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *, + ModelResource *model +#endif + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check_Pointer(directories); + + // + // If we were not provided a buffer to write the model data into, we must + // create it ourselves. Then make sure that the model stuff is read in + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + //---------------------------------------- + // Read in the data from notation file + //---------------------------------------- + // + // Get PointValue assigned to this ScoreZone + // + + if( + !model_file->GetEntry( + "gamedata", + "MaxWaitTime", + &local_model->maxWaitTime + ) + ) + { + cerr << model_name << "Missing MaxWaitTime" << endl; +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + return -1; + } + + if( + !model_file->GetEntry( + "gamedata", + "MinWaitTime", + &local_model->minWaitTime + ) + ) + { + cerr << model_name << "Missing MinWaitTime" << endl; + goto Dump_And_Die; + } + + // + //--------------------------- + // Write out the new resource + //--------------------------- + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + return new_res->resourceID; + } + else + { + return 0; + } +} + +Logical + EyeCandy::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/EYECANDY.HPP b/CODE/RP/MUNGA/EYECANDY.HPP new file mode 100644 index 0000000..e2d3424 --- /dev/null +++ b/CODE/RP/MUNGA/EYECANDY.HPP @@ -0,0 +1,120 @@ +//===========================================================================// +// File: eyecandy.hpp // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JSE Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(EYECANDY_HPP) +# define EYECANDY_HPP + +# if !defined(ENTITY_HPP) +# include +# endif + + //########################################################################## + //##################### EyeCandy::ModelResource ##################### + //########################################################################## + + struct EyeCandy__ModelResource + { + Scalar + maxWaitTime; + Scalar + minWaitTime; + + }; + + //########################################################################## + //########################### EyeCandy ############################### + //########################################################################## + + class EyeCandy: + public Entity + { + public: + enum { + effectOff = Entity::StateCount, + effectOn, + StateCount + }; + + private: + Scalar + maxWaitTime; + Scalar + minWaitTime; + Scalar + waitTime; + Scalar + lastTrigger; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (EyeCandy::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + EyeCandySimulation(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + + typedef EyeCandy__ModelResource ModelResource; + + static EyeCandy* + Make(EyeCandy::MakeMessage *creation_message); + + EyeCandy( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~EyeCandy(); + + Logical + TestInstance() const; + + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static ResourceDescription::ResourceID + EyeCandy::CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model = NULL + ); + + }; +#endif diff --git a/CODE/RP/MUNGA/FILESTRM.CPP b/CODE/RP/MUNGA/FILESTRM.CPP new file mode 100644 index 0000000..2e0c223 --- /dev/null +++ b/CODE/RP/MUNGA/FILESTRM.CPP @@ -0,0 +1,152 @@ +#include +#pragma hdrstop + +#if !defined(FILESTRM_HPP) +# include +#endif + +//############################################################################# +//########################### FileStream ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +FileStream::FileStream( + const char* file_name, + Logical writable +): + MemoryStream(NULL, 0) +{ + Open(file_name, writable); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::Open( + const char* file_name, + Logical writable + ) +{ + readOnly = !writable; + fileHandle = -1; + currentPosition = streamStart = NULL; + streamSize = 0; + if (file_name) + { + Check_Pointer(file_name); + fileHandle = OpenImplementation(file_name, readOnly); + } + + if (fileHandle != -1) + { + if (readOnly) + { + streamSize = SeekImplementation(fileHandle, 0, True); + SeekImplementation(fileHandle, 0); + } + else + { + streamSize = 0xFFFFFFFFU; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::Close() +{ + Check(this); + + // + //--------------------------------- + // If the file was opened, close it + //--------------------------------- + // + if (fileHandle != -1) + { + CloseImplementation(fileHandle); + } + fileHandle = -1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::SetPointer(size_t index) +{ + Check(this); + Verify(fileHandle != -1); + + currentPosition = (char*)SeekImplementation(fileHandle, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::AdvancePointer(size_t index) +{ + Check(this); + Verify(fileHandle != -1); + + currentPosition = + (char*)SeekImplementation(fileHandle, (size_t)currentPosition + index); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::RewindPointer(size_t index) +{ + Check(this); + Verify(fileHandle != -1); + + currentPosition = + (char*)SeekImplementation(fileHandle, (size_t)currentPosition + index); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::ReadBytes( + void *ptr, + size_t number_of_bytes + ) +{ + Check(this); + Verify(fileHandle != -1); + Verify(readOnly); + size_t read = ReadImplementation(fileHandle, ptr, number_of_bytes); + Verify(read == number_of_bytes); + currentPosition += read; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + FileStream::WriteBytes( + const void *ptr, + size_t number_of_bytes + ) +{ + Check(this); + Verify(fileHandle != -1); + Verify(!readOnly); + size_t written = WriteImplementation(fileHandle, ptr, number_of_bytes); + Verify(written == number_of_bytes); + currentPosition += written; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + FileStream::TestInstance() const +{ + return True; +} + diff --git a/CODE/RP/MUNGA/FILESTRM.HPP b/CODE/RP/MUNGA/FILESTRM.HPP new file mode 100644 index 0000000..d03e7ea --- /dev/null +++ b/CODE/RP/MUNGA/FILESTRM.HPP @@ -0,0 +1,118 @@ +//===========================================================================// +// File: filestrm.hpp // +// Project: MUNGA Brick: Resource Manager // +// Contents: Implementation Details of resource management // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(FILESTRM_HPP) +# define FILESTRM_HPP + +# if !defined(MEMSTRM_HPP) +# include +# endif + + //########################################################################## + //######################## FileStream ################################ + //########################################################################## + + class FileStream: + public MemoryStream + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructors + // + public: + FileStream( + const char* file_name = NULL, + Logical writable = False + ); + ~FileStream() + {Close();} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Status functions + // + public: + void* + GetPointer() const + { + Fail("No implementation possible for FileStream::GetPointer()"); + return NULL; + } + + void + SetPointer(void *new_pointer) + {Fail("No implementation possible for FileStream::SetPointer(void*)");} + void + SetPointer(size_t index); + + MemoryStream& + AdvancePointer(size_t count); + + MemoryStream& + RewindPointer(size_t count); + + MemoryStream& + ReadBytes( + void *ptr, + size_t number_of_bytes + ); + MemoryStream& + WriteBytes( + const void *ptr, + size_t number_of_bytes + ); + + void + Open( + const char* file_name = NULL, + Logical writable = False + ); + void + Close(); + Logical + IsFileOpened() + {return fileHandle != -1;} + + Logical + TestInstance() const; + + protected: + int fileHandle; + Logical readOnly; + + static int + OpenImplementation( + const char* file_name, + Logical read_only + ); + static void + CloseImplementation(int file_handle); + static size_t + SeekImplementation( + int file_handle, + size_t where, + Logical from_end = False + ); + static size_t + ReadImplementation( + int file_handle, + void *buffer, + size_t length + ); + static size_t + WriteImplementation( + int file_handle, + const void* buffer, + size_t length + ); + }; + +#endif + diff --git a/CODE/RP/MUNGA/FILESTUB.CPP b/CODE/RP/MUNGA/FILESTUB.CPP new file mode 100644 index 0000000..5a4936c --- /dev/null +++ b/CODE/RP/MUNGA/FILESTUB.CPP @@ -0,0 +1,77 @@ +#include +#pragma hdrstop + +#if !defined(FILESTRM_HPP) +# include +#endif + +#include +#include +#include + +//############################################################################# +//########################### FileStream ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + FileStream::OpenImplementation( + const char *file_name, + Logical read_only + ) +{ + if (read_only) + { + return open(file_name, O_BINARY|O_RDONLY); + } + else + { + return open(file_name, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, S_IWRITE); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::CloseImplementation(int file_handle) +{ + close(file_handle); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::SeekImplementation( + int file_handle, + size_t where, + Logical from_end + ) +{ + return lseek(file_handle, (long)where, (from_end) ? SEEK_END : SEEK_SET); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::ReadImplementation( + int file_handle, + void *buffer, + size_t length + ) +{ + return read(file_handle, buffer, length); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::WriteImplementation( + int file_handle, + const void *buffer, + size_t length + ) +{ + return write(file_handle, buffer, length); +} + diff --git a/CODE/RP/MUNGA/FILEUTIL.HPP b/CODE/RP/MUNGA/FILEUTIL.HPP new file mode 100644 index 0000000..3593aa9 --- /dev/null +++ b/CODE/RP/MUNGA/FILEUTIL.HPP @@ -0,0 +1,177 @@ +//===========================================================================// +// File: fileutil.hh // +// Title: General File Utilities // +// Project: Tool Architecture II // +// Author: Jerry Edsall // +// Purpose: Provide mechanism for keeping work directories // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/23/95 JSE Initial Coding // +// 03/01/95 KEO Cleanup and enhancements. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(FILEUTIL_HPP) + #define FILEUTIL_HPP + + //--------------- + // munga headers + //--------------- + #if !defined(STYLE_HPP) + #include + #endif + + #if !defined(SCALAR_HPP) + #include + #endif + + class NotationFile; + + extern char *WorkingDirectory; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + extern const char *White_Space; + + inline char* + NextToken() + { return strtok(NULL, White_Space); } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + SetSourceDirectory(const char *input_file); + void + SetOutputDirectory(const char *directory); + const char* + GetSourceDirectory(); + const char* + GetConfigDirectory(); + const char* + GetMaterialDirectory(); + const char* + GetTextureDirectory(); + const char* + GetAnimationDirectory(); + const char* + GetProductionDirectory(); + const char* + GetOutputDirectory(); + void + ClearDirectories(); + const char* + SourceFile( + const char *filename, + const char *extension = NULL + ); + const char* + ConfigFile( + const char *filename, + const char *extension = NULL + ); + const char* + MaterialFile( + const char *filename, + const char *extension = NULL + ); + const char* + TextureFile( + const char *filename, + const char *extension = NULL + ); + const char* + AnimationFile( + const char *filename, + const char *extension = NULL + ); + const char* + OutputFile( + const char *filename, + const char *extension = NULL + ); + const char* + StripDirectory(const char *filename); + const char* + StripExtension(const char *filename); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + char* + Ind(int level = 1); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Logical + GetLine( + istream &stream, + char *buffer, + int size_of_buffer + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if 0 + char* + stripname(char filename[]); +#endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Scalar + D2R(float degrees); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + char* + MakeWorkingDirectory( + const char *file + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Logical + DirectoryIsSpecified( + const char *file + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + char* + MakePathedFilename( + const char *directory, + const char *name + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + OpenOutput( + ofstream &stream, + const char *directory, + const char *filename + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + OpenInput( + ifstream &stream, + char *directory, + const char *filename + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Logical + DoesNotationFileExist( + NotationFile + *notation_file + ); + +#endif + +//============================================================================= diff --git a/CODE/RP/MUNGA/GAUGALRM.CPP b/CODE/RP/MUNGA/GAUGALRM.CPP new file mode 100644 index 0000000..62fa09f --- /dev/null +++ b/CODE/RP/MUNGA/GAUGALRM.CPP @@ -0,0 +1,437 @@ +//===========================================================================// +// File: gaugalrm.cpp // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/22/96 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(GAUGALRM_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +#if !defined(ENTITY_HPP) +# include +#endif + +#if !defined(SUBSYSTM_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//####################################################################### +// GaugeAlarm +//####################################################################### +GaugeAlarm::GaugeAlarm( + Entity *the_entity, + Subsystem *the_subsystem, + Enumeration the_condition +) : + Node(RegisteredClass::GaugeAlarmClassID), + lampList(NULL) +{ + Check(the_entity); + Check(the_subsystem); + + Test_Tell( + "GaugeAlarm(" << the_entity << + ", " << the_subsystem << + ", " << the_condition << + ")\n" + ); + + entity = the_entity; + subsystem = the_subsystem; + conditionIndex = the_condition; + Check_Fpu(); +} + +GaugeAlarm::~GaugeAlarm() +{ + Test_Tell("~GaugeAlarm()"); + Check(this); + + ChainIteratorOf + i(lampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + Test_Tell("lamp "); + lamp_pointer->SetAlertState(False); + } + Test_Tell("\n"); + Check_Fpu(); +} + +Logical + GaugeAlarm::TestInstance() const +{ + return Node::TestInstance(); +} + + +//####################################################################### +// GaugeAlarmManager +//####################################################################### +Logical + GaugeAlarmManager::CreateGaugeAlarmStreamItem( + MemoryStream */*mem_stream*/, + const char */*alarm_name*/, + const char */*alarm_data*/ + ) +{ + Fail("GaugeAlarmManager::CreateGaugeAlarmStreamItem not overridden!"); + return False; +} + +void + GaugeAlarmManager::ReadGaugeAlarmStreamItem( + GaugeAlarm */*alarm*/, + Entity */*the_entity*/, + Subsystem */*the_subsystem*/, + Enumeration /*the_condition*/, + MemoryStream */*mem_stream*/ + ) +{ + Fail("GaugeAlarmManager::ReadGaugeAlarmStreamItem not overridden!"); +} + +ResourceDescription::ResourceID + GaugeAlarmManager::CreateModelGaugeAlarmStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories */*directories*/ + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + int + i; + ResourceDescription::ResourceID + res_id = ResourceDescription::NullResourceID; + + //------------------------------------------------------------- + // Make sure the notation file is in relaxed operation mode + //------------------------------------------------------------- + Enumeration + old_notation_file_mode = model_file->GetModes(); + + model_file->SetMode( + NotationFile::RelaxedOperationModes | NotationFile::SkipBlanksListMode + ); + //------------------------------------------------------------- + // Build a list of all the alarm entries for the gauge renderer + //------------------------------------------------------------- + NameList + *alarm_list = model_file->MakeEntryList("gaugeAlarm"); + + if (alarm_list != NULL) + { + Test_Tell( + "Processing model gauge alarm data for '" << model_name << "':" + ); + Register_Object(alarm_list); + //------------------------------------------------------------- + // Get the number of alarms + //------------------------------------------------------------- + Logical + built_ok = True; + int + alarm_count = alarm_list->EntryCount(); + + Test_Tell(alarm_count << " entries.\n"); + Verify(alarm_count > 0); + //------------------------------------------------------------- + // Create a dynamic memory stream + //------------------------------------------------------------- + DynamicMemoryStream + *alarm_stream = new DynamicMemoryStream(); + Register_Object(alarm_stream); + //------------------------------------------------------------- + // Write the number of alarms to the stream + //------------------------------------------------------------- + MemoryStream_Write(alarm_stream, &alarm_count); + //------------------------------------------------------------- + // Write the alarms to the stream + //------------------------------------------------------------- + NameList::Entry + *alarm_entry = alarm_list->GetFirstEntry(); + + for(i=0; iGetName(), + alarm_entry->GetChar() + ) + == False + ) + { + DEBUG_STREAM << + "Model file '" << model_name << + "' has undefined alarm type '" << alarm_entry->GetName() << + "' - resource not built.\n"; + built_ok = False; + break; + } + alarm_entry = alarm_entry->GetNextEntry(); + } + //------------------------------------------------------------- + // Create the resource description, assign an ID + //------------------------------------------------------------- + if (built_ok) + { + Test_Tell("Creating resource description for '"<AddResourceMemoryStream( + model_name, + ResourceDescription::GaugeAlarmStreamResourceType, + 1, // priority + ResourceDescription::Preload, + alarm_stream + ); + + Check(res_desc_stream); + res_id = res_desc_stream->resourceID; + } + + Unregister_Object(alarm_stream); + delete alarm_stream; + Test_Tell("Closed gauge alarm stream\n" << flush); + Test_Tell("res_id = " << res_id << "\n"); + } + //------------------------------------------------------------- + // Restore the notation file's previous operation mode + //------------------------------------------------------------- + model_file->PutModes(old_notation_file_mode); + //------------------------------------------------------------- + // Return the new ResourceID + //------------------------------------------------------------- + Check_Fpu(); + return res_id; +} + +GaugeAlarmManager::GaugeAlarmManager() : + gaugeAlarmList(NULL) +{ + Check_Fpu(); +} + +GaugeAlarmManager::~GaugeAlarmManager() +{ + Check(this); + Check_Fpu(); +} + +Logical + GaugeAlarmManager::TestInstance() const +{ + return True; +} + +void + GaugeAlarmManager::RemoveAllAlarms() +{ + Check(this); + + //------------------------------------------- + // Delete all GaugeAlarms + //------------------------------------------- + ChainIteratorOf + i(gaugeAlarmList); + GaugeAlarm + *alarm_pointer; + + while ((alarm_pointer=i.ReadAndNext()) != NULL) + { + Check(alarm_pointer); + Unregister_Object(alarm_pointer); + delete alarm_pointer; + } + Check_Fpu(); +} + +void + GaugeAlarmManager::Activate( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID new_resource_id + ) +{ + Test_Tell( + "GaugeAlarmManager::Activate(" << entity << + ", " << subsystem << + ", " << condition << + ", " << new_resource_id << + ")\n"; + ); + Check(this); + + Check(application); + Check(application->GetResourceFile()); + //------------------------------------------- + // Attempt to find the specified resource + //------------------------------------------- + ResourceDescription + *stream_resource_description = + application->GetResourceFile()->SearchList( + new_resource_id, + ResourceDescription::GaugeAlarmStreamResourceType + ); + + if (stream_resource_description == NULL) + { + Test_Tell( + "GaugeAlarmManager::Activate: resource ID '" << new_resource_id << + "' does not exist\n" + ); + } + else + { + //------------------------------------------- + // Lock the stream + //------------------------------------------- + stream_resource_description->Lock(); + //------------------------------------------- + // Found it, open a DynamicMemoryStream + //------------------------------------------- + DynamicMemoryStream + *dynamic_memory_stream = + new DynamicMemoryStream( + stream_resource_description->resourceAddress, + stream_resource_description->resourceSize + ); + if (dynamic_memory_stream == NULL) + { + Test_Tell("GaugeAlarmManager::Activate: couldn't open stream\n"); + } + else + { + Register_Object(dynamic_memory_stream); + //------------------------------------------- + // Create the object, add to alarm list + //------------------------------------------- + GaugeAlarm + *alarm = new GaugeAlarm( + entity, + subsystem, + condition + ); + Register_Object(alarm); + gaugeAlarmList.Add(alarm); + //------------------------------------------- + // Read the alarm items from the stream + //------------------------------------------- + int + alarm_count; + MemoryStream_Read(dynamic_memory_stream, &alarm_count); + Verify(alarm_count > 0); + + for(; alarm_count>0; --alarm_count) + { + ReadGaugeAlarmStreamItem( + alarm, + entity, + subsystem, + condition, + dynamic_memory_stream + ); + } + //------------------------------------------- + // Destroy the stream + //------------------------------------------- + Unregister_Object(dynamic_memory_stream); + delete dynamic_memory_stream; + } + //------------------------------------------- + // Unlock the stream + //------------------------------------------- + stream_resource_description->Unlock(); + } + Check_Fpu(); +} + +void + GaugeAlarmManager::Deactivate( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ) +{ + Test_Tell( + "GaugeAlarmManager::Deactivate(" << entity << + ", " << subsystem << + ", " << condition << + ")\n"; + ); + Check(this); + //------------------------------------------- + // Find matching GaugeAlarm + //------------------------------------------- + ChainIteratorOf + i(gaugeAlarmList); + GaugeAlarm + *alarm_pointer; + + while ((alarm_pointer=i.ReadAndNext()) != NULL) + { + Check(alarm_pointer); + Test_Tell("pointer=" << alarm_pointer); + if (alarm_pointer->entity == entity) + { + if (alarm_pointer->subsystem == subsystem) + { + if (alarm_pointer->conditionIndex == condition) + { + Test_Tell("Found:"); + Unregister_Object(alarm_pointer); + delete alarm_pointer; + break; + } + } + } + Test_Tell("\n"); + } + Check_Fpu(); +} + + diff --git a/CODE/RP/MUNGA/GAUGALRM.HPP b/CODE/RP/MUNGA/GAUGALRM.HPP new file mode 100644 index 0000000..3b10dbd --- /dev/null +++ b/CODE/RP/MUNGA/GAUGALRM.HPP @@ -0,0 +1,128 @@ +//===========================================================================// +// File: gaugalrm.hpp // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/22/96 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(GAUGALRM_HPP) +# define GAUGALRM_HPP + + class GaugeAlarm; + class GaugeAlarmManager; + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(LAMP_HPP) +# include +# endif + + //####################################################################### + // GaugeAlarm + //####################################################################### + class GaugeAlarm : + public Node + { + friend class GaugeAlarmManager; + + protected: + GaugeAlarm( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ); + + ~GaugeAlarm(); + + public: + Logical + TestInstance() const; + protected: + Entity + *entity; + Subsystem + *subsystem; + int + conditionIndex; + public: + ChainOf // descendants of GaugeAlarmManager need to see this + lampList; + }; + + //####################################################################### + // GaugeAlarmManager + //####################################################################### + class GaugeAlarmManager SIGNATURED + { + friend class GaugeAlarm; + friend class GaugeRenderer; + protected: + GaugeAlarmManager(); + public: + virtual ~GaugeAlarmManager(); + //-------------------------------------------------------------------- + // Resource methods + //-------------------------------------------------------------------- + public: + ResourceDescription::ResourceID + CreateModelGaugeAlarmStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories */*directories*/ + ); + + virtual Logical + CreateGaugeAlarmStreamItem( + MemoryStream *mem_stream, + const char *alarm_name, + const char *alarm_data + ); + virtual void + ReadGaugeAlarmStreamItem( + GaugeAlarm *alarm, + Entity *the_entity, + Subsystem *the_subsystem, + Enumeration the_condition, + MemoryStream *mem_stream + ); + + void + RemoveAllAlarms(); + void + Activate( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID resource_ID + ); + void + Deactivate( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ); + + public: + Logical + TestInstance() const; + + protected: + ChainOf + gaugeAlarmList; + }; + +#endif + diff --git a/CODE/RP/MUNGA/GAUGE.TCP b/CODE/RP/MUNGA/GAUGE.TCP new file mode 100644 index 0000000..944919c --- /dev/null +++ b/CODE/RP/MUNGA/GAUGE.TCP @@ -0,0 +1,144 @@ +//==========================================================================// +// File: gauge.tst // +// Project: MUNGA Brick: Gauge module // +// Contents: Test code for gauge classes // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 02/10/95 CPB Initial coding. // +//--------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +class FakeGauge : + public Gauge +{ +public: + FakeGauge(GaugeRenderer *renderer, unsigned int owner_ID); + ~FakeGauge(); + + void + Execute(); + + Scalar + myScalar; +}; + +FakeGauge::FakeGauge(GaugeRenderer *renderer, unsigned int owner_ID) : + Gauge((GaugeRate) gaugeRate_A, (ModeMask) -1L, renderer, owner_ID) +{ + myScalar = 0.0f; +} + +FakeGauge::~FakeGauge() +{ +} + +void + FakeGauge::Execute() +{ + myScalar = 2.0f; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Gauge::TestClass() +{ +#if 0 + Tell("Starting Gauge test...\n"); + unsigned int fakeOwnerID(1); + + // + //-------------------------------------------------------- + // Test GaugeConnectionDirectOf... + //-------------------------------------------------------- + // + { + Scalar scalar1(0.0); + Scalar scalar2(1.5f); + // + // Create a GaugeConnection + // + GaugeConnectionDirectOf *instance1; + instance1 = new GaugeConnectionDirectOf(0, &scalar2, &scalar1); + Check(instance1); + Register_Object(instance1); + // + // Try it out + // + instance1->Update(); + Test(scalar2 == 0.0f); + // + // Destroy it + // + Unregister_Object(instance1); + delete instance1; + } + // + //-------------------------------------------------------- + // Test Gauge + //-------------------------------------------------------- + // + { + Scalar source(1.5f); + // + // Create a gauge + // + FakeGauge testGauge(NULL, fakeOwnerID); + Check(&testGauge); + Register_Object(&testGauge); + // + // Create a connection and add it to the gauge + // + GaugeConnectionDirectOf *instance1; + instance1 = new GaugeConnectionDirectOf( + 0, + &testGauge.myScalar, + &source + ); + Check(instance1); + Register_Object(instance1); + + testGauge.AddConnection(instance1); + #if 0 + // + // See if the connection works + // + Test(testGauge.myScalar == 0.0f); + testGauge.UpdateParameters(); + Test(testGauge.myScalar == 1.5f); + // + // See if Execute() occurs + // + testGauge.Execute(); + Test(testGauge.myScalar == 2.0f); + // + // Remove the connection, and ensure that the value doesn't change + // + testGauge.RemoveConnection(0); + source = 3.0f; + testGauge.UpdateParameters(); + Test(testGauge.myScalar == 2.0f); + #endif + // + // Everything seems ok! Unregister the gauge and delete it + // Note that RemoveConnection should have deleted the GaugeConnection. + // If it didn't, we'll hear about it when we check the + // remaining registered objects. + // + Unregister_Object(&testGauge); + } + // + //-------------------------------------------------------- + // Return test result + //-------------------------------------------------------- + // +#endif + return True; +} + diff --git a/CODE/RP/MUNGA/GAUGMAP.HPP b/CODE/RP/MUNGA/GAUGMAP.HPP new file mode 100644 index 0000000..27d3cd3 --- /dev/null +++ b/CODE/RP/MUNGA/GAUGMAP.HPP @@ -0,0 +1,165 @@ +//===========================================================================// +// File: gaugmap.hpp // +// Project: MUNGA Brick: Gauge Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/17/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(GAUGMAP_HPP) +# define GAUGMAP_HPP + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(SCALAR_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + + class Entity; + class GaugeEntityList; + class GaugeEntityArray; + class Derivation; + class Point3D; + + //####################################################################### + // GaugeEntityList + //####################################################################### + class GaugeEntityList : + public Node + { + public: + GaugeEntityList(); + ~GaugeEntityList(); + Logical + TestInstance() const; + void + Add(Entity *entity); + void + Remove(Entity *entity); + void + Clear(); + int + NumberOfItems(); + int + CopyEntities( + GaugeEntityList *destination, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Scalar min_x, + Scalar min_y, + Scalar min_z, + Scalar max_x, + Scalar max_y, + Scalar max_z, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Point3D *center, + Scalar radius, + Derivation *derivation_type = NULL + ); + + ChainOf * const + GetInstanceList() + { + return &instanceList; + } + protected: + ChainOf + instanceList; + }; + + //####################################################################### + // GaugeEntityArray + //####################################################################### + class GaugeEntityArray SIGNATURED + { + public: + GaugeEntityArray(); + ~GaugeEntityArray(); + Logical + TestInstance() const; + void + Add(Entity *entity); + void + Remove(Entity *entity); + void + Clear(); + void + PrintStatistics(); + int + CopyEntities( + GaugeEntityList *destination, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Scalar min_x, + Scalar min_y, + Scalar min_z, + Scalar max_x, + Scalar max_y, + Scalar max_z, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Point3D *center, + Scalar radius, + Derivation *derivation_type = NULL + ); + void + GetBounds( + Scalar *min_x, + Scalar *min_y, + Scalar *min_z, + Scalar *max_x, + Scalar *max_y, + Scalar *max_z + ); + + protected: + enum + { + gaugeMapArraySize=64 + }; + + int + ArrayOffset(Scalar n); + + Scalar + minimumX, + minimumY, + minimumZ, + maximumX, + maximumY, + maximumZ; + + GaugeEntityList + grid[gaugeMapArraySize][gaugeMapArraySize]; + }; + +#endif + diff --git a/CODE/RP/MUNGA/GRAPH2D.HPP b/CODE/RP/MUNGA/GRAPH2D.HPP new file mode 100644 index 0000000..ea091b9 --- /dev/null +++ b/CODE/RP/MUNGA/GRAPH2D.HPP @@ -0,0 +1,806 @@ +//===========================================================================// +// File: VGADisp.hh // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for LBE4 VGA display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/03/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(GRAPH2D_HPP) +# define GRAPH2D_HPP + +# if !defined(STYLE_HPP) +# include +# endif + +# if !defined(VECTOR2D_HPP) +# include +# endif + +# if !defined(RECT2D_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(PLUG_HPP) +# include +# endif + + class BitMap; + class PixelMap; + class GraphicsDisplay; + class GraphicsPort; + class GraphicsViewRecord; + class GraphicsView; + class NotationFile; + + //######################################################################## + //################################ BitMap ################################ + //######################################################################## + // + // The "raw" bit map is used by assembly-language routines. + // It must not be burdened with signatures, etc. + // + struct RawBitMap + { + Vector2DOf Size; + int WidthInWords; + Word *MapPointer; + }; + + class BitMap : + public Plug + { + public: + BitMap(int width, int height); + BitMap(int width, int height, Word *body); + BitMap(const char *filename); + BitMap(NotationFile *notation_file, const char *page_name); + ~BitMap(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + static BitMap * + Make(const char *file_name); + static BitMap * + Make(ResourceDescription::ResourceID new_resource_id); + + RawBitMap + Data; + }; + + //######################################################################## + //############################### Palette8 ############################### + //######################################################################## + + struct PaletteTriplet + { + Byte Red; //0..255 + Byte Green; //0..255 + Byte Blue; //0..255 + + friend ostream& + operator<<( + ostream& stream, + const PaletteTriplet& p + ); + + PaletteTriplet& + operator=(PaletteTriplet& t) + { + Red = t.Red; + Green = t.Green; + Blue = t.Blue; + return t; + } + Logical + operator==(const PaletteTriplet& t) const + { + return ((Red==t.Red) && (Green==t.Green) && (Blue==t.Blue)); + } + Logical + operator!=(const PaletteTriplet& t) const + { + return ((Red!=t.Red) || (Green!=t.Green) || (Blue!=t.Blue)); + } + }; + + class Palette8 SIGNATURED + { + friend class GraphicsPort; + + public: + Palette8(); + Palette8(int count, PaletteTriplet *source); + Palette8(const char *filename); + ~Palette8(); + + void + SetColorRange( + int start, + int end, + PaletteTriplet new_color + ); + void + BuildColorRange( + int start, + int end, + PaletteTriplet first_color, + PaletteTriplet last_color + ); + Logical + TestInstance() const; + void + ShowInstance(char *indent); + static Palette8 * + Make(const char *file_name); + static Palette8 * + Make(ResourceDescription::ResourceID new_resource_id); + + Logical + Valid; + + PaletteTriplet + Color[256]; + }; + + //######################################################################## + //############################## PixelMap8 ############################### + //######################################################################## + + // + // The "raw" pixel map is used by assembly-language routines. + // It must not be burdened with signatures, etc. + // + struct RawPixelMap8 + { + Vector2DOf Size; + Byte *MapPointer; + }; + + class PixelMap8 SIGNATURED + { + friend class GraphicsPort; + + public: + PixelMap8(int width, int height); + PixelMap8(Vector2DOf size); +// {PixelMap(size.x, size.y);} + PixelMap8(const char *filename); + PixelMap8() + { + Data.Size.x = 0; + Data.Size.y = 0; + Data.MapPointer = NULL; + } + ~PixelMap8(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + static PixelMap8 * + Make(const char *file_name); + static PixelMap8 * + Make(ResourceDescription::ResourceID new_resource_id); + + RawPixelMap8 + Data; + }; + + //######################################################################## + //############################## PixelMap16 ############################## + //######################################################################## + + // + // The "raw" pixel map is used by assembly-language routines. + // It must not be burdened with signatures, etc. + // + struct RawPixelMap16 + { + Vector2DOf Size; + Word *MapPointer; + }; + + class PixelMap16 SIGNATURED + { + friend class GraphicsPort; + + public: + PixelMap16(int width, int height); + PixelMap16(Vector2DOf size); +// {PixelMap(size.x, size.y);} + PixelMap16(char *filename); + PixelMap16() + { + Data.Size.x = 0; + Data.Size.y = 0; + Data.MapPointer = NULL; + } + ~PixelMap16(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + RawPixelMap16 + Data; + }; + + //######################################################################## + //########################### GraphicsDisplay ############################ + //######################################################################## + class GraphicsDisplay SIGNATURED + { + public: + enum Operation { + Replace=0, And, Or, Xor, NextOperation + }; + + enum FontNumber { + SystemFont=0, NextFontNumber + }; + + enum Justification { + Normal=0, + Left=0x00, Horizontal=0x01, Right=0x02, + Top=0x00, Vertical=0x04, Bottom=0x08 + }; + + public: + GraphicsDisplay(int x, int y); + + virtual ~GraphicsDisplay(); + + Logical + TestInstance() const; + + virtual void + ShowInstance(char *indent); + + virtual Logical + Update(Logical forceAll); + + virtual void + WaitForUpdate(); + + virtual Rectangle2D + TextBounds( + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + char *stringPointer + ); + + virtual void + DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ); + + virtual void + DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + virtual void + DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + virtual void + DrawText( + int color, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + virtual void + DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawBitMapOpaque( + int color, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + public: + Rectangle2D bounds; + }; + + //######################################################################## + //############################ GraphicsPort ############################## + //######################################################################## + class GraphicsPort SIGNATURED + { + public: + GraphicsPort( + GraphicsDisplay *graphics_display, + const char *name + ); + + virtual ~GraphicsPort(); + + Logical + TestInstance() const; + + virtual void + ShowInstance(char *indent); + + virtual Rectangle2D + TextBounds( + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + char *stringPointer + ); + + virtual void + SetColor( + PaletteTriplet *source_color, + int color_index + ); + + virtual void + DrawPoint( + int color, + Enumeration operation, + int x, int y + ); + + virtual void + DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + virtual void + DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + virtual void + DrawText( + int color, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + virtual void + DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + public: + Rectangle2D + bounds; + GraphicsDisplay + *graphicsDisplay; + + char + name[16]; + }; + + //######################################################################## + //######################### GraphicsViewRecord ########################### + //######################################################################## + class GraphicsViewRecord SIGNATURED + { + friend class GraphicsView; + public: + GraphicsViewRecord(); + ~GraphicsViewRecord(); + Logical + TestInstance() const; + void + Clear(); + void + Draw(GraphicsView *graphics_view, int forced_color=-1); + protected: + enum + { + endCommand=0, + pointCommand, + lineCommand, + frectCommand, + bitmapCommand, + bitmapOpaqueCommand, + pixelmap8Command, + pixelmap8SolidCommand, + }; + + void + PutChar(int value); + int + GetChar(); + void + PutLogical(Logical value); + Logical + GetLogical(); + void + PutShort(int value); + int + GetShort(); + void + PutPointer(void *pointer); + void * + GetPointer(); + + int + commandListLength, + commandListIndex; + char + *commandList; + GraphicsViewRecord + *link; + }; + + //######################################################################## + //############################ GraphicsView ############################## + //######################################################################## + class GraphicsView SIGNATURED + { + friend class GraphicsViewRecord; + public: + GraphicsView( + GraphicsPort *graphics_port, + int x1, int y1, int x2, int y2 + ); + + GraphicsView( + GraphicsPort *graphics_port + ); + + virtual ~GraphicsView(); + + Logical + TestInstance() const; + + virtual void + ShowInstance(char *indent); + + virtual void + SetPositionWithinPort( + int left, + int bottom, + int right, + int top + ); + + virtual void + SetOperation(GraphicsDisplay::Operation operation); + + virtual void + SetOrigin( + int x, + int y + ); + + virtual void + SetFont( + Enumeration new_font_ID + ); + + virtual void + SetColor( + int new_color + ); + + virtual void + SetClippingRectangle( + Rectangle2D *clippingRectangle + ); + + virtual void + ClearClippingRectangle(); + + virtual void + MoveToAbsolute( + int x, + int y + ); + + virtual void + MoveToRelative( + int x, + int y + ); + // + //----------------------------------------------------- + // These routines first clip the operation according to + // clippingRectangle of the GraphicsView. + // The clipped results are then passed on to the + // corresponding routine in the GraphicsPort object. + //----------------------------------------------------- + // + virtual void + DrawPoint(); + + virtual void + DrawLineToAbsolute(int x, int y); + + virtual void + DrawLineToRelative(int x, int y); + + virtual void + DrawThickLineToAbsolute(int x, int y); + + virtual void + DrawThickLineToRelative(int x, int y); + + virtual void + DrawRectangleToAbsolute(int x, int y); + + virtual void + DrawRectangleToRelative(int x, int y); + + virtual void + DrawFilledRectangleToAbsolute(int x, int y); + + virtual void + DrawFilledRectangleToRelative(int x, int y); + + virtual void + DrawText( + Logical opaque, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + virtual void + DrawBitMap( + int rotation, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMap( + int rotation, + BitMap *bitmap + ) + { + DrawBitMap( + rotation, + bitmap, + 0, 0, bitmap->Data.Size.x-1, bitmap->Data.Size.y-1 + ); + } + + virtual void + DrawBitMapOpaque( + int background, + int rotation, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int background, + int rotation, + BitMap *bitmap + ) + { + DrawBitMapOpaque( + background, + rotation, + bitmap, + 0, 0, bitmap->Data.Size.x-1, bitmap->Data.Size.y-1 + ); + } + + virtual void + DrawPixelMap8( + Logical opaque, + int rotation, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + Logical opaque, + int rotation, + PixelMap8 *pixelmap + ) + { + DrawPixelMap8( + opaque, + rotation, + pixelmap, + 0, 0, pixelmap->Data.Size.x-1, pixelmap->Data.Size.y-1 + ); + } + + virtual void + DrawPixelMap8SingleColor( + int rotation, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int rotation, + PixelMap8 *pixelmap + ) + { + DrawPixelMap8SingleColor( + rotation, + pixelmap, + 0, 0, pixelmap->Data.Size.x-1, pixelmap->Data.Size.y-1 + ); + } + + virtual void + AttachRecorder(GraphicsViewRecord *graphics_view_record); + virtual void + DetachRecorder(); + + enum PointCode{ + IsWithin=0, IsLeft=0x01, IsRight=0x02, IsBelow=0x04, IsAbove=0x08 + }; + + virtual int + BuildPointCode(Vector2DOf vector); + + Logical + ClipImage( + Rectangle2D *sourceRect, + Vector2DOf *position, + Vector2DOf imageLimits + ); + + virtual void + SetColor( + PaletteTriplet *source_color, + int color_index + ); + + protected: + void + DrawThickLine( + Vector2DOf start, + Vector2DOf end + ); + + void + DrawLine( + Vector2DOf start, + Vector2DOf end, + Logical include_last_pixel + ); + + void + DrawFilledRectangle(Rectangle2D r); + + Rectangle2D areaWithinPort; + Vector2DOf origin; + Vector2DOf currentPosition; + Enumeration currentFontID; + int currentColor; + Rectangle2D clippingRectangle; + GraphicsDisplay::Operation currentOperation; + GraphicsPort *graphicsPort; + GraphicsViewRecord *recorder; + }; + +#endif diff --git a/CODE/RP/MUNGA/HASH.CPP b/CODE/RP/MUNGA/HASH.CPP new file mode 100644 index 0000000..6868a7a --- /dev/null +++ b/CODE/RP/MUNGA/HASH.CPP @@ -0,0 +1,546 @@ +//===========================================================================// +// File: hash.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of Hash class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/15/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(HASH_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hash ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define Verify_Index(x) Verify(0 <= (x) && (x) < hashTableSize) + +// +//########################################################################### +// Hash +//########################################################################### +// +Hash::Hash( + CollectionSize size, + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + hashTableSize = size; + BuildHashTable(); +} + +void + Hash::BuildHashTable() +{ + int i; + +#if 0 + hashTable = (VChain**)malloc(hashTableSize * sizeof(VChain*)); +#else + hashTable = new VChain*[hashTableSize]; +#endif + Register_Pointer(hashTable); + + for (i = 0; i < hashTableSize; i++) + { + Check_Pointer(hashTable); + Verify_Index(i); + hashTable[i] = NULL; + } +} + +// +//########################################################################### +// ~Hash +//########################################################################### +// +Hash::~Hash() +{ + int i; + + for (i = 0; i < hashTableSize; i++) + { + Check_Pointer(hashTable); + Verify_Index(i); + if (hashTable[i] != NULL) + { + Unregister_Object(hashTable[i]); + delete hashTable[i]; + } + } + + Unregister_Pointer(hashTable); +#if 0 + free(hashTable); +#else + delete[] hashTable; +#endif + hashTable = NULL; + hashTableSize = 0; +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Hash::TestInstance() const +{ + SortedSocket::TestInstance(); + + Check_Pointer(hashTable); + Verify(hashTableSize > 0); + + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Hash::AddImplementation(Plug *plug) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + Hash::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + Check(this); + Check(plug); + Check_Pointer(value); + + // + //------------------------------------------------------------- + // Verify that value has not been added + //------------------------------------------------------------- + // + Verify(HasUniqueEntries() ? (FindImplementation(value) == NULL) : (Logical)True); + + // + //------------------------------------------------------------- + // Find hash entry + //------------------------------------------------------------- + // + IteratorPosition index; + + index = GetHashIndex(value); + + // + //------------------------------------------------------------- + // Get vchain for this index + //------------------------------------------------------------- + // + VChain *vchain; + + Check_Pointer(hashTable); + Verify_Index(index); + if ((vchain = hashTable[index]) == NULL) + { + vchain = MakeVChain(); + Register_Object(vchain); + hashTable[index] = vchain; + } + + // + //------------------------------------------------------------- + // Add to the vchain + //------------------------------------------------------------- + // + Check(vchain); + vchain->AddValuePlug(plug, value); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + Hash::FindImplementation( + const void *value + ) +{ + Check(this); + Check_Pointer(value); + + // + //------------------------------------------------------------- + // Find hash entry + //------------------------------------------------------------- + // + IteratorPosition index; + + index = GetHashIndex(value); + + // + //------------------------------------------------------------- + // Get vchain for this index + //------------------------------------------------------------- + // + VChain *vchain; + + Check_Pointer(hashTable); + Verify_Index(index); + if ((vchain = hashTable[index]) == NULL) + { + return NULL; + } + + // + //------------------------------------------------------------- + // Find in vchain + //------------------------------------------------------------- + // + Check(vchain); + return vchain->FindPlug(value); +} + +// +//########################################################################### +// MakeVChain +//########################################################################### +// +VChain* + Hash::MakeVChain() +{ + Fail("Hash::MakeVChain - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// MakeVChain +//########################################################################### +// +IteratorPosition + Hash::GetHashIndex(const void*) +{ + Fail("Hash::GetHashIndex - Should never reach here"); + return 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const IteratorPosition HashIteratorNullPosition = -1; + +// +//########################################################################### +// HashIterator +//########################################################################### +// +HashIterator::HashIterator(Hash *hash): + SortedIterator(hash) +{ + hashTable = hash->hashTable; + hashTableSize = hash->hashTableSize; + currentPosition = HashIteratorNullPosition; + vchainIterator = NULL; + First(); +} + +HashIterator::~HashIterator() +{ + hashTable = NULL; + hashTableSize = 0; + currentPosition = HashIteratorNullPosition; + DeleteVChainIterator(); +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + HashIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + Check_Pointer(hashTable); + Verify(hashTableSize > 0); + + if (vchainIterator != NULL) + { + Check(vchainIterator); + } + + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + HashIterator::First() +{ + NextVChainIterator(0); +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + HashIterator::Last() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + HashIterator::Next() +{ + if (vchainIterator != NULL) + { + Check(vchainIterator); + + if (vchainIterator->GetCurrentPlug() != NULL) + { + // + // Try to step to the next item in this list + // + vchainIterator->Next(); + } + if (vchainIterator->GetCurrentPlug() == NULL) + { + // + // At end of list, step to the next list + // + NextVChainIterator(currentPosition+1); + } + } +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + HashIterator::Previous() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *HashIterator::GetCurrentImplementation() +{ + if (vchainIterator != NULL) + { + Check(vchainIterator); + + if (vchainIterator->GetCurrentPlug() != NULL) + { + return vchainIterator->GetCurrentPlug(); + } + + // + // List was emptied, step to next list + // + NextVChainIterator(currentPosition+1); + + if (vchainIterator != NULL) + { + Check(vchainIterator); + Verify(vchainIterator->GetCurrentPlug() != NULL); + return vchainIterator->GetCurrentPlug(); + } + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + HashIterator::GetSize() +{ + HashIterator iterator(Cast_Object(Hash*, socket)); + CollectionSize i = 0; + + while (iterator.ReadAndNextImplementation() != NULL) + { + i++; + } + return(i); +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + HashIterator::Remove() +{ + if (vchainIterator != NULL) + { + Check(vchainIterator); + + if (vchainIterator->GetCurrentPlug() != NULL) + { + vchainIterator->Remove(); + return; + } + + // + // List was emptied, step to next list + // + NextVChainIterator(currentPosition+1); + + if (vchainIterator != NULL) + { + Check(vchainIterator); + vchainIterator->Remove(); + return; + } + } +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug + *HashIterator::FindImplementation( + const void* + ) +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + HashIterator::ReceiveMemo( + IteratorMemo, + void* + ) +{ +} + +// +//########################################################################### +//########################################################################### +// +void + HashIterator::DeleteVChainIterator() +{ + if (vchainIterator != NULL) + { + Unregister_Object(vchainIterator); + delete vchainIterator; + vchainIterator = NULL; + } +} + +// +//########################################################################### +//########################################################################### +// +void + HashIterator::NextVChainIterator(IteratorPosition index) +{ + int i; + + DeleteVChainIterator(); + currentPosition = HashIteratorNullPosition; + + for (i = index; i < hashTableSize; i++) + { + Check_Pointer(hashTable); + Verify_Index(i); + + if (hashTable[i] != NULL) + { + // + // This index contains a vchain + // + Check(hashTable[i]); + + // + // Create a vchain iterator + // + vchainIterator = new VChainIterator(hashTable[i]); + Register_Object(vchainIterator); + if (vchainIterator->GetCurrentPlug() != NULL) + { + // + // The vchain contains items + // + currentPosition = i; + return; + } + + // + // Destroy the vchain iterator + // + DeleteVChainIterator(); + } + } +} + +#if defined(TEST_CLASS) +# include "hash.tcp" +#endif diff --git a/CODE/RP/MUNGA/HASH.HPP b/CODE/RP/MUNGA/HASH.HPP new file mode 100644 index 0000000..7246966 --- /dev/null +++ b/CODE/RP/MUNGA/HASH.HPP @@ -0,0 +1,354 @@ +//===========================================================================// +// File: hash.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/15/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(HASH_HPP) +# define HASH_HPP + +# if !defined(SRTSKT_HPP) +# include +# endif + +# if !defined(VCHAIN_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hash ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Hash: + public SortedSocket + { + friend class HashIterator; + + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructor and Testing + //-------------------------------------------------------------------- + // + Hash( + CollectionSize size, + Node *node, + Logical has_unique_entries + ); + ~Hash(); + + Logical + TestInstance() const; + static Logical + TestClass(); + static Logical + ProfileClass(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + AddImplementation(Plug *plug); + void + AddValueImplementation( + Plug *plug, + const void *value + ); + Plug + *FindImplementation(const void *value); + + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + VChain **hashTable; + CollectionSize hashTableSize; + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + virtual VChain* + MakeVChain(); + + virtual IteratorPosition + GetHashIndex(const void *value); + + void + BuildHashTable(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class HashOf: + public Hash + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + HashOf( + CollectionSize size, + Node *node, + Logical has_unique_entries + ); + ~HashOf(); + + // + //-------------------------------------------------------------------- + // Socket methods (see Socket for full listing) + //-------------------------------------------------------------------- + // + void + AddValue( + T plug, + const V &value + ) + {AddValueImplementation(Cast_Object(Plug*,plug), &value);} + + T + Find(const V &value) + {return (T)FindImplementation(&value);} + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + VChain* + MakeVChain(); + + IteratorPosition + GetHashIndex(const void *value); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + HashOf::HashOf( + CollectionSize size, + Node *node, + Logical has_unique_entries + ): + Hash( + size, + node, + has_unique_entries + ) + { + } + + template + HashOf::~HashOf() + { + } + + template VChain* + HashOf::MakeVChain() + { + return new VChainOf(GetReleaseNode(), HasUniqueEntries()); + } + + template IteratorPosition + HashOf::GetHashIndex(const void *value) + { + Check_Pointer(value); + return (IteratorPosition(*(V*)value) % hashTableSize); + // return ((IteratorPosition)*(V*)value % hashTableSize); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class HashIterator: + public SortedIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors, Destructor and testing + //-------------------------------------------------------------------- + // + HashIterator(Hash *hash); + ~HashIterator(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + void + First(); + void + Last(); + void + Next(); + void + Previous(); + CollectionSize + GetSize(); + void + Remove(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + #if 0 + void* + ReadAndNextImplementation(); + void* + ReadAndPreviousImplementation(); + #endif + void* + GetCurrentImplementation(); + #if 0 + void* + GetNthImplementation(CollectionSize index); + #endif + Plug* + FindImplementation(const void *value); + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + ReceiveMemo( + IteratorMemo memo, + void *content + ); + + void + DeleteVChainIterator(); + + void + NextVChainIterator(IteratorPosition index); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + VChain + **hashTable; + CollectionSize + hashTableSize; + IteratorPosition + currentPosition; + VChainIterator + *vchainIterator; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class HashIteratorOf: + public HashIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors and Destructor + //-------------------------------------------------------------------- + // + HashIteratorOf(HashOf *hash); + HashIteratorOf(HashOf &hash); + ~HashIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T + ReadAndNext() + {return (T)ReadAndNextImplementation();} + T + ReadAndPrevious() + {return (T)ReadAndPreviousImplementation();} + T + GetCurrent() + {return (T)GetCurrentImplementation();} + T + GetNth(CollectionSize index) + {return (T)GetNthImplementation(index);} + T + Find(const V &value) + {return (T)FindImplementation(&value);} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + HashIteratorOf::HashIteratorOf(HashOf *hash): + HashIterator(hash) + { + } + + template + HashIteratorOf::HashIteratorOf(HashOf &hash): + HashIterator(&hash) + { + } + + template + HashIteratorOf::~HashIteratorOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/HASH.TCP b/CODE/RP/MUNGA/HASH.TCP new file mode 100644 index 0000000..634864c --- /dev/null +++ b/CODE/RP/MUNGA/HASH.TCP @@ -0,0 +1,420 @@ +//===========================================================================// +// File: hash.tst // +// Project: MUNGA Brick: Connection Library // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/15/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "time.hpp" + +class HashTestPlug: + public Plug +{ +public: + int value; + + HashTestPlug(int value); + ~HashTestPlug(); +}; + +class HashTestNode: + public Node +{ +public: + HashOf hash1; + HashOf hash2; + + HashTestNode(); + ~HashTestNode(); + + void RunProfile(); + void RunTest(); +}; + +#define RandInt(x) (rand() % x + 1) + +HashTestPlug::HashTestPlug(int value): + Plug() +{ + this->value = value; +} + +HashTestPlug::~HashTestPlug() +{ +} + +HashTestNode::HashTestNode(): + Node(), + hash1(TEST_CLASS/2, this, True), + hash2(TEST_CLASS/2, this, True) +{ +} + +HashTestNode::~HashTestNode() +{ +} + +// +//########################################################################### +// ProfileClass +//########################################################################### +// + +Logical + Hash::ProfileClass() +{ + HashTestNode testNode; + Time startTicks = Now(); + + Test_Message("Hash::ProfileClass \n"); + + testNode.RunProfile(); + + Test_Message("Hash::ProfileClass elapsed = " << (Now() - startTicks) << endl); + return True; +} + +// +//########################################################################### +// TestClass +//########################################################################### +// + +Logical + Hash::TestClass() +{ + DEBUG_STREAM << "Starting Hash test...\n"; + + HashTestNode testNode; + + testNode.RunTest(); + return True; +} + +void + HashTestNode::RunProfile() +{ + HashTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; + Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Run timing tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + startTicks = Now(); + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new HashTestPlug(values[i]); + Register_Object( testPlug1 ); + hash1.AddValue(testPlug1, values[i]); + hash2.AddValue(testPlug1, values[i]); + } + Test_Message("HashTestNode::RunTest Create = " << (Now() - startTicks) << endl); + + /* + * Iterate over both sockets + */ + startTicks = Now(); + { + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + i++; + } + Verify( i == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator2.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + i++; + } + Verify( i == TEST_CLASS ); + } + Test_Message("HashTestNode::RunTest Iterate = " << (Now() - startTicks) << endl); + + /* + * Find + */ + startTicks = Now(); + { + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = hash1.Find(i); + testPlug2 = hash2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + } + } + Test_Message("HashTestNode::RunTest Find = " << (Now() - startTicks) << endl); + + /* + * Destroy from hash1, verify with hash2 + */ + startTicks = Now(); + { + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + i++; + + Unregister_Object(testPlug1); + delete(testPlug1); + } + Verify( i == TEST_CLASS ); + Verify( iterator2.GetCurrent() == NULL ); + } + Test_Message("HashTestNode::RunTest Destroy = " << (Now() - startTicks) << endl); +} + +void + HashTestNode::RunTest() +{ + HashTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; +// Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Stress tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new HashTestPlug(values[i]); + Register_Object( testPlug1 ); + hash1.AddValue(testPlug1, values[i]); + hash2.AddValue(testPlug1, values[i]); + } + + /* + * Find + */ + { + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = hash1.Find(i); + testPlug2 = hash2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + Verify( testPlug1 == testPlug2 ); + } + } + + /* + * Test first and last + */ + { + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + iterator1.First(); + iterator2.First(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + } + + /* + * Test next and prev + */ + { + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + iterator1.Next(); + iterator2.Next(); + + i++; + } + Verify( i == TEST_CLASS ); + } + + /* + * Test read next and read prev + */ + { + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + testPlug2 = iterator2.ReadAndNext(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + i++; + } + Verify( i == TEST_CLASS ); + } + + /* + * Test Remove + */ + { + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + iterator1.Remove(); + + Unregister_Object(testPlug1); + delete(testPlug1); + + i++; + } + Verify( iterator2.GetCurrent() == NULL ); + Verify( i == TEST_CLASS ); + } + + /* + * Test random deletion + */ + /* + * Add plugs to both sockets + */ + { + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + Verify( iterator1.GetCurrent() == NULL ); + Verify( iterator2.GetCurrent() == NULL ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new HashTestPlug(values[i]); + Register_Object( testPlug1 ); + hash1.AddValue(testPlug1, values[i]); + hash2.AddValue(testPlug1, values[i]); + } + } + + /* + * Perform random deletion + */ + { + int size, index; + HashIteratorOf iterator1(hash1); + HashIteratorOf iterator2(hash2); + + i = 0; + iterator1.First(); + while((size = iterator1.GetSize()) != 0) + { + index = RandInt(size) - 1; + testPlug1 = iterator1.GetNth(index); + Check( testPlug1 ); + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(index); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + { + HashIteratorOf iterator3(hash1); + + while ((testPlug1 = iterator3.ReadAndNext()) != NULL) + { + Check(testPlug1); + } + } + + i++; + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetCurrent() == NULL ); + Verify( iterator2.GetCurrent() == NULL ); + } +} + diff --git a/CODE/RP/MUNGA/HEAP.HPP b/CODE/RP/MUNGA/HEAP.HPP new file mode 100644 index 0000000..af4025f --- /dev/null +++ b/CODE/RP/MUNGA/HEAP.HPP @@ -0,0 +1,121 @@ +//--------------------------------------------------------------------------- +// +// Heap.h -- This file contains the definition for the Base HEAP +// Manager Class. The Base HEAP manager creates, +// manages and destroys block of memory using Win32 +// virtual memory calls. +// +// Honor Bound -- FASA Interactive Technologies +// +// Copyright (c) 1995 FASA Interactive Technologies +// +//--------------------------------------------------------------------------- + +#if !defined(HEAP_HPP) +# define HEAP_HPP + + #if !defined(STYLE_HPP) + #include + #endif + +# if !defined(MEMREG_HPP) +# include +# endif + + struct HeapBlock; + struct HeapFreeBlock; + + class UserHeap SIGNATURED + { + protected: + char + *bigHeap; + const char + *heapName; + HeapBlock + *heapStart, + *firstNearBlock; + size_t + heapSize, + lowestTotalHeapLeft; + size_t + allocateCount, + releaseCount; + + protected: + void + Relink(HeapBlock *newBlock); + void + Unlink(HeapBlock *oldBlock); + void + Sort(HeapBlock *sortBlock); + void + MergeWithLower(HeapBlock *block); + + public: + UserHeap( + const char* heap_name, + size_t mem_size + ); + ~UserHeap(); + + size_t + GetTotalHeapLeft(); + size_t + GetBiggestHeapLeft(); + size_t + GetLowestTotalHeapLeft() + {return lowestTotalHeapLeft;} + size_t + GetHeapUsed() + {return heapSize - GetTotalHeapLeft();} + size_t + GetMostHeapUsed() + {return heapSize - lowestTotalHeapLeft;} + + Logical + TestHeap( + Logical print_it = False, + Logical skip_allocated = False, + Logical skip_free = False + ); + + void* + Allocate(size_t mem_size); + void + Release(void *where); + void + ReleaseAll(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Global memory allocation + // + protected: + static LWord + HeapMark; + Logical + mainHeap; + + public: + static UserHeap + MainStorage; + + static size_t + GetMainHeapInitialSize(); + + friend void* + operator new(size_t mem_size); + friend void* + operator new(size_t mem_size, void* where); + friend void + operator delete(void *mem_block); + }; + + void* + Get_Caller(int levels); + +#endif + diff --git a/CODE/RP/MUNGA/HOST.CPP b/CODE/RP/MUNGA/HOST.CPP new file mode 100644 index 0000000..652dadf --- /dev/null +++ b/CODE/RP/MUNGA/HOST.CPP @@ -0,0 +1,159 @@ +//===========================================================================// +// File: host.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for base Host class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/28/94 ECH Initial coding. // +// 11/03/94 ECH Develop to munga spec // +// 11/29/94 JMA Moved EntityID to entity.cc // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(HOST_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +//############################################################################# +//################################ Host ################################# +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +Host::Host( + HostID host_ID, + HostType host_type, + NetworkAddress network_address +): + hostType(host_type), + allEntitySocket(NULL), + dynamicMasterEntitySocket(NULL), + dynamicReplicantEntitySocket(NULL) +{ + Verify(host_ID >= FirstLegalHostID); + hostID = host_ID; + networkAddress = network_address; + currentConnectStatus = NoNetworkConnectionStatus; +} + +// +//############################################################################# +//############################################################################# +// +Host::~Host() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Host::TestInstance() const +{ + Node::TestInstance(); + + Verify(hostID >= FirstLegalHostID); + Verify( + hostType == GameMachineHostType || + hostType == MissionReviewHostType || + hostType == ConsoleHostType + ); + Check(&allEntitySocket); + Check(&dynamicMasterEntitySocket); + Check(&dynamicReplicantEntitySocket); + + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + Host::AddEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + // Add entity to all socket + // + allEntitySocket.Add(entity); + + // + // Conditionally add entity to aux sockets + // + switch (entity->GetInstance()) + { + case Entity::MasterInstance: + case Entity::IndependantInstance: + case Entity::HermitInstance: + if (entity->IsDynamic()) + { + dynamicMasterEntitySocket.Add(entity); + } + break; + + case Entity::ReplicantInstance: + if (entity->IsDynamic()) + { + dynamicReplicantEntitySocket.Add(entity); + } + break; + + default: + Fail("Host::AddEntity - Should never reach here"); + break; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~ Host__AllEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Host__AllEntityIterator::Host__AllEntityIterator(Host *host): + SChainIteratorOf(&host->allEntitySocket) +{ +} + +Host__AllEntityIterator::~Host__AllEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~ Host__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~~~~~~~ + +Host__DynamicMasterEntityIterator:: + Host__DynamicMasterEntityIterator(Host *host): + SChainIteratorOf(&host->dynamicMasterEntitySocket) +{ +} + +Host__DynamicMasterEntityIterator::~Host__DynamicMasterEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~ Host__DynamicReplicantEntityIterator ~~~~~~~~~~~~~~~~~~~ + +Host__DynamicReplicantEntityIterator:: + Host__DynamicReplicantEntityIterator(Host *host): + SChainIteratorOf(&host->dynamicReplicantEntitySocket) +{ +} + +Host__DynamicReplicantEntityIterator::~Host__DynamicReplicantEntityIterator() +{ +} + + diff --git a/CODE/RP/MUNGA/HOST.HPP b/CODE/RP/MUNGA/HOST.HPP new file mode 100644 index 0000000..c64a999 --- /dev/null +++ b/CODE/RP/MUNGA/HOST.HPP @@ -0,0 +1,238 @@ +//===========================================================================// +// File: host.hpp // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for base Host class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/28/94 ECH Initial coding. // +// 11/03/94 ECH Develop to munga spec // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(HOST_HPP) +# define HOST_HPP + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(HOSTID_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(NETWORK_HPP) +# include +# endif + + class Entity; + + //########################################################################## + //####### Support types for entity identity and host manager ######### + //########################################################################## + + enum HostType + { + GameMachineHostType, + CameraShipHostType, + MissionReviewHostType, + ConsoleHostType + }; + + //########################################################################## + //############################ Host ################################## + //########################################################################## + + class Host: + public Node + { + friend class HostManager; + + friend class Host__AllEntityIterator; + friend class Host__DynamicMasterEntityIterator; + friend class Host__DynamicReplicantEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + typedef Host__AllEntityIterator + AllEntityIterator; + + // + // NoNetworkConnectionStatus - + // Initial state, host just created with no net link + // OpeningConnectionStatus - + // Waiting for completion of an active open to this host + // ListeningConnectionStatus - + // Waiting for this host to connect to us + // OnLineConnectionStatus - + // Host is on-line and ready + // + enum ConnectionStatus + { + NoNetworkConnectionStatus, + OpeningConnectionStatus, + ListeningConnectionStatus, + OnLineConnectionStatus + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and testing + // + public: + Host( + HostID host_ID, + HostType host_type, + NetworkAddress network_address + ); + ~Host(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessors + // + public: + HostType + GetHostType(); + HostID + GetHostID(); + + NetworkAddress + GetNetworkAddress(); + void + SetNetworkAddress(NetworkAddress network_address); + + ConnectionStatus + GetConnectStatus(); + void + SetConnectStatus(ConnectionStatus new_status); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Host Manager support + // + private: + void + AddEntity(Entity *entity); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + HostID + hostID; + HostType + hostType; + NetworkAddress + networkAddress; + ConnectionStatus + currentConnectStatus; + + // + // The all entity socket contains all entities that are on this host. + // + SChainOf + allEntitySocket; + + // + // The dynamic master entity socket contains all entities that are + // masters and dynamic + // + SChainOf + dynamicMasterEntitySocket; + + // + // The dynamic replicant entity socket contains all entities that are + // replicants and dynamic + // + SChainOf + dynamicReplicantEntitySocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Host inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline HostType + Host::GetHostType() + { + Check(this); + return hostType; + } + + inline HostID + Host::GetHostID() + { + Check(this); + return hostID; + } + + inline NetworkAddress + Host::GetNetworkAddress() + { + Check(this); + return networkAddress; + } + + inline void + Host::SetNetworkAddress(NetworkAddress network_address) + { + Check(this); + Verify(networkAddress == NullNetworkAddress); + Verify(network_address != NullNetworkAddress); + networkAddress = network_address; + } + + inline Host::ConnectionStatus + Host::GetConnectStatus() + { + Check(this); + return currentConnectStatus; + } + + inline void + Host::SetConnectStatus(ConnectionStatus new_status) + { + Check(this); + currentConnectStatus = new_status; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~ Host__AllEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Host__AllEntityIterator: + public SChainIteratorOf + { + public: + Host__AllEntityIterator(Host *host); + ~Host__AllEntityIterator(); + }; + + //~~~~~~~~~~~~~~~~~~~~ Host__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~~~~~ + + class Host__DynamicMasterEntityIterator: + public SChainIteratorOf + { + public: + Host__DynamicMasterEntityIterator(Host *host); + ~Host__DynamicMasterEntityIterator(); + }; + + //~~~~~~~~~~~~~~~~~~~ Host__DynamicReplicantEntityIterator ~~~~~~~~~~~~~~~~~ + + class Host__DynamicReplicantEntityIterator: + public SChainIteratorOf + { + public: + Host__DynamicReplicantEntityIterator(Host *host); + ~Host__DynamicReplicantEntityIterator(); + }; + +#endif + diff --git a/CODE/RP/MUNGA/HOST.TCP b/CODE/RP/MUNGA/HOST.TCP new file mode 100644 index 0000000..cfc587f --- /dev/null +++ b/CODE/RP/MUNGA/HOST.TCP @@ -0,0 +1,56 @@ +//===========================================================================// +// File: host.tst // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for base Host class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/07/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +void + HostManager::TestClass() +{ + DEBUG_STREAM << "Starting Host test...\n"; + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Host *local_host; + + local_host = new Host( + FirstLegalHostID, + GameMachineHostType, + (NetworkAddress)1 + ); + Register_Object(local_host); + + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptLocalHost(local_host); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + HostID localHostID; + + Check(application); + localHostID = application->GetHostManager()->GetLocalHostID(); + Verify(localHostID != NullHostID); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + EntityID newEntityID; + + Check(application); + newEntityID = application->GetHostManager()->MakeUniqueEntityID(); + Verify(newEntityID != EntityID::Null); +} diff --git a/CODE/RP/MUNGA/HOSTID.HPP b/CODE/RP/MUNGA/HOSTID.HPP new file mode 100644 index 0000000..24ddf22 --- /dev/null +++ b/CODE/RP/MUNGA/HOSTID.HPP @@ -0,0 +1,34 @@ +//===========================================================================// +// File: network.hh // +// Project: MUNGA Brick: Network Manager // +// Contents: Interface specification for network brick // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/01/94 JMA Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/03/94 ECH Changed NetworkClient to inherit from Node // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(HOSTID_HPP) +# define HOSTID_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + // + //--------------------------------------------------- + // Support types for host manager + //--------------------------------------------------- + // + typedef Enumeration HostID; + + const HostID NullHostID = 0; + const HostID MapHostID = -1; + const HostID FirstLegalHostID = 1; + +#endif diff --git a/CODE/RP/MUNGA/HOSTMGR.CPP b/CODE/RP/MUNGA/HOSTMGR.CPP new file mode 100644 index 0000000..2a1c143 --- /dev/null +++ b/CODE/RP/MUNGA/HOSTMGR.CPP @@ -0,0 +1,733 @@ +//===========================================================================// +// File: hostmgr.cpp // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for base Host class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/28/94 ECH Initial coding. // +// 11/03/94 ECH Develop to munga spec // +// 11/29/94 JMA Moved EntityID to entity.cc // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(HOSTMGR_HPP) +# include +#endif + +#if !defined(INTEREST_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +//############################################################################# +//######################### HostManager ################################# +//############################################################################# + +// +// HACK - EntitySocketHashSize should come from somewhere else +// +const CollectionSize EntitySocketHashSize = 500; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HostManager data +// +HostManager::SharedData + HostManager::DefaultData( + HostManager::ClassDerivations, + HostManager::MessageHandlers + ); + +Derivation + HostManager::ClassDerivations( + NetworkClient::ClassDerivations, + "HostManager" + ); + +const Receiver::HandlerEntry + HostManager::MessageHandlerEntries[]= +{ + { + HostManager::NewHostMessageID, + "NewHost", + (HostManager::Handler)&Receiver::DefaultMessageHandler // HACK + }, + { + HostManager::HostUpdateMessageID, + "HostUpdate", + (HostManager::Handler)&Receiver::DefaultMessageHandler // HACK + }, + { + HostManager::EntityTransferOwnershipMessageID, + "EntityTransferOwnership", + (HostManager::Handler)&HostManager::EntityTransferOwnershipHandler + }, + { + HostManager::EntityNewOwnershipMessageID, + "EntityNewOwnership", + (HostManager::Handler)&HostManager::EntityNewOwnershipHandler + } +}; + +Receiver::MessageHandlerSet + HostManager::MessageHandlers( + ELEMENTS(HostManager::MessageHandlerEntries), + HostManager::MessageHandlerEntries, + Receiver::MessageHandlers + ); + +// +//############################################################################# +// HostManager +//############################################################################# +// +HostManager::HostManager(): + NetworkClient(HostManagerClassID, DefaultData, HostManagerClientID), + remoteHostSocket(NULL, True), + allHostSocket(NULL, True), + entityIndexSocket(EntitySocketHashSize, NULL, True) +{ + localHost = NULL; + allHostIterator = NULL; +} + +// +//############################################################################# +//############################################################################# +// +HostManager::~HostManager() +{ + if (allHostIterator != NULL) + { + Unregister_Object(allHostIterator); + delete allHostIterator; + allHostIterator = NULL; + } + + Verify(localHost == NULL); + + #if DEBUG_LEVEL>0 + { + TableIteratorOf iterator(&remoteHostSocket); + Check(&iterator); + Verify(iterator.GetSize() == 0); + } + #endif + + #if DEBUG_LEVEL>0 + { + HashIteratorOf iterator(&entityIndexSocket); + Check(&iterator); + Verify(iterator.GetSize() == 0); + } + #endif +} + +// +//############################################################################# +//############################################################################# +// +Logical + HostManager::TestInstance() const +{ + if (!IsDerivedFrom(ClassDerivations)) + { + return False; + } + + if (localHost != NULL) + { + Check(localHost) + } + if (allHostIterator != NULL) + { + Check(allHostIterator) + } + Check(&remoteHostSocket); + Check(&allHostSocket); + Check(&lastEntityID); + Check(&entityIndexSocket); + return True; +} + +// +//############################################################################# +// Shutdown +//############################################################################# +// +void + HostManager::Shutdown() +{ + Check(this); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // For (each transferrable entity) + //-------------------------------------------------------------------------- + // + // + // Find new host for ownership + // + + // + // Send transfer entity ownership to that host + // + #else + // + //-------------------------------------------------------------------------- + // Delete all of the entities + //-------------------------------------------------------------------------- + // + if (localHost != NULL) + { + Check(localHost); + Host::AllEntityIterator iterator(localHost); + Check(&iterator); + iterator.DeletePlugs(); + } + #endif +} + +// +//############################################################################# +// AdoptLocalHost +//############################################################################# +// +void + HostManager::AdoptLocalHost(Host *local_host) +{ + Check(this); + Check(local_host); + + // + //-------------------------------------------------------------------------- + // Verify that the local host is currently unassigned and then assign it + //-------------------------------------------------------------------------- + // + Verify(lastEntityID == EntityID::Null); + Verify(localHost == NULL); + localHost = local_host; + + EntityID entity_ID(local_host->GetHostID()); + lastEntityID = entity_ID; + + // + //-------------------------------------------------------------------------- + // Add the local host to the all host socket + //-------------------------------------------------------------------------- + // + allHostSocket.AddValue(local_host, local_host->GetHostID()); +} + +// +//############################################################################# +// OrphanLocalHost +//############################################################################# +// +Host* + HostManager::OrphanLocalHost() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Unassign the local host + //-------------------------------------------------------------------------- + // + Host *local_host = localHost; + localHost = NULL; + lastEntityID = EntityID::Null; + + // + //-------------------------------------------------------------------------- + // Remove the local host from the all host socket + //-------------------------------------------------------------------------- + // + if (local_host != NULL) + { + Check(local_host); + PlugIterator remover(local_host); + remover.RemoveSocket(&allHostSocket); + } + return local_host; +} + +// +//############################################################################# +// AdoptRemoteHost +//############################################################################# +// +void + HostManager::AdoptRemoteHost(Host *remote_host) +{ + Check(this); + Check(remote_host); + + // + //-------------------------------------------------------------------------- + // Add to the remote and all host socket + //-------------------------------------------------------------------------- + // + remoteHostSocket.AddValue(remote_host, remote_host->GetHostID()); + allHostSocket.AddValue(remote_host, remote_host->GetHostID()); +} + +// +//############################################################################# +// OrphanRemoteHost +//############################################################################# +// +void + HostManager::OrphanRemoteHost(Host *remote_host) +{ + Check(this); + Check(remote_host); + + // + //-------------------------------------------------------------------------- + // Remove from the remote and all host socket + //-------------------------------------------------------------------------- + // + { + PlugIterator remover(remote_host); + remover.RemoveSocket(&remoteHostSocket); + } + { + PlugIterator remover(remote_host); + remover.RemoveSocket(&allHostSocket); + } +} + +// +//############################################################################# +// GetLocalHostID +//############################################################################# +// +HostID + HostManager::GetLocalHostID() +{ + Check(this); + Check(localHost); + return localHost->GetHostID(); +} + +// +//############################################################################# +// GetRemoteHost +//############################################################################# +// +Host* + HostManager::GetRemoteHost(HostID host_ID) +{ + Check(this); + Verify(host_ID >= FirstLegalHostID); + + return remoteHostSocket.Find(host_ID); +} + +// +//############################################################################# +// GetConsoleHost +//############################################################################# +// +Host* + HostManager::GetConsoleHost() +{ + Check(this); + + Host *host; + TableIteratorOf iterator(&remoteHostSocket); + + Check(&iterator); + while ((host = iterator.ReadAndNext()) != NULL) + { + Check(host); + if (host->GetHostType() == ConsoleHostType) + return host; + } + return NULL; +} + +// +//############################################################################# +// FindHost +//############################################################################# +// +Host* + HostManager::FindHost(NetworkAddress net_address) +{ + Check(this); + + Host *host; + TableIteratorOf iterator(&allHostSocket); + + Check(&iterator); + while ((host = iterator.ReadAndNext()) != NULL) + { + Check(host); + if (host->GetNetworkAddress() == net_address) + { + return host; + } + } + return NULL; +} + +// +//############################################################################# +// MakeUniqueEntityID +//############################################################################# +// +EntityID + HostManager::MakeUniqueEntityID() +{ + Check(this); + Verify(lastEntityID != EntityID::Null); + + return (lastEntityID += 1); +} + +// +//############################################################################# +// NotifyOfEntityCreation +//############################################################################# +// +void + HostManager::NotifyOfEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // The host keeps track of all entities + //-------------------------------------------------------------------------- + // + Check(localHost); + localHost->AddEntity(entity); + + // + //-------------------------------------------------------------------------- + // Link the entity to our index + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Check(&entityIndexSocket); + entityIndexSocket.AddValue(entity, entity->GetEntityID()); + + // + //-------------------------------------------------------------------------- + // Call interest manager + //-------------------------------------------------------------------------- + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->NotifyOfEntityCreation( + entity, + creation_message + ); +} + +// +//############################################################################# +// NotifyOfReplacementEntityCreation +//############################################################################# +// +void + HostManager::NotifyOfReplacementEntityCreation( + Entity*, + EntityID, + ClassID, + LWord + ) +{ + Fail("HostManager::NotifyOfReplacementEntityCreation - under construction"); +} + +// +//############################################################################# +// NotifyOfEntityDestruction +//############################################################################# +// +void + HostManager::NotifyOfEntityDestruction(Entity *entity) +{ + // + //-------------------------------------------------------------------------- + // Perform any additional processing here... + //-------------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------------- + // Notify interest manager of the destruction + //-------------------------------------------------------------------------- + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->NotifyOfEntityDestruction(entity); +} + +// +//############################################################################# +// IdentifyNewMapEntityHost +//############################################################################# +// +HostID + HostManager::IdentifyNewMapEntityHost( + EntityID + ) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // HACK - Partial Implementation, since the entity IDs are not yet + // precomputed several assumptions are made. 1) The map stream read by each + // pilot is identical. 2) All of the hosts are connected at the point that + // the stream is read. => Therefore, it is easy to allocate the entities to + // each host. + //-------------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------------- + // Verify that legal map entity hosts exist + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + { + TableIteratorOf iterator(&allHostSocket); + Host *host; + CollectionSize legal_map_entity_hosts = 0; + + while ((host = iterator.ReadAndNext()) != NULL) + { + if (host->GetHostType() == GameMachineHostType) + { + legal_map_entity_hosts++; + } + } + Verify(legal_map_entity_hosts > 0); + } + #endif + + // + //-------------------------------------------------------------------------- + // Check the host iterator + //-------------------------------------------------------------------------- + // + if (allHostIterator == NULL) + { + allHostIterator = new TableIteratorOf(&allHostSocket); + Register_Object(allHostIterator); + } + Check(allHostIterator); + + // + //-------------------------------------------------------------------------- + // Get a legal map entity host + //-------------------------------------------------------------------------- + // + Host *map_entity_host; + Logical is_legal_map_entity_host = False; + + do + { + if ((map_entity_host = allHostIterator->GetCurrent()) == NULL) + { + allHostIterator->First(); + map_entity_host = allHostIterator->GetCurrent(); + } + Check(map_entity_host); + if (map_entity_host->GetHostType() == GameMachineHostType) + { + is_legal_map_entity_host = True; + } + else + { + allHostIterator->Next(); + } + } + while (!is_legal_map_entity_host); + + // + //-------------------------------------------------------------------------- + // Move to the next host + //-------------------------------------------------------------------------- + // + allHostIterator->Next(); + + // + //-------------------------------------------------------------------------- + // Return the map entity host ID + //-------------------------------------------------------------------------- + // + Check(map_entity_host); + Verify(map_entity_host->GetHostType() == GameMachineHostType); + Verify(map_entity_host->GetHostID() != NullHostID); + + return map_entity_host->GetHostID(); +} + +// +//############################################################################# +// EntityTransferOwnership +//############################################################################# +// +void + HostManager::EntityTransferOwnershipHandler( + EntityTransferOwnershipMessage* + ) +{ + #if 0 + // + // Find replicant for this entity + // + + // + // If (replicant found) + // + // + // Morph the replicant into the master replicant + // + + // + // If (the replicant was not found) + // + // + // Make a transferred master entity + // + + // + // Broadcast new entity ownership + // + #else + Fail("HostManager::EntityTransferOwnershipHandler - under construction"); + #endif +} + +// +//############################################################################# +// EntityNewOwnership +//############################################################################# +// +void + HostManager::EntityNewOwnershipHandler( + EntityNewOwnershipMessage* + ) +{ + #if 0 + // + // If (this host is the owner host) + // + // + // Return + // + + // + // Find the replicant for this entity + // + // + // If (found the replicant) + // + // + // Point it at the new owner + // + #else + Fail("HostManager::EntityNewOwnershipHandler - under construction"); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllEntityIterator ~~~~~~~~~~~~~~~~~~~~~ + +HostManager__AllEntityIterator::HostManager__AllEntityIterator( + HostManager *host_manager +): + Host__AllEntityIterator(host_manager->localHost) +{ +} + +HostManager__AllEntityIterator::~HostManager__AllEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~ HostManager__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~~~ + +HostManager__DynamicMasterEntityIterator:: + HostManager__DynamicMasterEntityIterator( + HostManager *host_manager + ): + Host__DynamicMasterEntityIterator(host_manager->localHost) +{ +} + +HostManager__DynamicMasterEntityIterator:: + ~HostManager__DynamicMasterEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~ HostManager__DynamicReplicantEntityIterator ~~~~~~~~~~~~~~~ + +HostManager__DynamicReplicantEntityIterator:: + HostManager__DynamicReplicantEntityIterator( + HostManager *host_manager + ): + Host__DynamicReplicantEntityIterator(host_manager->localHost) +{ +} + +HostManager__DynamicReplicantEntityIterator:: + ~HostManager__DynamicReplicantEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__RemoteHostIterator ~~~~~~~~~~~~~~~~~~~~ + +HostManager__RemoteHostIterator::HostManager__RemoteHostIterator( + HostManager *host_manager +): + TableIteratorOf(&host_manager->remoteHostSocket) +{ +} + +HostManager__RemoteHostIterator::~HostManager__RemoteHostIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllHostIterator ~~~~~~~~~~~~~~~~~~~~~~~ + +HostManager__AllHostIterator::HostManager__AllHostIterator( + HostManager *host_manager +): + TableIteratorOf(&host_manager->allHostSocket) +{ +} + +HostManager__AllHostIterator::~HostManager__AllHostIterator() +{ +} + +#if 0 +# if defined(TEST_CLASS) +# include "host.tcp" +# endif +#endif diff --git a/CODE/RP/MUNGA/HOSTMGR.HPP b/CODE/RP/MUNGA/HOSTMGR.HPP new file mode 100644 index 0000000..99f6821 --- /dev/null +++ b/CODE/RP/MUNGA/HOSTMGR.HPP @@ -0,0 +1,404 @@ +//===========================================================================// +// File: hostmgr.hpp // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for base Host class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/28/94 ECH Initial coding. // +// 11/03/94 ECH Develop to munga spec // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(HOSTMGR_HPP) +# define HOSTMGR_HPP + +# if !defined(NETWORK_HPP) +# include +# endif + +# if !defined(HOST_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + +# if !defined(HASH_HPP) +# include +# endif + +# if !defined(ENTITYID_HPP) +# include +# endif + + class Entity; + class Entity__MakeMessage; + + //########################################################################## + //######################### HostManager ############################## + //########################################################################## + + class HostManager__EntityTransferOwnershipMessage; + class HostManager__EntityNewOwnershipMessage; + + class HostManager: + public NetworkClient + { + friend class HostManager__AllEntityIterator; + friend class HostManager__DynamicMasterEntityIterator; + friend class HostManager__DynamicReplicantEntityIterator; + + friend class HostManager__RemoteHostIterator; + friend class HostManager__AllHostIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + typedef HostManager__AllEntityIterator + AllEntityIterator; + typedef HostManager__DynamicMasterEntityIterator + DynamicMasterEntityIterator; + typedef HostManager__DynamicReplicantEntityIterator + DynamicReplicantEntityIterator; + + typedef HostManager__RemoteHostIterator + RemoteHostIterator; + typedef HostManager__AllHostIterator + AllHostIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and testing + // + public: + HostManager(); + ~HostManager(); + + Logical + TestInstance() const; + static void + TestClass(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Execution control + // + public: + void + Shutdown(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local and remote host methods + // + public: + // + //----------------------------------------------------------------------- + // AdoptLocalHost, OrphanLocalHost + //----------------------------------------------------------------------- + // + void + AdoptLocalHost(Host *local_host); + Host* + OrphanLocalHost(); + + // + //----------------------------------------------------------------------- + // GetLocalHostID, GetLocalHost + //----------------------------------------------------------------------- + // + HostID + GetLocalHostID(); + Host* + GetLocalHost(); + + // + //----------------------------------------------------------------------- + // AdoptRemoteHost, OrphanRemoteHost + //----------------------------------------------------------------------- + // + void + AdoptRemoteHost(Host *remote_host); + void + OrphanRemoteHost(Host *remote_host); + + // + //----------------------------------------------------------------------- + // GetRemoteHost, GetConsoleHost, FindHost + //----------------------------------------------------------------------- + // + Host* + GetRemoteHost(HostID host_ID); + Host* + GetConsoleHost(); + Host* + FindHost(NetworkAddress net_address); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Entity methods + // + public: + // + //----------------------------------------------------------------------- + // MakeUniqueEntityID + // + // Returns a unique entity indentity + //----------------------------------------------------------------------- + // + EntityID + MakeUniqueEntityID(); + + // + //----------------------------------------------------------------------- + // NotifyOfEntityCreation + // + // This method is called to notify the host manager that a new entity + // has been created on this host. + //----------------------------------------------------------------------- + // + void + NotifyOfEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + + // + //----------------------------------------------------------------------- + // NotifyOfEntityDestruction + // + // This method is called to notify the host manager that a entity is + // being destroyed. + //----------------------------------------------------------------------- + // + void + NotifyOfEntityDestruction(Entity *entity); + + // + //----------------------------------------------------------------------- + // NotifyOfReplacementEntityCreation + // + // This method is called by the registry manager to notify the + // host manager that a new replacement entity has been + // created on this host. + //----------------------------------------------------------------------- + // + void + NotifyOfReplacementEntityCreation( + Entity *entity, + EntityID entity_ID, + ClassID entity_class, + LWord entity_type + ); + + // + //----------------------------------------------------------------------- + // GetEntityPointer + // + // Returns a pointer to the entity specified by entityID. + //----------------------------------------------------------------------- + // + Entity* + GetEntityPointer(const EntityID &entityID); + + // + //----------------------------------------------------------------------- + // IdentifyNewMapEntityHost + // + // For LAN specific solutions the host manager can return the + // host id of a new map entity prior to its creation. This + // method uses an algorithm to determine this value and returns + // it. + //----------------------------------------------------------------------- + // + HostID + IdentifyNewMapEntityHost(EntityID entity_ID); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + // + // Message IDs + // + enum + { + NewHostMessageID = NetworkClient::NextMessageID, + HostUpdateMessageID, + EntityTransferOwnershipMessageID, + EntityNewOwnershipMessageID, + NextMessageID + }; + + // + // Message types + // + typedef HostManager__EntityTransferOwnershipMessage + EntityTransferOwnershipMessage; + typedef HostManager__EntityNewOwnershipMessage + EntityNewOwnershipMessage; + + // + //----------------------------------------------------------------------- + // EntityTransferOwnership + //----------------------------------------------------------------------- + // + void + EntityTransferOwnershipHandler(EntityTransferOwnershipMessage*); + + // + //----------------------------------------------------------------------- + // EntityNewOwnership + //----------------------------------------------------------------------- + // + void + EntityNewOwnershipHandler(EntityNewOwnershipMessage*); + + // + //----------------------------------------------------------------------- + // Message table, Shared data + //----------------------------------------------------------------------- + // + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + Host + *localHost; + TableOf + remoteHostSocket; + TableOf + allHostSocket; + TableIteratorOf + *allHostIterator; + + // + // The last entity id to be allocated, used to allocate a new one + // + EntityID + lastEntityID; + + // + // The entity index socket holds all entities, static, dynamic, + // replicant, etc... + // + HashOf + entityIndexSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ HostManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline Entity* + HostManager::GetEntityPointer(const EntityID &entity_ID) + { + Check(this); + return entityIndexSocket.Find(entity_ID); + } + + inline Host* + HostManager::GetLocalHost() + { + Check(this); + + // + // GAC removed this so we can use the call to see if a + // local host exists or not, there doesn't seem to be + // any call for this. Host Manager initializes localHost + // to NULL and all routines check it before use so this + // shouldn't cause any problems. + // + // Check(localHost); + + return localHost; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ HostManager messages ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class HostManager__EntityTransferOwnershipMessage: + public NetworkClient::Message + { + public: + HostManager__EntityTransferOwnershipMessage(): + NetworkClient::Message( + HostManager::EntityTransferOwnershipMessageID, + sizeof(HostManager__EntityTransferOwnershipMessage) + ) + {} + }; + + class HostManager__EntityNewOwnershipMessage: + public NetworkClient::Message + { + public: + HostManager__EntityNewOwnershipMessage(): + NetworkClient::Message( + HostManager::EntityNewOwnershipMessageID, + sizeof(HostManager__EntityNewOwnershipMessage) + ) + {} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllEntityIterator ~~~~~~~~~~~~~~~~~~ + + class HostManager__AllEntityIterator: + public Host__AllEntityIterator + { + public: + HostManager__AllEntityIterator(HostManager *host_manager); + ~HostManager__AllEntityIterator(); + }; + + //~~~~~~~~~~~~~~~~~ HostManager__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~ + + class HostManager__DynamicMasterEntityIterator: + public Host__DynamicMasterEntityIterator + { + public: + HostManager__DynamicMasterEntityIterator(HostManager *host_manager); + ~HostManager__DynamicMasterEntityIterator(); + }; + + //~~~~~~~~~~~~~~~~~ HostManager__DynamicReplicantEntityIterator ~~~~~~~~~~~~ + + class HostManager__DynamicReplicantEntityIterator: + public Host__DynamicReplicantEntityIterator + { + public: + HostManager__DynamicReplicantEntityIterator(HostManager *host_manager); + ~HostManager__DynamicReplicantEntityIterator(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__RemoteHostIterator ~~~~~~~~~~~~~~~~~ + + class HostManager__RemoteHostIterator: + public TableIteratorOf + { + public: + HostManager__RemoteHostIterator(HostManager *host_manager); + ~HostManager__RemoteHostIterator(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllHostIterator ~~~~~~~~~~~~~~~~~~~~ + + class HostManager__AllHostIterator: + public TableIteratorOf + { + public: + HostManager__AllHostIterator(HostManager *host_manager); + ~HostManager__AllHostIterator(); + }; + +#endif + diff --git a/CODE/RP/MUNGA/ICOM.CPP b/CODE/RP/MUNGA/ICOM.CPP new file mode 100644 index 0000000..f04db36 --- /dev/null +++ b/CODE/RP/MUNGA/ICOM.CPP @@ -0,0 +1,496 @@ +//===========================================================================// +// File: icom.cpp // +// Project: MUNGA Brick: Controls // +// Contents: Interface specification for intercom class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/18/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(ICOM_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) Tell(n << flush); +#else +# define Test_Tell(n) +#endif + +//########################################################################## +//############################# Icom ################################# +//########################################################################## +Icom::Icom( + HostID host_id, + int unit_number +): +Plug(IcomClassID) +{ + Test_Tell("Icom::Icom(" << host_id << ", " << unit_number << ")\n"); + Check_Pointer(this); + //-------------------------------------- + // Initialize values + //-------------------------------------- + hostID = host_id; + unitNumber = unit_number; + channel = undefinedChannel; + channelBeforePA = undefinedChannel; + PTTStatus = False; + PACaptive = False; + + Check_Fpu(); +} + +Icom::~Icom() +{ + Test_Tell("Icom::~Icom()\n"); + Check(this); + //-------------------------------------- + // Cleanup before deletion + //-------------------------------------- + SetPTTStatusValue(False); + SetChannelValue(undefinedChannel); + //-------------------------------------- + // The plug automatically unlinks + // from the Icom Manager upon deletion. + //-------------------------------------- + Check_Fpu(); +} + +Logical + Icom::TestInstance() const +{ + Plug::TestInstance(); + Check_Fpu(); + return True; +} + +//-------------------------------------------------------------------------- +void + Icom::SetChannel(int new_channel) +{ + Test_Tell("Icom::SetChannel(" << new_channel << ")\n"); + Check(this); + //-------------------------------------- + // Broadcast the change + // (nonexclusive broadcast: we receive + // and process this msg locally) + //-------------------------------------- + IcomManager::IMMessage + message; + + message.BuildChannelMessage( + IcomManager::ChannelMessageID, + hostID, + unitNumber, + new_channel + ); + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + NetworkClient::IcomManagerClientID, + &message + ); + + Check_Fpu(); +} + +void + Icom::SetChannelValue(int new_channel) +{ + Test_Tell("Icom::SetChannelValue(" << new_channel << ")\n"); + Check(this); + //-------------------------------------- + // Set local value + //-------------------------------------- + channel = new_channel; + Check_Fpu(); +} + +int + Icom::GetChannel() +{ + Check(this); + Check_Fpu(); + return channel; +} + +//-------------------------------------------------------------------------- +void + Icom::SetPTTStatus(Logical new_ptt) +{ + Test_Tell("Icom::SetPTTStatus(" << new_ptt << ")\n"); + Check(this); + + //--------------------------------------- + // Disallow talking during public address + //--------------------------------------- + if (!PACaptive) + { + //-------------------------------------- + // Broadcast change + // (nonexclusive broadcast: we receive + // and process this msg locally) + //-------------------------------------- + IcomManager::IMMessage + message; + + message.BuildPTTMessage( + IcomManager::PTTMessageID, + hostID, + unitNumber, + new_ptt + ); + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + NetworkClient::IcomManagerClientID, + &message + ); + } + + Check_Fpu(); +} + +void + Icom::SetPTTStatusValue(Logical new_ptt) +{ + Test_Tell("Icom::SetPTTStatusValue(" << new_ptt << ")\n"); + Check(this); + //--------------------------------------- + // Disallow talking during public address + //--------------------------------------- + if (!PACaptive) + { + PTTStatus = new_ptt; + } + Check_Fpu(); +} + +Logical + Icom::GetPTTStatus() +{ + Check(this); + Check_Fpu(); + return PTTStatus; +} + +//-------------------------------------------------------------------------- +void + Icom::SetPACaptive(Logical new_pa) +{ + Test_Tell("Icom::SetPACaptive(" << new_pa << ")\n"); + Check(this); + + //-------------------------------------- + // Broadcast the change + // (nonexclusive broadcast: we receive + // and process this msg locally) + //-------------------------------------- + IcomManager::IMMessage + message; + + message.BuildPAMessage( + IcomManager::PAMessageID, + hostID, + unitNumber, + new_pa + ); + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + NetworkClient::IcomManagerClientID, + &message + ); + + Check_Fpu(); +} + +void + Icom::SetPACaptiveValue(Logical new_pa) +{ + Test_Tell("Icom::SetPACaptiveValue(" << new_pa << ")\n"); + Check(this); + + if (new_pa == True) + { + if (PACaptive == False) + { + channelBeforePA = channel; + } + //-------------------------------------- + // Force PTT off during public address + //-------------------------------------- + if (PTTStatus == True) + { + SetPTTStatusValue(False); + } + } + else + { + //-------------------------------------- + // Return to previous channel + //-------------------------------------- + SetChannelValue(channelBeforePA); + } + PACaptive = new_pa; + Check_Fpu(); +} + +Logical + Icom::GetPACaptive() +{ + Check(this); + Check_Fpu(); + return PACaptive; +} + +//########################################################################## +//######################### IcomManager ############################## +//########################################################################## + +//-------------------------------------------------------------------------- +// Virtual Data support +// + +Derivation + IcomManager::ClassDerivations( + NetworkClient::ClassDerivations, + "IcomManager" + ); + +IcomManager::SharedData + IcomManager::DefaultData( + IcomManager::ClassDerivations, + IcomManager::MessageHandlers + ); + +//-------------------------------------------------------------------------- +// Creator +// +IcomManager::IcomManager( + SharedData &shared_data +): +NetworkClient(IcomManagerClassID, shared_data, IcomManagerClientID), +instanceList(this) +{ + Test_Tell("IcomManager::IcomManager()\n"); + Check_Pointer(this); + + //-------------------------------- + // Initialize unit number service + //-------------------------------- + nextUnitNumber = 0; + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +// Destructor +// +IcomManager::~IcomManager() +{ + Test_Tell("IcomManager::~IcomManager()\n"); + Check(this); + + Shutdown(); + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +Logical + IcomManager::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +//-------------------------------------------------------------------------- +void + IcomManager::LoadMission(Mission */*mission*/) +{ + Check(this); + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + IcomManager::Shutdown() +{ + Check(this); + + Icom + *icom; + ChainIteratorOf + i(instanceList); + + //------------------------------------------ + // Delete all icom objects + //------------------------------------------ + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + Unregister_Object(icom); + delete icom; + } + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + IcomManager::Execute() +{ + Check(this); + Fail("IcomManager::Execute() should not be called directly!\n"); +} + +//-------------------------------------------------------------------------- +Icom * + IcomManager::MakeIcom(HostID host_id, int unit_number) +{ + Test_Tell( + "IcomManager::MakeIcom(" << host_id << + ", " << unit_number << + ")\n" + ); + Check(this); + + //------------------------------------------ + // Create, register icom object + //------------------------------------------ + Icom + *icom = new Icom(host_id, unit_number); + Check(icom); + Register_Object(icom); + //------------------------------------------ + // Add to global list + //------------------------------------------ + instanceList.Add(icom); + + Check_Fpu(); + return icom; +} + +//------------------------------------------------------------------------ +void + IcomManager::SetPAState(int pa_channel) +{ + Test_Tell("IcomManager::SetPAState(" << pa_channel << ")\n"); + Check(this); + + Icom + *icom; + + ChainIteratorOf + i(instanceList); + + if (pa_channel == Icom::undefinedChannel) + { + //------------------------------------------ + // Release all icom objects from PA state + //------------------------------------------ + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + icom->SetPACaptive(False); + } + } + else + { + //------------------------------------------ + // Force all icom objects to PA state + //------------------------------------------ + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + icom->SetPACaptive(True); + icom->SetChannel(pa_channel); + } + } + Check_Fpu(); +} + +//------------------------------------------------------------------------ +Icom* + IcomManager::FindIcom(HostID host_id, int unit_number) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + Icom + *icom; + + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + if (icom->hostID == host_id) + { + if (icom->unitNumber == unit_number) + { + Check_Fpu(); + return icom; + } + } + } + + Check_Fpu(); + return NULL; +} + + +void + IcomManager::ReceiveNetworkPacket( + NetworkPacket */*packet*/, + Receiver::Message *packet_message + ) +{ + Test_Tell("IcomManager::ReceiveNetworkPacket(...)\n"); + Check(this); + Check(packet_message); + Verify(packet_message->messageID >= 0); + Verify(packet_message->messageID < NextMessageID); + + IMMessage + *message = (IMMessage *) packet_message; + + Icom + *icom = FindIcom(message->hostID, message->unitNumber); + + if (icom != NULL) + { + Check(icom); + switch (message->messageID) + { + case ChannelMessageID: + icom->SetChannelValue(message->data.channelNumber); + break; + + case PTTMessageID: + icom->SetPTTStatusValue(message->data.PTTStatus); + break; + + case PAMessageID: + icom->SetPACaptiveValue(message->data.PAStatus); + break; + } + } + + Check_Fpu(); +} + + diff --git a/CODE/RP/MUNGA/ICOM.HPP b/CODE/RP/MUNGA/ICOM.HPP new file mode 100644 index 0000000..308000e --- /dev/null +++ b/CODE/RP/MUNGA/ICOM.HPP @@ -0,0 +1,263 @@ +//===========================================================================// +// File: icom.hpp // +// Project: MUNGA Brick: Controls // +// Contents: Interface specification for intercom class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/14/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ICOM_HPP) +# define ICOM_HPP + +# if !defined(ENTITY_HPP) +# include +# endif + +# if !defined(NETWORK_HPP) +# include +# endif + + class Mission; + + //########################################################################## + //############################# Icom ################################# + //########################################################################## + class Icom: + public Plug + { + friend class IcomManager; + public: + // constructor is protected: only the IcomManager should call it. + + virtual ~Icom(); + + Logical + TestInstance() const; + + //-------------------------------------------------- + // These methods are used to set the channel, PTT, + // and PA status globally across all the cockpits. + // + // They invoke the protected 'set value' methods + // defined below. + //-------------------------------------------------- + void + SetChannel(int new_channel); + void + SetPTTStatus(Logical new_ptt); + void + SetPACaptive(Logical new_pa); + //-------------------------------------------------- + // These methods allow access to the values + //-------------------------------------------------- + int + GetChannel(); + Logical + GetPTTStatus(); + Logical + GetPACaptive(); + + enum + { + undefinedChannel = -1 + }; + + protected: + Icom(HostID host_id, int unit_number = 0); + //-------------------------------------------------- + // These methods are used to locally set the value + // for the channel, PTT, and PA status. + // + // The difference between these methods and the + // public methods defined above is that these + // methods are called by both the public routines + // above and the event receiver to actually + // set the values involved. Making them virtual + // allows derived classes to be notified of changes + // (but also requires that all derived classes + // explicitly call the overridden methods!) + //-------------------------------------------------- + virtual void + SetChannelValue(int new_channel); + virtual void + SetPTTStatusValue(Logical new_ptt); + virtual void + SetPACaptiveValue(Logical new_pa); + + HostID + hostID; + int + unitNumber; + int + channel, + channelBeforePA; + Logical + PTTStatus; + Logical + PACaptive; // held by operator + }; + + //########################################################################## + //##################### IcomManager::Message ########################### + //########################################################################## + + class IcomManager__Message : + public Receiver::Message + { + public: + HostID + hostID; + int + unitNumber; + + union + { + int channelNumber; + Logical PTTStatus; + Logical PAStatus; + } + data; + + IcomManager__Message(): + Receiver::Message(Receiver::AnyMessageID, sizeof(*this)) + {} + + // Message ID's must be passed in as parameters + // to avoid circular reference (ID's not defined yet) + void + BuildChannelMessage( + Receiver::MessageID message_id, + HostID host_id, + int unit_number, + int new_channel + ) + { + messageLength = sizeof(IcomManager__Message); + messageID = message_id; + hostID = host_id; + unitNumber = unit_number; + data.channelNumber = new_channel; + } + + void + BuildPTTMessage( + Receiver::MessageID message_id, + HostID host_id, + int unit_number, + Logical new_status + ) + { + messageLength = sizeof(IcomManager__Message); + messageID = message_id; + hostID = host_id; + unitNumber = unit_number; + data.PTTStatus = new_status; + } + + void + BuildPAMessage( + Receiver::MessageID message_id, + HostID host_id, + int unit_number, + Logical new_status + ) + { + messageLength = sizeof(IcomManager__Message); + messageID = message_id; + hostID = host_id; + unitNumber = unit_number; + data.PAStatus = new_status; + } + + }; + + //########################################################################## + //######################### IcomManager ############################## + //########################################################################## + class IcomManager: + public NetworkClient + { + friend class Icom; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum + { + ChannelMessageID = NetworkClient::NextMessageID, + PTTMessageID, + PAMessageID, + NextMessageID + }; + + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + + typedef IcomManager__Message IMMessage; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + IcomManager( + SharedData &shared_data = DefaultData + ); + virtual ~IcomManager(); + + Logical + TestInstance() const; + + virtual Icom * + MakeIcom(HostID host_id, int unit_number=0); + int + AllocateUnitNumber(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // LoadMission, Shutdown methods + // + public: + virtual void + LoadMission(Mission *mission); + virtual void + Shutdown(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Periodic update method + // + public: + virtual void + Execute(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public address (force all intercoms to listen to common channel) + // + virtual void + SetPAState(int channel); // use Icom::undefinedChannel to release + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Icom object support routines + // + protected: + Icom * + FindIcom(HostID host_id, int unit_number); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // protected data + // + protected: + int + nextUnitNumber; + ChainOf + instanceList; // list of all Icom objects + }; + +#endif diff --git a/CODE/RP/MUNGA/INTEREST.CPP b/CODE/RP/MUNGA/INTEREST.CPP new file mode 100644 index 0000000..a2faab4 --- /dev/null +++ b/CODE/RP/MUNGA/INTEREST.CPP @@ -0,0 +1,2629 @@ +//===========================================================================// +// File: interest.cc // +// Project: MUNGA Brick: Interest Manager // +// Contents: Interface specification Interest Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/28/94 ECH Initial coding. // +// 11/03/94 ECH Develop to munga spec // +// 11/29/94 JMA Changed Identities to IDs // +// 02/10/95 CPB Added GaugeInterestType // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(INTEREST_HPP) +# include +#endif + +#if !defined(REGISTRY_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(BOXTREE_HPP) +# include +#endif + +#if !defined(RENDERER_HPP) +# include +#endif + +#if !defined(CULTURAL_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +//############################################################################# +//####################### InterestManager ############################### +//############################################################################# + +// +//-------------------------------------------------------------------- +// InterestManager data +//-------------------------------------------------------------------- +// +unsigned char + InterestManager::messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE]; + +InterestManager::SharedData + InterestManager::DefaultData( + InterestManager::ClassDerivations, + InterestManager::MessageHandlers + ); + +Derivation + InterestManager::ClassDerivations( + NetworkClient::ClassDerivations, + "InterestManager" + ); + +const Receiver::HandlerEntry + InterestManager::MessageHandlerEntries[]= +{ + // + // NewDynamicEntityMessageID + // + { + InterestManager::NewDynamicEntityMessageID, + "NewDynamicEntity", + (InterestManager::Handler)&InterestManager::NewDynamicEntityHandler + }, + // + // DestroyDynamicEntityMessageID + // + { + InterestManager::DestroyDynamicEntityMessageID, + "DestroyDynamicEntity", + (InterestManager::Handler)&InterestManager::DestroyDynamicEntityHandler + }, + // + // EntitySubscribeToUpdatesMessageID + // + { + InterestManager::EntitySubscribeToUpdatesMessageID, + "EntitySubscribeToUpdates", + (InterestManager::Handler)&InterestManager::EntitySubscribeToUpdatesHandler + }, + // + // EntityUpdateReplicantsMessageID + // + { + InterestManager::EntityUpdateReplicantsMessageID, + "EntityUpdateReplicants", + (InterestManager::Handler)&InterestManager::EntityUpdateReplicantsHandler + }, + // + // EntityBroadcastToReplicantsMessageID + // + { + InterestManager::EntityBroadcastToReplicantsMessageID, + "EntityBroadcastToReplicants", + (InterestManager::Handler)&InterestManager::EntityBroadcastToReplicantsHandler + }, + // + // EntityNewInterestZoneMessageID + // + { + InterestManager::EntityNewInterestZoneMessageID, + "EntityNewInterestZone", + (InterestManager::Handler)&InterestManager::EntityNewInterestZoneHandler + }, + // + // HostInterestArenaChangedMessageID + // + { + InterestManager::HostInterestArenaChangedMessageID, + "HostInterestArenaChanged", + (InterestManager::Handler)&InterestManager::HostInterestArenaChangedHandler + }, + // + // InterestZoneDeltaMessageID + // + { + InterestManager::InterestZoneDeltaMessageID, + "InterestZoneDelta", + (InterestManager::Handler)&InterestManager::InterestZoneDeltaHandler + }, + // + // LoadResourceFinishedMessageID + // + { + Receiver::LoadResourceFinishedMessageID, + "LoadResourceFinished", + (InterestManager::Handler)&InterestManager::LoadResourceFinishedHandler + } +}; + +Receiver::MessageHandlerSet + InterestManager::MessageHandlers( + ELEMENTS(InterestManager::MessageHandlerEntries), + InterestManager::MessageHandlerEntries, + NetworkClient::MessageHandlers + ); + +// +//############################################################################# +// InterestManager +//############################################################################# +// +InterestManager::InterestManager(): + NetworkClient(InterestManagerClassID, DefaultData, InterestManagerClientID), + interestOriginSocket(NULL) +{ + interestArena = NULL; +} + +// +//############################################################################# +// ~InterestManager +//############################################################################# +// +InterestManager::~InterestManager() +{ + if (interestArena != NULL) + { + Unregister_Object(interestArena); + delete interestArena; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + InterestManager::TestInstance() const +{ + if (!IsDerivedFrom(ClassDerivations)) + { + return False; + } + Check(&interestLatticeManager); + return True; +} + +// +//############################################################################# +// LoadMission +//############################################################################# +// +void + InterestManager::LoadInterestArenas(Mission*) +{ + Check(this); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Load the interest zones that are accessed by the pilot's drop zone + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Make one interest arena manually + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + { + Check(&interestOriginSocket); + SChainIteratorOf iterator(&interestOriginSocket); + Check(&iterator); + Verify(iterator.GetSize() == 0); + } + #endif + Verify(interestArena == NULL); + interestArena = interestLatticeManager.MakeInterestArena( + (InterestZoneID)0, + (InterestType)0, + (InterestDepth)0 + ); + Register_Object(interestArena); + #endif +} + +// +//############################################################################# +// LoadMission +//############################################################################# +// +void + InterestManager::LoadMission(Mission *mission) +{ + Check(this); + Check(mission); + + // + //-------------------------------------------------------------------------- + // Return if the map ID is not valid + //-------------------------------------------------------------------------- + // + if (mission->GetMapID() == ResourceDescription::NullResourceID) + return; + + // + //-------------------------------------------------------------------------- + // Get the resource description + //-------------------------------------------------------------------------- + // + ResourceFile *resource_file; + ResourceDescription *resource_description; + + Check(application); + resource_file = application->GetResourceFile(); + Check(resource_file); + resource_description = + resource_file->FindResourceDescription(mission->GetMapID()); + Check(resource_description); + resource_description->Lock(); + + // + //-------------------------------------------------------------------------- + // Create the map stream and load + //-------------------------------------------------------------------------- + // + MemoryStream + map_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + + Check(&map_stream); + EntityID last_entity_id(MapHostID); + int landmark_id=0; + LoadMapStream(&map_stream, Origin::Identity, last_entity_id, landmark_id); + resource_description->Unlock(); + + // + //-------------------------------------------------------------------------- + // HACK - load in the collision resources into the tree pointed to by + // this resource + //-------------------------------------------------------------------------- + // + resource_description = + resource_file->FindResourceDescription(mission->GetExistanceMapID()); + + if (resource_description) + { + Check(resource_description); + resource_description->Lock(); + + InterestZone *zone = + GetInterestZone(interestArena->GetInterestZoneID()); + Check(zone); + BoundingBoxTree* tree = zone->GetExistanceRoot(); + Check(tree); + ExtentBox* zones = (ExtentBox*)resource_description->resourceAddress; + int size = resource_description->resourceSize / sizeof(ExtentBox); + while (size--) + { + BoundingBox *box; + box = new BoundingBox(*zones); + Register_Object(box); + tree->Add(box, *box); + ++zones; + } + resource_description->Unlock(); + } + resource_file->ReleaseUnlockedResources(); +} + +// +//############################################################################# +// LoadMapStream +//############################################################################# +// +void + InterestManager::LoadMapStream( + MemoryStream *map_stream, + const Origin &root, + EntityID &last_entity_id, + int &landmark_id + ) +{ + Check(this); + Check(map_stream); + + // + //-------------------------------------------------------------------------- + // Read the map stream and post creation messages + //-------------------------------------------------------------------------- + // + int map_count; + *map_stream >> map_count; + + for (int i=0; iGetPointer()); + Check(message); + + // + //----------------------------------------------------------- + // If this is an include message, recurse into a new map load + //----------------------------------------------------------- + // + if (message->messageFlags & Entity::MakeMessage::MapStreamMarkerFlag) + { + if (message->messageID == Entity::MakeMessageID) + { + Verify(message->messageLength == sizeof(Entity::MakeMapMessage)); + + Entity::MakeMapMessage *map_message = + Cast_Object(Entity::MakeMapMessage*, message); + Check(map_message); + + // + // + //----------------------------- + // Get the resource description + //----------------------------- + // + Check(application); + ResourceFile *resource_file = application->GetResourceFile(); + Check(resource_file); + ResourceDescription *resource_description = + resource_file->FindResourceDescription( + map_message->resourceID + ); + Check(resource_description); + resource_description->Lock(); + + // + //-------------------------------------------------- + // Figure out the origin to use for this map include + // HACK - map rotation is not supported + //-------------------------------------------------- + // + Origin local = map_message->localOrigin; + local.linearPosition += root.linearPosition; + + // + //------------------------------- + // Create the map stream and load + //------------------------------- + // + MemoryStream + map_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + Check(&map_stream); + LoadMapStream(&map_stream, local, last_entity_id, landmark_id); + resource_description->Unlock(); + } + else + { + Fail("Unknown message marker in map stream!\n"); + } + map_stream->AdvancePointer((message->messageLength+3)&~3); + continue; + } + + // + //------------------- + // Verify the message + //------------------- + // + #if DEBUG_LEVEL>0 + // + //---------------------------------------------------------- + // These classes should be stored in the map as map entities + //---------------------------------------------------------- + // + switch (message->classToCreate) + { + case DropZoneClassID: + case ScoreZoneClassID: + case DoorFrameClassID: + case CulturalIconClassID: + case LandmarkClassID: + if ((message->instanceFlags & Entity::MapFlag) == 0) + { + Fail("InterestManager::LoadMapStream - MapFlag disabled"); + } + break; + default: + break; + } + #endif + + // + //--------------------------------------------------------------------- + // If the message id is for a map entity, only make the thing if we are + // supposed to + //--------------------------------------------------------------------- + // + Logical post_make_message = True; + if (Entity::EntityFlagsIsMap(message->instanceFlags)) + { + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + + if ( + host_manager->GetLocalHostID() != + host_manager->IdentifyNewMapEntityHost(message->entityID) + ) + { + post_make_message = False; + } + } + + // + //----------------------------------------------------- + // Make a MakeEntityMessage and post it to the registry + //----------------------------------------------------- + // + if (post_make_message) + { + // + //-------------------------------------------------------------- + // Make a copy of the message for modification by the map origin + // HACK - map rotation is not supported + //-------------------------------------------------------------- + // + Entity::MakeMessage *local_msg = + (Entity::MakeMessage*)new char[message->messageLength]; + Register_Pointer(local_msg); + Mem_Copy( + local_msg, + message, + message->messageLength, + message->messageLength + ); + local_msg->localOrigin.linearPosition += root.linearPosition; + + // + //--------------------------------------------------- + // If this is a landmark, assign the next landmark ID + //--------------------------------------------------- + // + if (local_msg->classToCreate == LandmarkClassID) + { + Landmark::MakeMessage *land_msg = + (Landmark::MakeMessage*)local_msg; + land_msg->landmarkID = landmark_id++; + } + + // + //-------------------------------------------------------- + // If this is not a dynamic object, assign it an entity ID + //-------------------------------------------------------- + // + if (!(local_msg->instanceFlags & Entity::DynamicFlag)) + { + last_entity_id += 1; + local_msg->entityID = last_entity_id; + } + + Registry::MakeEntityMessage + *make_entity_message = + Registry::MakeEntityMessage::Make(local_msg); + Register_Object(make_entity_message); + + Check(application); + // ECH 1/28/96 - application->PostCreationEvent(make_entity_message); + PostCreationEvent(make_entity_message); + #if 0 + Tell( + "InterestManager::LoadMapStream - Posted creation event: " << + "class=" << message->classToCreate << "; " << + "entityID=" << message->entityID << "\n" + ); + #endif + + Unregister_Object(make_entity_message); + delete make_entity_message; + Unregister_Pointer(local_msg); + delete (char*)local_msg; + } + + // + //----------------------------------------------------------------------- + // Advance to the next message + //----------------------------------------------------------------------- + // + map_stream->AdvancePointer((message->messageLength+3)&~3); + } + Check_Fpu(); +} + +// +//############################################################################# +// Shutdown +//############################################################################# +// +void + InterestManager::Shutdown() +{ + Check(this); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Delete interest zones + //-------------------------------------------------------------------------- + // + #else + // + // Delete the one interest arena + // + if (interestArena) + { + Unregister_Object(interestArena); + delete interestArena; + interestArena = NULL; + } + #endif +} + +// +//############################################################################# +// Execute +//############################################################################# +// +void + InterestManager::Execute() +{ + #if 0 + // + // If (the changed origin list is empty) + // + // + // return + // + + // + // Update the net interest arena with the changes from the + // changed interest origin list + // + + // + // Calculate which interest zones should be released and which + // interest zones should be loaded + // + + // + // For (the interest zones which should be released) + // + // + // For (the static entities in the interest zones to be released) + // + // + // Send a becoming uninteresting event to the entity + // + + // + // For (the dynamic master entities in the interest zones to be released) + // + // + // Send a becoming uninteresting event to the entity + // + + // + // For (the dynamic map entities in the interest zones to be released) + // + // + // Send a becoming uninteresting event to the entity + // + + // + // For (the replicants in the interest zones to be released) + // + // + // Unsubscribe the replicants from changes + // + + // + // Send a becoming uninteresting event to the entity + // + + // + // Call the resource manager releasing the interest zone + // + + // + // For (the interest zones which should be loaded) + // + // + // Call the resource manager, requesting the interest zones + // + + // + // Broadcast the interest arena change + // + { + HostInterestArenaChangedMessage message; + + // + // Send at the end of the current frame + // + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + InterestManagerID, + &message + ); + } + #endif +} + +// +//############################################################################# +// AdoptInterestOrigin +//############################################################################# +// +void + InterestManager::AdoptInterestOrigin(InterestOrigin *interest_origin) +{ + Check(this); + Check(interest_origin); + + // + //-------------------------------------------------------------------------- + // Add the interest origin to managers socket + //-------------------------------------------------------------------------- + // + Check(&interestOriginSocket); + interestOriginSocket.Add(interest_origin); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Add to net interest arena... + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // HACK - add interesting entities to the interest origin manually + //-------------------------------------------------------------------------- + // + interest_origin->Update(interest_origin->GetInterestZoneID()); + AddInterestingEntitiesToInterestOrigin(interest_origin); + #endif +} + +// +//############################################################################# +// OrphanInterestOrigin +//############################################################################# +// +void + InterestManager::OrphanInterestOrigin(InterestOrigin *interest_origin) +{ + Check(this); + Check(interest_origin); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Remove from net interest arena + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // HACK - remove interesting entities manually + //-------------------------------------------------------------------------- + // + RemoveUninterestingEntitiesFromInterestOrigin(interest_origin); + #endif +} + +// +//############################################################################# +// NotifyOfEntityCreation +//############################################################################# +// +void + InterestManager::NotifyOfEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + #if 0 + Tell( + "InterestManager::NotifyOfEntityCreation - " << + "class=" << entity->GetClassID() << "; " << + "entityID=" << entity->GetEntityID() << "\n" + ); + #endif + + // + //-------------------------------------------------------------------------- + // Call appropriate service routine + //-------------------------------------------------------------------------- + // + switch (entity->GetInstance()) + { + case Entity::IndependantInstance: + { + Check(application); + Check(application->GetHostManager()); + if ( + entity->GetOwnerID() == + application->GetHostManager()->GetLocalHostID() + ) + { + DynamicEntityCreation(entity, creation_message); + } + else + { + ReplicantEntityCreation(entity, creation_message); + } + } + break; + + case Entity::MasterInstance: + DynamicEntityCreation(entity, creation_message); + break; + + case Entity::HermitInstance: + if (entity->IsDynamic()) + { + DynamicEntityCreation(entity, creation_message); + } + else + { + StaticEntityCreation(entity, creation_message); + } + break; + + case Entity::ReplicantInstance: + ReplicantEntityCreation(entity, creation_message); + break; + + default: + Fail("InterestManager::NotifyOfEntityCreation - should never reach here"); + break; + } +} + +// +//############################################################################# +// StaticEntityCreation +//############################################################################# +// +void + InterestManager::StaticEntityCreation( + #if DEBUG_LEVEL>0 + Entity *entity, + Entity::MakeMessage *creation_message + #else + Entity *entity, + Entity::MakeMessage * + #endif + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Verify( + entity->GetInstance() == Entity::MasterInstance || + entity->GetInstance() == Entity::HermitInstance + ); + // Verify(entity->IsStatic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // The interest zone of the static entity should already be calculated + // correctly + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Find the interest zone for the static entity and set the interest zone + //-------------------------------------------------------------------------- + // + InterestZoneID interest_zone_ID; + + interest_zone_ID = + interestLatticeManager.SearchForEntityInterestZone( + (InterestZoneID)0, + entity->GetEntityID() + ); + entity->SetInterestZoneID(interest_zone_ID); + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If within any existing interest arenas, then add to the interest origin + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // HACK - Manually add to all interest origins + //-------------------------------------------------------------------------- + // + AddInterestingEntityToInterestOrigins(entity); + #endif +} + +// +//############################################################################# +// DynamicEntityCreation +//############################################################################# +// +void + InterestManager::DynamicEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + Verify(entity->GetEntityID() != EntityID::Null); + Verify( + entity->GetInstance() == Entity::MasterInstance || + entity->GetInstance() == Entity::IndependantInstance || + entity->GetInstance() == Entity::HermitInstance + ); + // Verify(entity->IsDynamic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + if (entity->GetInstance() == Entity::IndependantInstance) + { + Check(application); + Check(application->GetHostManager()); + Verify( + entity->GetOwnerID() == + application->GetHostManager()->GetLocalHostID() + ); + } + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // Set the interest zone id of the entity. Use the spatializer to locate + // the interest zone that the entity is located in + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Find the interest zone for the static entity and set the interest zone + //-------------------------------------------------------------------------- + // + InterestZoneID interest_zone_ID; + + interest_zone_ID = + interestLatticeManager.SearchForEntityInterestZone( + (InterestZoneID)0, + entity->GetEntityID() + ); + entity->SetInterestZoneID(interest_zone_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Send new dynamic entity message + //-------------------------------------------------------------------------- + // + + // + // Setup and verify network fields in creation message + // + entity->SetupNetworkMessage(creation_message); + #if DEBUG_LEVEL>0 + Check(&creation_message->entityID); + Verify(creation_message->entityID != EntityID::Null); + Verify(creation_message->interestZoneID != NullInterestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + creation_message->ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + // HACK - Spoof the make entity message into a NewDynamicEntityMessageID + // for the purposes of sending to interest managers + // + Verify(creation_message->messageID == Entity::MakeMessageID); + creation_message->messageID = NewDynamicEntityMessageID; + + // + //-------------------------------------------------------------------------- + // If the entity is replicated + //-------------------------------------------------------------------------- + // + if ( + entity->GetInstance() == Entity::MasterInstance || + entity->GetInstance() == Entity::IndependantInstance + ) + { + // + // Broadcast the message + // + Check(application); + application->BroadcastMessage(InterestManagerClientID, creation_message); + } + + // + //-------------------------------------------------------------------------- + // Else (the entity is not replicated) + //-------------------------------------------------------------------------- + // + else + { + Verify(entity->GetInstance() == Entity::HermitInstance); + + // + // Post the message to ourselves + // + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, this, creation_message); + Dispatch(creation_message); + } +} + +// +//############################################################################# +// NewDynamicEntityHandler +//############################################################################# +// +void + InterestManager::NewDynamicEntityHandler( + NewDynamicEntityMessage *creation_message + ) +{ + Check(this); + Check(creation_message); + + // + // Verify the creation message + // + Check(&creation_message->entityID); + Verify(creation_message->entityID != EntityID::Null); + Verify(creation_message->interestZoneID != NullInterestZoneID); + Verify(creation_message->ownerID >= FirstLegalHostID); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (the new entity is not in any of the interest arenas) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Get the local host id + //-------------------------------------------------------------------------- + // + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + + // + //-------------------------------------------------------------------------- + // If (this host is not the owner host) + //-------------------------------------------------------------------------- + // + if (local_host_ID != creation_message->ownerID) + { + // + //----------------------------------------------------------------------- + // Make the replicant + //----------------------------------------------------------------------- + // + + // + // HACK - Message was spoofed as NewDynamicEntityMessageID, now + // turn back to make entity message ID + // + Verify(creation_message->messageID == NewDynamicEntityMessageID); + creation_message->messageID = Entity::MakeMessageID; + + // + // Turn on the replicant flag if this is a master instance, + // otherwise, the instance should be an independant + // + if ( + Entity::EntityFlagsGetInstance(creation_message->instanceFlags) == + Entity::MasterInstance + ) + { + creation_message->instanceFlags = Entity::EntityFlagsSetInstance( + creation_message->instanceFlags, + Entity::ReplicantInstance + ); + } + else + { + Verify( + Entity::EntityFlagsGetInstance(creation_message->instanceFlags) == + Entity::IndependantInstance + ); + } + + // + //----------------------------------------------------------------------- + // Make a MakeEntityMessage and post it to the registry + //----------------------------------------------------------------------- + // + Registry::MakeEntityMessage *make_entity_message; + + make_entity_message = Registry::MakeEntityMessage::Make(creation_message); + Register_Object(make_entity_message); + + Check(application); + // + // Implicit assumption that this will be a higher + // priority and/or earlier sequence than any update message + // + Check(application->GetRegistry()); + application->GetRegistry()->Dispatch(make_entity_message); + + Unregister_Object(make_entity_message); + delete make_entity_message; + } + + // + //-------------------------------------------------------------------------- + // If (this host is the owner host) + //-------------------------------------------------------------------------- + // + else + { + // + //----------------------------------------------------------------------- + // Get the entity pointer + //----------------------------------------------------------------------- + // + Entity *entity; + + Check(application); + Check(application->GetHostManager()); + entity = application->GetHostManager()->GetEntityPointer( + creation_message->entityID + ); + Check(entity); + + // + //----------------------------------------------------------------------- + // Tell the master that it is interesting + // Should this wait until next interest frame? + //----------------------------------------------------------------------- + // + entity->BecomeInteresting(); + + // + //----------------------------------------------------------------------- + // HACK - Manually add to all interest origins + //----------------------------------------------------------------------- + // + AddInterestingEntityToInterestOrigins(entity); + } +} + +#if 0 // HACK - Partial Implementation +// +//############################################################################# +// NotifyOfMapEntityCreation +//############################################################################# +// +void + InterestManager::NotifyOfMapEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message, + Time + ) +{ + Check(this); + Check(entity); + Check(creation_message); + Verify(creation_message->entityID != EntityID::Null); + Verify(creation_message->interestZoneID != NullInterestZoneID); + + // + // Verify instance type, and interest characterisitics + // + Verify(entity->GetInstance() == Entity::MasterInstance); + Verify(entity->IsDynamic()); + Verify(entity->IsMap()); + + #if 0 + // + // Call the resource manager, storing the interest zone delta + // + + // + // Broadcast the interest zone delta + // + { + InterestZoneDeltaMessage message; + + Check(application); + application->SendMessage( + DefaultEventPriority, + InterestManagerID, + &message + ); + } + + // + // Broadcast the new map entity message + // + { + Verify(creation_message->messageID == Entity::MakeMessageID); + creation_message->messageID = NewMapEntityMessageID; + + Check(application); + application->SendMessage( + DefaultEventPriority, + InterestManagerID, + creation_message + ); + } + #else + Fail("InterestManager::NotifyOfMapEntityCreation - under construction"); + #endif +} +#endif + +#if 0 // HACK - Partial Implementation +// +//############################################################################# +// NewMapEntityHandler +//############################################################################# +// +void + InterestManager::NewMapEntityHandler( + NewMapEntityMessage *message + ) +{ + Check(this); + Check(message); + + #if 0 + // + // If (the entity is outside of the interest arena) + // + // + // Return + // + + // + // If (this is the owner host) + // + // + // Tell the entity that it is interesting + // + + // + // If (this host is not the owner host) + // + // + // Find the replicant or local master entity + // + + // + // If (the entity does not exist) + // + // + // Make the replicant + // + + // + // Tell the replicant that it is interesting + // + + // + // Subscribe the replicant to updates from the master + // + + // + // If (the entity does exist) + // + // + // If (the entity is a replicant) + // + // + // Point it at the new owner + // + + // + // If (the entity is a master) + // + // + // If (creation time of new master > creation time of local master) + // + // + // Morph the local master into a replicant pointing at new master + // + + // + // Tell the replicant that it is interesting + // + + // + // Subscribe the replicant to updates from the master + // + #else + Fail("InterestManager::NewMapEntityHandler - under construction"); + #endif +} +#endif + +// +//############################################################################# +// ReplicantEntityCreation +//############################################################################# +// +void + InterestManager::ReplicantEntityCreation( + #if DEBUG_LEVEL>0 + Entity *entity, + Entity::MakeMessage *creation_message + #else + Entity *entity, + Entity::MakeMessage * + #endif + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + Verify(entity->GetEntityID() != EntityID::Null); + Verify( + entity->GetInstance() == Entity::ReplicantInstance || + entity->GetInstance() == Entity::IndependantInstance + ); + // Verify(entity->IsDynamic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + if (entity->GetInstance() == Entity::IndependantInstance) + { + Check(application); + Check(application->GetHostManager()); + Verify( + entity->GetOwnerID() != + application->GetHostManager()->GetLocalHostID() + ); + } + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // The interest zone of the static entity should already be calculated + // correctly + //-------------------------------------------------------------------------- + // + #endif + + // + //-------------------------------------------------------------------------- + // Get the local host id + //-------------------------------------------------------------------------- + // + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + + // + //-------------------------------------------------------------------------- + // Subscribe the replicant to updates from the master + //-------------------------------------------------------------------------- + // + EntitySubscribeToUpdates( + entity->GetEntityID(), + entity->GetOwnerID(), + local_host_ID + ); + + // + //-------------------------------------------------------------------------- + // Tell the replicant that it is interesting + //-------------------------------------------------------------------------- + // + entity->BecomeInteresting(); + + // + //-------------------------------------------------------------------------- + // HACK - Manually add to all interest origins + //-------------------------------------------------------------------------- + // + AddInterestingEntityToInterestOrigins(entity); +} + +// +//############################################################################# +// NotifyOfEntityDestruction +//############################################################################# +// +void + InterestManager::NotifyOfEntityDestruction(Entity *entity) +{ + Check(this); + Check(entity); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (this is a map entity) + //-------------------------------------------------------------------------- + // + // + // Store an interest zone delta with the owner set to MapHostID + // + + // + // Broadcast an interest zone delta + // + #endif + + // + //-------------------------------------------------------------------------- + // HACK - Manually remove from all interest origins + //-------------------------------------------------------------------------- + // + RemoveUninterestingEntityFromInterestOrigins(entity); + + // + //-------------------------------------------------------------------------- + // Broadcast delete entity message for master entities that have replicants + //-------------------------------------------------------------------------- + // + if ( + entity->GetInstance() == Entity::MasterInstance // && // HACK - Partial Implementation + // entity->IsDynamic() // HACK - Partial Implementation + ) + { + // + // Create destruction message + // + DestroyDynamicEntityMessage + destroy_message( + DestroyDynamicEntityMessageID, + sizeof(DestroyDynamicEntityMessage) + ); + Check(&destroy_message); + + // + // Setup and verify network fields in destruction message + // + entity->SetupNetworkMessage(&destroy_message); + #if DEBUG_LEVEL>0 + Check(&destroy_message.entityID); + Verify(destroy_message.entityID == entity->entityID); + Verify(destroy_message.interestZoneID == entity->interestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + destroy_message.ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + // Broadcast destruction message + // + Check(application); + application->ExclusiveBroadcastMessage( + InterestManagerClientID, + &destroy_message + ); + } +} + +// +//############################################################################# +// DestroyDynamicEntityHandler +//############################################################################# +// +void + InterestManager::DestroyDynamicEntityHandler( + DestroyDynamicEntityMessage *destroy_message + ) +{ + Check(this); + Check(destroy_message); + + // + // Verify destruction message + // + Check(&destroy_message->entityID); + Verify(destroy_message->entityID != EntityID::Null); + Verify(destroy_message->interestZoneID != NullInterestZoneID); + Verify(destroy_message->ownerID >= FirstLegalHostID); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If entity is not within interest zone + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Verify the local host id + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + Verify(destroy_message->ownerID != local_host_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Find the replicant to destroy + //-------------------------------------------------------------------------- + // + Entity *replicant; + + Check(application); + Check(application->GetHostManager()); + replicant = application->GetHostManager()->GetEntityPointer( + destroy_message->entityID + ); + + // + //-------------------------------------------------------------------------- + // If (the replicant exists) + //-------------------------------------------------------------------------- + // + if (replicant != NULL) + { + Check(replicant); + Verify(replicant->GetInstance() == Entity::ReplicantInstance); + + // + // HACK - Message was spoofed as DestroyDynamicEntityMessage, now + // turn back to DestroyEntityMessage + // + Verify(destroy_message->messageID == DestroyDynamicEntityMessageID); + destroy_message->messageID = Entity::DestroyEntityMessageID; + + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, destroy_message); + PostDestructionEvent(replicant, destroy_message); + } +} + +// +//############################################################################# +// EntityUpdateInterestZone +//############################################################################# +// +void + InterestManager::EntityUpdateInterestZone( +#if DEBUG_LEVEL>0 + Entity *entity +#else + Entity * +#endif + ) +{ + Check(this); + Check(entity); + Verify(entity->IsDynamic()); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------- + // Update the interest zone id if the entity is not trapped + //-------------------------------------------------------------------- + // + if (entity->IsTrapped()) + return; + + // + //-------------------------------------------------------------------- + // Find the entities new interest zone + //-------------------------------------------------------------------- + // + InterestZoneID + old_interest_zone_ID, + new_interest_zone_ID; + + old_interest_zone_ID = entity->GetInterestZoneID(); + new_interest_zone_ID = + interestLatticeManager.SearchForEntityInterestZone( + old_interest_zone_ID, + entity->GetEntityID() + ); + + // + //-------------------------------------------------------------------- + // If the interest zone has changed, then update the entity + // and broadcast the change + //-------------------------------------------------------------------- + // + if (old_interest_zone_ID != new_interest_zone_ID) + { + entity->SetInterestZoneID(new_interest_zone_ID); + + // + // HACK - a way is needed to get from the entity the information + // required for another host to create the replicant + // + EntityNewInterestZoneMessage + message(entity->GetEntityID(),new_interest_zone_ID); + + // + // This message should be handled locally before the end of + // the current render frame? + // + #if 0 + Check(application); + application->SendEvent( + DefaultEventPriority, + InterestManagerID, + &message + ); + #else + Check(application); + application->BroadcastMessage( + InterestManagerClientID, + &message + ); + #endif + } + #endif +} + +// +//############################################################################# +// EntityNewInterestZoneHandler +//############################################################################# +// +void + InterestManager::EntityNewInterestZoneHandler( + EntityNewInterestZoneMessage* + ) +{ + #if 0 + // + // If (the master entity is on this host) + // + // + // Determine if the entity is interesting given its new + // interest zone + // + + // + // If (the entity was and still is interesting) + // then (do nothing) + // + + // + // If (the entity was not interesting and still is not interesting) + // then (do nothing) + // + + // + // If (the entity was interesting and now is not interesting) + // + // + // Send BecomeUninteresting message to the entity + // + + // + // If (the entity was not interesting and now is interesting) + // + // + // Send BecomeInteresting message to the entity + // + + // + // If (the master entity is not on this host) + // + // + // Determine if the entity is interesting given its new + // interest zone + // + + // + // If (the entity was and still is interesting) + // then (do nothing) + // + + // + // If (the entity was not interesting and still is not interesting) + // then (do nothing) + // + + // + // If (the entity was interesting and now is not interesting) + // + // + // Unsubscribe the replicant entity from updates + // + + // + // Send BecomeUninteresting message to the entity + // + + // + // If (the entity was not interesting and now is interesting) + // + // + // If (the replicant does not exist) + // + // + // Create the replicant + // + + // + // Send BecomeInteresting message to the entity + // + + // + // Subscribe the replicant to updates + // + #else + Fail("InterestManager::EntityNewInterestZoneHandler - under construction"); + #endif +} + +// +//############################################################################# +// LoadResourceFinishedHandler +//############################################################################# +// +void + InterestManager::LoadResourceFinishedHandler(Receiver::Message*) +{ + #if 0 + // + // If (an interest origin request for interest zone finished) + // + // + // For (the static entities in the interest zone) + // + // + // If (the static entity does not exist) + // + // + // Make the static entity + // + + // + // For (the map entities in the interest zone) + // + // + // If (the owner of the map entity is MapHostID) + // + // + // This entity has not been created by any other hosts, + // so create it with this host as owner + // + + // + // Need to somehow put in a small random delay for map + // entity creation resolution between two hosts? + // + + // + // Make the map entity + // + #if 0 + { + Entity entity_ID; // From the interest zone + ClassID class_ID; // From the interest zone + HostID owner_ID; // From this host + + application->registry->MakeEntity(entity_ID, class_ID); + } + #endif + #else + Fail("InterestManager::LoadResourceFinishedHandler - under construction"); + #endif +} + +// +//############################################################################# +// EntitySubscribeToUpdates +//############################################################################# +// +void + InterestManager::EntitySubscribeToUpdates( + EntityID, + HostID, + HostID + ) +{ + // HACK - Partial implementation +} + +// +//############################################################################# +// EntitySubscribeToUpdatesHandler +//############################################################################# +// +void + InterestManager::EntitySubscribeToUpdatesHandler( + EntitySubscribeToUpdatesMessage* + ) +{ + // HACK - Partial implementation +} + +// +//############################################################################# +// EntityUpdateReplicants +//############################################################################# +// +void + InterestManager::EntityUpdateReplicants( + Entity *entity, + Entity::UpdateMessage *update_message + ) +{ + Check(this); + Check(entity); + Check(update_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Verify(entity->GetInstance() == Entity::MasterInstance); + Verify(entity->IsDynamic()); + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (no replicants are subscribed to this entity) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // Send it to the subscribed replicants + // + // LAN Solution: + // If (subscriber list is not empty) + // Broadcast the update + // + // WAN Solution: + // If (subscriber list is not empty) + // Send the update via point-to-point messages + // + // A way is needed to get from the entity the information + // required for another host to create the replicant + //-------------------------------------------------------------------------- + // + #else + // + // Setup and verify network fields in message + // + entity->SetupNetworkMessage(update_message); + #if DEBUG_LEVEL>0 + Check(&update_message->entityID); + Verify(update_message->entityID != EntityID::Null); + Verify(update_message->interestZoneID != NullInterestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + update_message->ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + // HACK - Spoof the update message into EntityUpdateReplicantsMessageID + // + Verify(update_message->messageID == Entity::UpdateMessageID); + update_message->messageID = EntityUpdateReplicantsMessageID; + + // + // Broadcast update message + // + Check(application); + application->ExclusiveBroadcastMessage( + InterestManagerClientID, + update_message + ); + #endif +} + +// +//############################################################################# +// EntityUpdateReplicantsHandler +//############################################################################# +// +void + InterestManager::EntityUpdateReplicantsHandler( + EntityUpdateReplicantsMessage *update_message + ) +{ + Check(this); + Check(update_message); + + // + // Verify update message + // + Check(&update_message->entityID); + Verify(update_message->entityID != EntityID::Null); + Verify(update_message->interestZoneID != NullInterestZoneID); + Verify(update_message->ownerID >= FirstLegalHostID); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (interest zone id is outside of our interest arenas) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Verify the local host id + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + Verify(update_message->ownerID != local_host_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Find the replicant to update + //-------------------------------------------------------------------------- + // + Entity *replicant; + + Check(application); + Check(application->GetHostManager()); + replicant = application->GetHostManager()->GetEntityPointer( + update_message->entityID + ); + + // + //-------------------------------------------------------------------------- + // If (the replicant exists) + //-------------------------------------------------------------------------- + // + if (replicant) + { + // + // Update the replicant + // + Check(replicant); + Verify(replicant->GetInstance() == Entity::ReplicantInstance); + Verify(replicant->IsDynamic()); + + // + // HACK - Message was spoofed as EntityUpdateReplicantsMessageID, now + // turn back to update entity message ID + // + Verify(update_message->messageID == EntityUpdateReplicantsMessageID); + update_message->messageID = Entity::UpdateMessageID; + + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, update_message); + PostUpdateEvent(replicant, update_message); + } + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (the replicant does not exist) + //-------------------------------------------------------------------------- + // + // + // Create the replicant + // + + // + // Send BecomeInteresting message to the entity + // + + // + // Subscribe the replicant to updates + // + #endif +} + +// +//############################################################################# +// EntityBroadcastToReplicants +//############################################################################# +// +void + InterestManager::EntityBroadcastToReplicants( + Entity *entity, + Entity::Message *broadcast_message + ) +{ + Check(this); + Check(entity); + Check(broadcast_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Verify(entity->GetInstance() == Entity::MasterInstance); + // Verify(entity->IsDynamic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (no replicants are subscribed to this entity) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // Send it to the subscribed replicants + // + // LAN Solution: + // If (subscriber list is not empty) + // Broadcast the update + // + // WAN Solution: + // If (subscriber list is not empty) + // Send the update via point-to-point messages + // + // A way is needed to get from the entity the information + // required for another host to create the replicant + // + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Setup and verify network fields in message + //-------------------------------------------------------------------------- + // + entity->SetupNetworkMessage(broadcast_message); + #if DEBUG_LEVEL>0 + Check(&broadcast_message->entityID); + Verify(broadcast_message->entityID != EntityID::Null); + Verify(broadcast_message->interestZoneID != NullInterestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + broadcast_message->ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + //-------------------------------------------------------------------------- + // Build the interest manager message + //-------------------------------------------------------------------------- + // + MemoryStream + memory_stream(messageBuildBuffer, INTERESTMANAGER_MESSAGE_BUFFER_SIZE); + EntityBroadcastToReplicantsMessage + *interest_manager_message; + size_t + total_length; + + total_length = + sizeof (EntityBroadcastToReplicantsMessage) + + broadcast_message->messageLength; + Verify(total_length < memory_stream.GetBytesRemaining()); + + Check_Pointer(memory_stream.GetPointer()); + interest_manager_message = + new (memory_stream.GetPointer()) EntityBroadcastToReplicantsMessage( + total_length + ); + Check(interest_manager_message); + + memory_stream.AdvancePointer(sizeof(EntityBroadcastToReplicantsMessage)); + Mem_Copy( + memory_stream.GetPointer(), + broadcast_message, + broadcast_message->messageLength, + memory_stream.GetBytesRemaining() + ); + + // + //-------------------------------------------------------------------------- + // Broadcast update message + //-------------------------------------------------------------------------- + // + #if 0 + Tell( + "InterestManager::EntityBroadcastToReplicants - Send entity message ID " << + broadcast_message->messageID << "\n" + ); + #endif + + Check(application); + application->ExclusiveBroadcastMessage( + InterestManagerClientID, + interest_manager_message + ); + #endif +} + +// +//############################################################################# +// EntityBroadcastToReplicantsHandler +//############################################################################# +// +void + InterestManager::EntityBroadcastToReplicantsHandler( + EntityBroadcastToReplicantsMessage *interest_manager_message + ) +{ + Check(this); + Check(interest_manager_message); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // If (interest zone id is outside of our interest arenas) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Parse broadcast message + //-------------------------------------------------------------------------- + // + MemoryStream + memory_stream( + interest_manager_message, + interest_manager_message->messageLength + ); + Entity::Message *broadcast_message; + + memory_stream.AdvancePointer(sizeof(EntityBroadcastToReplicantsMessage)); + broadcast_message = Cast_Object(Entity::Message*, memory_stream.GetPointer()); + Check(broadcast_message); + + Check(&broadcast_message->entityID); + Verify(broadcast_message->entityID != EntityID::Null); + Verify(broadcast_message->interestZoneID != NullInterestZoneID); + Verify(broadcast_message->ownerID >= FirstLegalHostID); + + #if 0 + Tell( + "InterestManager::EntityBroadcastToReplicantsHandler - Receive entity message ID " << + broadcast_message->messageID << "\n" + ); + #endif + + // + //-------------------------------------------------------------------------- + // Verify the local host id + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + Verify(broadcast_message->ownerID != local_host_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Find the replicant to update + //-------------------------------------------------------------------------- + // + Entity *replicant; + + Check(application); + Check(application->GetHostManager()); + replicant = application->GetHostManager()->GetEntityPointer( + broadcast_message->entityID + ); + + #if 0 + Tell( + "InterestManager::EntityBroadcastToReplicantsHandler - Replicant=" << + (long)replicant << "\n" + ); + #endif + + // + //-------------------------------------------------------------------------- + // If the replicant exists, update it + //-------------------------------------------------------------------------- + // + if (replicant) + { + Check(replicant); + Verify(replicant->GetInstance() == Entity::ReplicantInstance); + + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, broadcast_message); + PostUpdateEvent(replicant, broadcast_message); + } + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (the replicant does not exist) + //-------------------------------------------------------------------------- + // + else + { + // + // Create the replicant + // + + // + // Send BecomeInteresting message to the entity + // + + // + // Subscribe the replicant to updates + // + #if 0 + Tell("Unknown replicant " << broadcast_message->entityID << endl); + #endif + } + #endif +} + +// +//############################################################################# +// HostInterestArenaChangedHandler +//############################################################################# +// +void + InterestManager::HostInterestArenaChangedHandler( + HostInterestArenaChangedMessage* + ) +{ + #if 0 + // + // Get all hosted dynamic entities + // + + // + // For (each entity within the given interest arena) + // + { + // + // HACK - need someway of doing the following point-to-point, + // potentially to ourselves + // + Entity::UpdateMessage + *update_message = NULL; + + Check(update_message); + + Check(application); + application->interestManager.EntityUpdateReplicants( + entity, + update_message + ); + } + #else + Fail("InterestManager::HostInterestArenaChangedHandler - under construction"); + #endif +} + +// +//############################################################################# +// InterestZoneDeltaHandler +//############################################################################# +// +void + InterestManager::InterestZoneDeltaHandler( + InterestZoneDeltaMessage* + ) +{ + #if 0 + // + // If (a delta already exists for this interest zone) + // + // + // Get the timestamp of the existing delta + // + + // + // If (the timestamp of the incoming delta is > then current delta) + // + // + // Store the incoming delta + // + + // + // If (a delta does not exist for this interest zone) + // + // + // Store the incoming data + // + #else + Fail("InterestManager::InterestZoneDeltaHandler - under construction"); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::AddInterestingEntityToInterestOrigins(Entity *new_entity) +{ + Check(this); + Check(new_entity); + Check(&interestOriginSocket); + + InterestOrigin + *interest_origin; + SChainIteratorOf + iterator(&interestOriginSocket); + + Check(&iterator); + while((interest_origin = iterator.ReadAndNext()) != NULL) + { + Check(interest_origin); + interest_origin->AddInterestingEntity(new_entity); + } +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::RemoveUninterestingEntityFromInterestOrigins(Entity *entity) +{ + Check(this); + Check(entity); + Check(&interestOriginSocket); + + InterestOrigin + *interest_origin; + SChainIteratorOf + iterator(&interestOriginSocket); + + Check(&iterator); + while((interest_origin = iterator.ReadAndNext()) != NULL) + { + Check(interest_origin); + interest_origin->RemoveUninterestingEntity(entity); + } +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::AddInterestingEntitiesToInterestOrigin( + InterestOrigin *interest_origin + ) +{ + Check(this); + Check(interest_origin); + + // + // Get an iterator for all the entities on this host + // + Check(application); + Check(application->GetHostManager()); + + HostManager::AllEntityIterator + iterator(application->GetHostManager()); + Entity + *entity; + + Check(&iterator); + while((entity = iterator.ReadAndNext()) != NULL) + { + Check(entity); + interest_origin->AddInterestingEntity(entity); + } +} + +// +//############################################################################# +// PostCreationEvent +//############################################################################# +// +void + InterestManager::PostCreationEvent(Receiver::Message *make_entity_message) +{ + Check(this); + Check(make_entity_message); + + Check(application); + + #if 0 // ECH 1/28/96 + EventPriorities priority = + (application->GetApplicationState() != Application::RunningMission) ? + LowEventPriority : + DefaultEventPriority; + #else + EventPriorities priority = + (application->GetApplicationState() != Application::RunningMission) ? + LowEventPriority : + CreationEventPriority; + #endif + + Check(application); + Registry *registry = application->GetRegistry(); + Check(registry); + application->Post(priority, registry, make_entity_message); +} + +// +//############################################################################# +// PostRendererEvent +//############################################################################# +// +void + InterestManager::PostRendererEvent( + Entity *entity, + Renderer *renderer, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(renderer); + + #if 0 // ECH 1/26/96 + EventPriorities priority = + (applicationState.GetState() != Application::RunningMission) ? + MinEventPriority : + DefaultEventPriority; + #endif + + EventPriorities priority; + + switch (entity->GetInterestPriority(renderer->GetLinkedEntity())) + { + case LowInterestPriority: + priority = + (application->GetApplicationState() != Application::RunningMission) ? + MinEventPriority : + LowInterestEventPriority; + break; + + case HighInterestPriority: + priority = + (application->GetApplicationState() != Application::RunningMission) ? + MinEventPriority : + HighInterestEventPriority; + break; + + default: + Fail("Application::PostInterestEvent - Should never reach here"); + break; + } + + application->Post(priority, renderer, message); +} + +// +//############################################################################# +// PostUpdateEvent +//############################################################################# +// +void + InterestManager::PostUpdateEvent( + Entity *entity, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(message); + + // + // Note that the priority of the update can be greater than the + // creation priority since the replicants are created via dispatch + // in the interest manager. + // + EventPriorities priority = + (application->GetApplicationState() != Application::RunningMission) ? + DefaultEventPriority : + UpdateEventPriority; + + Check(application); + application->Post(priority, entity, message); +} + +// +//############################################################################# +// PostDestructionEvent +//############################################################################# +// +void + InterestManager::PostDestructionEvent( + Entity *entity, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(message); + + EventPriorities priority = DestructionEventPriority; + + #if 0 + switch (entity->GetInterestPriority(renderer->GetLinkedEntity())) + { + case LowInterestPriority: + priority = LowEventPriority; + break; + + case HighInterestPriority: + priority = DefaultEventPriority; + break; + + default: + Fail("Application::PostInterestEvent - Should never reach here"); + break; + } + #endif + + Check(application); + application->Post(priority, entity, message); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::RemoveUninterestingEntitiesFromInterestOrigin( + InterestOrigin *interest_origin + ) +{ + Check(this); + Check(interest_origin); + + interest_origin->RemoveUninterestingEntities(); +} + +//~~~~~~~~~~~~~~~~~ InterestManager__EntitySubscribeToUpdatesMessage ~~~~~~~~~~ + +InterestManager__EntitySubscribeToUpdatesMessage:: + InterestManager__EntitySubscribeToUpdatesMessage(): + NetworkClient::Message( + InterestManager::EntitySubscribeToUpdatesMessageID, + sizeof(InterestManager__EntitySubscribeToUpdatesMessage) + ) +{ +} + +//~~~~~~~~~~~~~~ InterestManager__EntityBroadcastToReplicantsMessage ~~~~~~~~~~ + +InterestManager__EntityBroadcastToReplicantsMessage:: + InterestManager__EntityBroadcastToReplicantsMessage(size_t message_length): + NetworkClient::Message( + InterestManager::EntityBroadcastToReplicantsMessageID, + message_length + ) +{ +} + +//~~~~~~~~~~~~~~~~~ InterestManager__EntityNewInterestZoneMessage ~~~~~~~~~~~~~ + +InterestManager__EntityNewInterestZoneMessage:: + InterestManager__EntityNewInterestZoneMessage( + const EntityID &entity_ID, + InterestZoneID interest_zone_ID + ): + NetworkClient::Message( + InterestManager::EntityNewInterestZoneMessageID, + sizeof(InterestManager__EntityNewInterestZoneMessage) + ) +{ + entityID = entity_ID; + interestZoneID = interest_zone_ID; +} + +//~~~~~~~~~~~~~~~~~ InterestManager__HostInterestArenaChangedMessage ~~~~~~~~~~ + +InterestManager__HostInterestArenaChangedMessage:: + InterestManager__HostInterestArenaChangedMessage(): + NetworkClient::Message( + InterestManager::HostInterestArenaChangedMessageID, + sizeof(InterestManager__HostInterestArenaChangedMessage) + ) +{ +} + +//~~~~~~~~~~~~~~~~~ InterestManager__InterestZoneDeltaMessage ~~~~~~~~~~~~~~~~~ + +InterestManager__InterestZoneDeltaMessage:: + InterestManager__InterestZoneDeltaMessage(): + NetworkClient::Message( + InterestManager::InterestZoneDeltaMessageID, + sizeof(InterestManager__InterestZoneDeltaMessage) + ) +{ +} + diff --git a/CODE/RP/MUNGA/INTEREST.HPP b/CODE/RP/MUNGA/INTEREST.HPP new file mode 100644 index 0000000..1f2cb3d --- /dev/null +++ b/CODE/RP/MUNGA/INTEREST.HPP @@ -0,0 +1,603 @@ +//===========================================================================// +// File: interest.hh // +// Project: MUNGA Brick: Interest Manager // +// Contents: Interface specifications for interest manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 11/04/94 ECH Initial coding. // +// 11/29/94 JMA Changed Identities to IDs // +// 02/10/95 CPB Added GaugeInterestType // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(INTEREST_HPP) +# define INTEREST_HPP + +# if !defined(NETWORK_HPP) +# include +# endif + +# if !defined(HOST_HPP) +# include +# endif + +# if !defined(INTORGN_HPP) +# include +# endif + +# if !defined(ENTITYID_HPP) +# include +# endif + + class Renderer; + class Entity; + class Entity__MakeMessage; + class Entity__UpdateMessage; + class Entity__DestroyEntityMessage; + class Entity__Message; + + //########################################################################## + //####################### InterestManager ############################ + //########################################################################## + + #define INTERESTMANAGER_MESSAGE_BUFFER_SIZE (1536) + + class Mission; + + class InterestManager__EntitySubscribeToUpdatesMessage; + class InterestManager__EntityBroadcastToReplicantsMessage; + class InterestManager__EntityNewInterestZoneMessage; + class InterestManager__HostInterestArenaChangedMessage; + class InterestManager__InterestZoneDeltaMessage; + + // + //-------------------------------------------------------------------------- + // InterestManager + // + // Entity types relevant to the interest managers operation: + // + // Static Entity (!replicated, !executing, !moving, trapped, map, id) + // - an entity that is not replicated, it does not execute or move. + // It is a component of the map and therefore trapped within its + // interest zone. It has a preallocated entity id. (rock, fence, wall) + // + // Dynamic Entity (replicated, executing, moving, !trapped, !map, !id) + // - an entity that may be replicated. It executes upon its host + // machine. It is also moves freely, crossing interest zones if it + // wishes. It is not a component of the map and can not be given a + // preallocated entity id. (VTV, Mech, missile) + // + // Dynamic Trapped Entity (replicated, executing, moving, trapped, !map, !id) + // - an entity that may be replicated. It executes upon its host + // machine. It may move but not out of its interest zone. It is not + // a component of the map and can not be given a preallocated entity id. + // (mines, burning husk of Mech) + // + // Dynamic Map Entity (replicated, executing, moving, !trapped, map, id) + // - an entity that may be replicated. It executes upon its host machine. + // It is also moves freely, crossing interest zones if it wishes. It + // is a component of the map and can be given a preallocated entity id. + // (The ork that activates upon entering the dungeon and then follows you, + // the one moon around the planet that orbits once every 24 hours) + // + // Dynamic Trapped Map Entity (replicated, executing, moving, trapped, map, id) + // - an entity that may be replicated. It executes upon its host machine. + // It is also moves freely, but may not change interest zones. It is a + // component of the map and can be given a preallocated entity id. + // (The swinging crane, the RP door) + //-------------------------------------------------------------------------- + // + + class InterestManager: + public NetworkClient + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + InterestManager(); + ~InterestManager(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Execution control + // + public: + virtual void + LoadInterestArenas(Mission *mission); + virtual void + LoadMission(Mission *mission); + void + LoadMapStream( + MemoryStream *map_stream, + const Origin& root, + EntityID& static_id, + int &landmark_id + ); + + virtual void + Shutdown(); + + void + Execute(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Origin methods + // + public: + // + //----------------------------------------------------------------------- + // AdoptInterestOrigin + // + // Asserts that the entity is a origin of interest of a specified + // type (example: visual, auditory, radar). Traversals of the interest + // lattice are performed with respect to this origin and may be + // performed with different algorithms depending upon type. The + // Lattice is traversed to a particular "depth" or "cost" for a + // specific interest type and may be calibrated with the + // DepthCalibration parameter. + //----------------------------------------------------------------------- + // + void + AdoptInterestOrigin(InterestOrigin *interestOrigin); + + // + //----------------------------------------------------------------------- + // OrphanInterestOrigin + //----------------------------------------------------------------------- + // + void + OrphanInterestOrigin(InterestOrigin *interest_origin); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Entity methods + // + public: + // + //----------------------------------------------------------------------- + // NotifyOfEntityCreation + //----------------------------------------------------------------------- + // + void + NotifyOfEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + + // + //----------------------------------------------------------------------- + // NotifyOfEntityDestruction + // + // This method is called to notify the interest manager that a + // entity has been destroyed. + //----------------------------------------------------------------------- + // + void + NotifyOfEntityDestruction(Entity *entity); + + // + //----------------------------------------------------------------------- + // EntityUpdateInterestZone + // + // This method is called if the entity may have changed the + // interest zone that it is in. This is used by the update + // manager. + //----------------------------------------------------------------------- + // + void + EntityUpdateInterestZone(Entity *entity); + + // + //----------------------------------------------------------------------- + // EntityForceToInteresting + // + // This forces the interest manager to treat the entity as + // interesting. + // + // HACK - Is effect local? Is the entity forced to be + // interesting on just this host? Or, does the effect pervade + // all hosts? + //----------------------------------------------------------------------- + // + void + EntityForceToInteresting(Entity *entity); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accesors for interest lattice manager + // + public: + InterestLatticeManager* + GetInterestLatticeManager(); + + InterestZone* + GetInterestZone(InterestZoneID interestZoneID); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + // + // Message IDs + // + enum + { + // + //-------------------------------------------------------------------- + // Sent by an interest manager to itself and others when it has been + // notified that a new dynamic entity has been created on the host + // machine. + //-------------------------------------------------------------------- + // + NewDynamicEntityMessageID = NetworkClient::NextMessageID, + + #if 0 + // + //-------------------------------------------------------------------- + // Sent by an interest manager to itself and others when it has been + // notified that a new dynamic map entity has been created on the + // host machine. + //-------------------------------------------------------------------- + // + NewMapEntityMessageID, + #endif + + // + //-------------------------------------------------------------------- + // Sent by an interest manager to itself and others when it has been + // notified that a entity is under going deletion. + //-------------------------------------------------------------------- + // + DestroyDynamicEntityMessageID, + + // + //-------------------------------------------------------------------- + // Message is sent to the host of the original (serving) entity that + // the host id wishes to be on the entities update list. + //-------------------------------------------------------------------- + // + EntitySubscribeToUpdatesMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to itself and others when a hosted + // entity needs to send updates to its replicants. + //-------------------------------------------------------------------- + // + EntityUpdateReplicantsMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to itself and others when a hosted + // entity needs to broadcast a message to its replicants. + //-------------------------------------------------------------------- + // + EntityBroadcastToReplicantsMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to itself and others when a hosted + // entity has changed interest zones. + //-------------------------------------------------------------------- + // + EntityNewInterestZoneMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to others when its interest arena has + // changed. + //-------------------------------------------------------------------- + // + HostInterestArenaChangedMessageID, + + // + //-------------------------------------------------------------------- + // Tells interest managers of a change to a interest zone. This is + // for the purpose of creating and destroying Dynamic Map Entities. + // The creation time stamp is used by the interest manager to resolve + // synchronization problems. + //-------------------------------------------------------------------- + // + InterestZoneDeltaMessageID, + + NextMessageID + }; + + // + // Message types + // + typedef Entity__MakeMessage + NewDynamicEntityMessage; + typedef Entity__DestroyEntityMessage + DestroyDynamicEntityMessage; + typedef Entity__UpdateMessage + EntityUpdateReplicantsMessage; + + typedef InterestManager__EntitySubscribeToUpdatesMessage + EntitySubscribeToUpdatesMessage; + typedef InterestManager__EntityBroadcastToReplicantsMessage + EntityBroadcastToReplicantsMessage; + typedef InterestManager__EntityNewInterestZoneMessage + EntityNewInterestZoneMessage; + typedef InterestManager__HostInterestArenaChangedMessage + HostInterestArenaChangedMessage; + typedef InterestManager__InterestZoneDeltaMessage + InterestZoneDeltaMessage; + + // + //----------------------------------------------------------------------- + // NewDynamicEntityHandler + //----------------------------------------------------------------------- + // + void + NewDynamicEntityHandler(NewDynamicEntityMessage *message); + + // + //----------------------------------------------------------------------- + // DestroyEntityHandler + //----------------------------------------------------------------------- + // + void + DestroyDynamicEntityHandler(DestroyDynamicEntityMessage *message); + + // + //----------------------------------------------------------------------- + // EntitySubscribeToUpdates & EntitySubscribeToUpdatesHandler + //----------------------------------------------------------------------- + // + void + EntitySubscribeToUpdates( + EntityID entity_ID, + HostID master_host, + HostID replicant_host + ); + void + EntitySubscribeToUpdatesHandler( + EntitySubscribeToUpdatesMessage *message + ); + + // + //----------------------------------------------------------------------- + // EntityUpdateReplicants & EntityUpdateReplicantsHandler + // + // If the entity has any subscribers then send then update to subscribers. + //----------------------------------------------------------------------- + // + void + EntityUpdateReplicants( + Entity *entity, + Entity__UpdateMessage *update_message + ); + void + EntityUpdateReplicantsHandler( + EntityUpdateReplicantsMessage *update_message + ); + + // + //----------------------------------------------------------------------- + // EntityBroadcastToReplicants & EntityBroadcastToReplicantsHandler + // + // If the entity has any subscribers then send then update to subscribers. + //----------------------------------------------------------------------- + // + void + EntityBroadcastToReplicants( + Entity *entity, + Entity__Message *broadcast_message + ); + void + EntityBroadcastToReplicantsHandler( + EntityBroadcastToReplicantsMessage *broadcast_message + ); + + // + //----------------------------------------------------------------------- + // EntityNewInterestZoneHandler + //----------------------------------------------------------------------- + // + void + EntityNewInterestZoneHandler( + EntityNewInterestZoneMessage *message + ); + + // + //----------------------------------------------------------------------- + // HostInterestArenaChanged + //----------------------------------------------------------------------- + // + void + HostInterestArenaChangedHandler( + HostInterestArenaChangedMessage *message + ); + + // + //----------------------------------------------------------------------- + // InterestZoneDelta + //----------------------------------------------------------------------- + // + void + InterestZoneDeltaHandler( + InterestZoneDeltaMessage *message + ); + + // + //----------------------------------------------------------------------- + // LoadResourceFinished + //----------------------------------------------------------------------- + // + void + LoadResourceFinishedHandler(Message *message); + + // + //----------------------------------------------------------------------- + // Shared Data and message tables + //----------------------------------------------------------------------- + // + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Creation and Interest Event Posting + // + public: + void + PostRendererEvent( + Entity *entity, + Renderer *renderer, + Receiver::Message *message + ); + + private: + void + PostCreationEvent(Receiver::Message *message); + void + PostUpdateEvent( + Entity *entity, + Receiver::Message *message + ); + void + PostDestructionEvent( + Entity *entity, + Receiver::Message *message + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private entity creation and destruction management + // + private: + void + StaticEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + void + DynamicEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + void + ReplicantEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private interest origin management + // + private: + void + AddInterestingEntityToInterestOrigins(Entity *entity); + void + RemoveUninterestingEntityFromInterestOrigins(Entity *entity); + void + AddInterestingEntitiesToInterestOrigin( + InterestOrigin *interest_origin + ); + void + RemoveUninterestingEntitiesFromInterestOrigin( + InterestOrigin *interest_origin + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + InterestLatticeManager + interestLatticeManager; + SChainOf + interestOriginSocket; + InterestArena + *interestArena; + + static unsigned char + messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE]; + }; + + //~~~~~~~~~~~~~ InterestManager__EntitySubscribeToUpdatesMessage ~~~~~~~~~~~ + + class InterestManager__EntitySubscribeToUpdatesMessage: + public NetworkClient::Message + { + public: + InterestManager__EntitySubscribeToUpdatesMessage(); + }; + + //~~~~~~~~~~~ InterestManager__EntityBroadcastToReplicantsMessage ~~~~~~~~~~ + + class InterestManager__EntityBroadcastToReplicantsMessage: + public NetworkClient::Message + { + public: + InterestManager__EntityBroadcastToReplicantsMessage( + size_t message_length + ); + }; + + //~~~~~~~~~~~~~ InterestManager__EntityNewInterestZoneMessage ~~~~~~~~~~~~~~ + + class InterestManager__EntityNewInterestZoneMessage: + public NetworkClient::Message + { + public: + InterestManager__EntityNewInterestZoneMessage( + const EntityID &entity_ID, + InterestZoneID interest_zone_ID + ); + + EntityID + entityID; + InterestZoneID + interestZoneID; + // + // HACK - a way is needed to get from the entity the information + // required for another host to create the replicant + // + }; + + //~~~~~~~~~~~~~ InterestManager__HostInterestArenaChangedMessage ~~~~~~~~~~~ + + class InterestManager__HostInterestArenaChangedMessage: + public NetworkClient::Message + { + public: + InterestManager__HostInterestArenaChangedMessage(); + }; + + //~~~~~~~~~~~~~~~~~ InterestManager__InterestZoneDeltaMessage ~~~~~~~~~~~~~~ + + class InterestManager__InterestZoneDeltaMessage: + public NetworkClient::Message + { + public: + InterestManager__InterestZoneDeltaMessage(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ InterestManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline InterestLatticeManager* + InterestManager::GetInterestLatticeManager() + { + return &interestLatticeManager; + } + + inline InterestZone* + InterestManager::GetInterestZone(InterestZoneID interestZoneID) + { + Check(&interestLatticeManager); + return interestLatticeManager.GetInterestZone(interestZoneID); + } + +#endif + diff --git a/CODE/RP/MUNGA/INTORGN.CPP b/CODE/RP/MUNGA/INTORGN.CPP new file mode 100644 index 0000000..a2c3d18 --- /dev/null +++ b/CODE/RP/MUNGA/INTORGN.CPP @@ -0,0 +1,177 @@ +//===========================================================================// +// File: intorgn.cpp // +// Project: MUNGA Brick: Interest Manager // +// Contents: Interface specification Interest Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/28/94 ECH Initial coding. // +// 11/03/94 ECH Develop to munga spec // +// 11/29/94 JMA Changed Identities to IDs // +// 02/10/95 CPB Added GaugeInterestType // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(INTORGN_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(INTEREST_HPP) + #include +#endif + +//############################################################################# +//####################### InterestOrigin ################################ +//############################################################################# + +// +//############################################################################# +// InterestOrigin +//############################################################################# +// +InterestOrigin::InterestOrigin( + InterestZoneID interest_zone_ID, + InterestType interest_type, + InterestDepth depth_calibration +): + interestArenaSocket(NULL) +{ + interestZoneID = interest_zone_ID; + interestType = interest_type; + depthCalibration = depth_calibration; +} + +// +//############################################################################# +// ~InterestOrigin +//############################################################################# +// +InterestOrigin::~InterestOrigin() +{ + InterestArena *interest_arena; + + Check(&interestArenaSocket); + if ((interest_arena = interestArenaSocket.GetCurrent()) != NULL) + { + Unregister_Object(interest_arena); + delete interest_arena; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + InterestOrigin::TestInstance() const +{ + Node::TestInstance(); + + Verify(interestZoneID != NullInterestZoneID); + Verify( + interestType == VisualInterestType || + interestType == AudioInterestType || + interestType == GaugeInterestType || + interestType == CollisionInterestType + ); + Check(&interestArenaSocket); + + return True; +} + +// +//############################################################################# +// Update +//############################################################################# +// +void + InterestOrigin::Update( +#if DEBUG_LEVEL>0 + InterestZoneID interest_zone_ID +#else + InterestZoneID +#endif + ) +{ + Check(this); + Verify(interest_zone_ID != NullInterestZoneID); + + #if 0 + // + // If (the interest zone has changed) + // + // + // Calculate the new interest arena for this interest origin + // + + // + // Add this interest origin to a "changed" list + // + #else + // + // HACK - there is only one interest zone right now... + // + if (interestArenaSocket.GetCurrent() == NULL) + { + InterestManager *interest_manager; + + Check(application); + interest_manager = application->GetInterestManager(); + Check(interest_manager); + Check(interest_manager->GetInterestLatticeManager()); + + InterestArena *interest_arena = + interest_manager->GetInterestLatticeManager()->MakeInterestArena( + (InterestZoneID)0, + (InterestType)0, + (InterestDepth)0 + ); + Register_Object(interest_arena); + + interestArenaSocket.Add(interest_arena); + Verify(interest_arena == interestArenaSocket.GetCurrent()); + } + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + InterestOrigin::AddInterestingEntity(Entity*) +{ + Fail("InterestOrigin::AddInterestingEntity - Should never reach here\n"); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestOrigin::RemoveUninterestingEntity(Entity*) +{ + Fail("InterestOrigin::RemoveUninterestingEntity - Should never reach here\n"); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestOrigin::RemoveUninterestingEntities() +{ + Fail("InterestOrigin::RemoveUninterestingEntities - Should never reach here\n"); +} + diff --git a/CODE/RP/MUNGA/INTORGN.HPP b/CODE/RP/MUNGA/INTORGN.HPP new file mode 100644 index 0000000..c923a96 --- /dev/null +++ b/CODE/RP/MUNGA/INTORGN.HPP @@ -0,0 +1,205 @@ +//===========================================================================// +// File: intorgn.hh // +// Project: MUNGA Brick: Interest Manager // +// Contents: Interface specifications for interest manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 11/04/94 ECH Initial coding. // +// 11/29/94 JMA Changed Identities to IDs // +// 02/10/95 CPB Added GaugeInterestType // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(INTORGN_HPP) +# define INTORGN_HPP + +# if !defined(NETWORK_HPP) +# include +# endif + +# if !defined(LATTICE_HPP) +# include +# endif + + //########################################################################## + //####################### InterestOrigin ############################# + //########################################################################## + + class Entity; + + class InterestOrigin: + public Node + { + friend class InterestManager; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Destructor, and Testing + // + public: + ~InterestOrigin(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update + // + public: + // + //----------------------------------------------------------------------- + // Update + // + // Updates the interest origins internal data structures for the + // interest zone ID. This method is most likely called by the + // renderer manager. + //----------------------------------------------------------------------- + // + virtual void + Update(InterestZoneID interest_zone_ID); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessors + // + private: + InterestZoneID + GetInterestZoneID(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor + // + protected: + InterestOrigin( + InterestZoneID interest_zone_ID, + InterestType interest_type, + InterestDepth depth_calibration + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Manager support + // + private: + virtual void + AddInterestingEntity(Entity *interesting_entity); + virtual void + RemoveUninterestingEntity(Entity *uninteresting_entity); + virtual void + RemoveUninterestingEntities(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + InterestZoneID + interestZoneID; + InterestType + interestType; + InterestDepth + depthCalibration; + SlotOf + interestArenaSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~ InterestOrigin inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline InterestZoneID + InterestOrigin::GetInterestZoneID() + { + Check(this); + return interestZoneID; + } + +#if 0 + //########################################################################## + //####################### InterestOrigin ############################# + //########################################################################## + + class InterestOrigin: + public Node + { + friend class InterestManager; + friend class InterestOrigin__InterestingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + typedef InterestOrigin__InterestingEntityIterator + InterestingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + InterestOrigin( + const EntityID &entity_ID, + InterestType interest_type, + InterestDepth depth_calibration + ); + ~InterestOrigin(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Renderer support + // + public: + // + //-------------------------------------------------------------------- + // UpdateInterestOrigin + // + // Updates the interest managers internal data structures for the + // interest origin entity. This method is most likely called by the + // renderer manager. It prepares the data that will be accessed by + // InterestingEntityIterator. + //-------------------------------------------------------------------- + // + virtual void + Update(); + + InterestArena* + GetInterestArena(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Manager support + // + protected: + virtual void + AddInterestingEntity(Entity *interesting_entity); + virtual void + RemoveUninterestingEntity(Entity *uninteresting_entity); + virtual void + RemoveUninterestingEntities(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + EntityID + entityID; + InterestType + interestType; + InterestDepth + depthCalibration; + SlotOf + interestArenaSocket; + SChainOf + interestingEntitySocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ InterestOrigin inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline InterestArena* + InterestOrigin::GetInterestArena() + { + Check(this); + return interestArenaSocket.GetCurrent(); + } +#endif + +#endif + diff --git a/CODE/RP/MUNGA/ITERATOR.CPP b/CODE/RP/MUNGA/ITERATOR.CPP new file mode 100644 index 0000000..3102eb1 --- /dev/null +++ b/CODE/RP/MUNGA/ITERATOR.CPP @@ -0,0 +1,179 @@ +//===========================================================================// +// File: iterator.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of base iterator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/08/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/23/94 ECH Added Begin, End, Forward, Backward style iteration // +// methods // +// 10/23/94 ECH Added higher level of deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 01/04/95 ECH Added base methods for some iterator methods // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(ITERATOR_HPP) + #include +#endif + +// +//############################################################################# +//############################################################################# +// +Iterator::Iterator() +{ +} + +// +//############################################################################# +//############################################################################# +// +Iterator::~Iterator() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Iterator::TestInstance() const +{ + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + Iterator::First() +{ + Fail("Iterator::First - Should never reach here"); +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + Iterator::Last() +{ + Fail("Iterator::Last - Should never reach here"); +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + Iterator::Next() +{ + Fail("Iterator::Next - Should never reach here"); +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + Iterator::Previous() +{ + Fail("Iterator::Previous - Should never reach here"); +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + Iterator::GetSize() +{ + Fail("Iterator::GetSize - Should never reach here"); + return 0; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *Iterator::ReadAndNextImplementation() +{ + void *item; + + if ((item = GetCurrentImplementation()) != NULL) + { + Next(); + } + return item; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *Iterator::ReadAndPreviousImplementation() +{ + void *item; + + if ((item = GetCurrentImplementation()) != NULL) + { + Previous(); + } + return item; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + Iterator::GetCurrentImplementation() +{ + Fail("Iterator::GetCurrentImplementation - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *Iterator::GetNthImplementation(CollectionSize index) +{ + CollectionSize i = 0; + void *item; + + First(); + while ((item = GetCurrentImplementation()) != NULL) + { + if (i == index) + return item; + Next(); + i++; + } + return NULL; +} + diff --git a/CODE/RP/MUNGA/ITERATOR.HPP b/CODE/RP/MUNGA/ITERATOR.HPP new file mode 100644 index 0000000..4bfe141 --- /dev/null +++ b/CODE/RP/MUNGA/ITERATOR.HPP @@ -0,0 +1,174 @@ +//===========================================================================// +// File: iterator.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specifications for the abstract iterator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/23/94 ECH Added Begin, End, Forward, Backward style iteration // +// methods // +// 10/23/94 ECH Added higher level of deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 01/04/95 ECH Added base methods for some iterator methods // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ITERATOR_HPP) +# define ITERATOR_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Iterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef int CollectionSize; + typedef int IteratorPosition; + + class Iterator SIGNATURED + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface to abstract class + // + // NOTE: All unsafe, untyped public methods are named XXXItem. The + // safe, typed public methods are named XXX and are declared in the + // template sub-classes. + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Destructor and testing + //-------------------------------------------------------------------- + // + virtual + ~Iterator(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // First - Moves to next item + // Last - Moves to last item + //-------------------------------------------------------------------- + // + virtual void + First(); + virtual void + Last(); + + // + //-------------------------------------------------------------------- + // Next - Moves to next item + // Previous - Moves to previous item + //-------------------------------------------------------------------- + // + virtual void + Next(); + virtual void + Previous(); + + // + //-------------------------------------------------------------------- + // ReadAndNextItem - Returns current item and moves to next item + // ReadAndPreviousItem - Returns current item and moves to prev item + // GetCurrentItem - Returns current item + //-------------------------------------------------------------------- + // + void* + ReadAndNextItem() + {return ReadAndNextImplementation();} + void* + ReadAndPreviousItem() + {return ReadAndPreviousImplementation();} + void* + GetCurrentItem() + {return GetCurrentImplementation();} + + // + //-------------------------------------------------------------------- + // GetSize - Returns number of items + // GetNthItem - Returns nth item + //-------------------------------------------------------------------- + // + virtual CollectionSize + GetSize(); + void* + GetNthItem(CollectionSize index) + {return GetNthImplementation(index);} + + // + //-------------------------------------------------------------------- + // BeginIterator - Moves to first item and returns iterator + // EndIterator - Moves to last item and returns iterator + //-------------------------------------------------------------------- + // + virtual Iterator& + BeginIterator() + {return BeginImplementation();} + virtual Iterator& + EndIterator() + {return EndImplementation();} + + // + //-------------------------------------------------------------------- + // ForwardIterator - Moves to next item and returns iterator + // BackwardIterator - Moves to previous item and returns iterator + //-------------------------------------------------------------------- + // + virtual Iterator& + ForwardIterator() + {return ForwardImplementation();} + virtual Iterator& + BackwardIterator() + {return BackwardImplementation();} + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface to abstract class + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Iterator(); + + // + //-------------------------------------------------------------------- + // Untyped implementations + //-------------------------------------------------------------------- + // + virtual void* + ReadAndNextImplementation(); + virtual void* + ReadAndPreviousImplementation(); + virtual void* + GetCurrentImplementation(); + virtual void* + GetNthImplementation(CollectionSize index); + + virtual Iterator& + BeginImplementation() + {First(); return *this;} + virtual Iterator& + EndImplementation() + {Last(); return *this;} + virtual Iterator& + ForwardImplementation() + {Next(); return *this;} + virtual Iterator& + BackwardImplementation() + {Previous(); return *this;} + }; + +#endif diff --git a/CODE/RP/MUNGA/JMOVER.CPP b/CODE/RP/MUNGA/JMOVER.CPP new file mode 100644 index 0000000..7f674ab --- /dev/null +++ b/CODE/RP/MUNGA/JMOVER.CPP @@ -0,0 +1,2068 @@ +//===========================================================================// +// File: jmover.cpp // +// Project: MUNGA Brick: Model Manager // +// Contents: Implementation details of moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(JMOVER_HPP) + #include +#endif + +#if !defined(FILEUTIL_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +//############################################################################# +//############################ JointedMover ############################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation + JointedMover::ClassDerivations(Mover::ClassDerivations,"JointedMover"); + +JointedMover::SharedData + JointedMover::DefaultData( + JointedMover::ClassDerivations, + JointedMover::MessageHandlers, + JointedMover::AttributeIndex, + JointedMover::StateCount, + (Entity::MakeHandler)JointedMover::Make + ); + +//############################################################################# +// Attribute Support +// + + const JointedMover::IndexEntry + JointedMover::AttributePointers[]= +{ + { + JointedMover::SegmentCountAttributeID, + "SegmentCount", + (Simulation::AttributePointer)&JointedMover::segmentCount + }, + { + JointedMover::SegmentTableAttributeID, + "SegmentTable", + (Simulation::AttributePointer)&JointedMover::segmentTable + }, + { + JointedMover::JointSubsystemAttributeID, + "JointSubsystem", + (Simulation::AttributePointer)&JointedMover::jointSubsystem + } +}; + +JointedMover::AttributeIndexSet + JointedMover::AttributeIndex( + ELEMENTS(JointedMover::AttributePointers), + JointedMover::AttributePointers, + Mover::AttributeIndex + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment* + JointedMover::GetSegment(CString segment_name) +{ + Check(this); + Check_Pointer(segment_name); + EntitySegment::SegmentTableIterator iterator(segmentTable); + + EntitySegment *current_segment; + + while( (current_segment = iterator.ReadAndNext() ) != NULL) + { + if(segment_name.Compare(current_segment->GetName()) == 0) + { + return current_segment; + } + } + return NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment* + JointedMover::GetSegmentFromDamageZone(CString damage_zone) +{ + EntitySegment::SegmentTableIterator iterator(segmentTable); + EntitySegment *current_segment; + while ((current_segment = iterator.ReadAndNext() ) != NULL) + { + EntitySegment::IntegerTableIterator *damage_iterator; + damage_iterator = current_segment->MakeDamageZoneIndexTable(); + Register_Object(damage_iterator); + EntitySegment::IntegerPlug *index_plug; + while ((index_plug = damage_iterator->ReadAndNext() ) != NULL) + { + CString current_name; + Verify(index_plug->GetItem() >= 0); + Verify(index_plug->GetItem() <= damageZoneCount); + + current_name = damageZones[index_plug->GetItem()]->damageZoneName; + Check_Pointer(¤t_name); + if(current_name.Compare(damage_zone) == 0) + { + Unregister_Object(damage_iterator); + delete damage_iterator; + return current_segment; + } + } + Unregister_Object(damage_iterator); + delete damage_iterator; + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + JointedMover::GetSegmentToWorld( + EntitySegment &my_segment, + LinearMatrix *transform + ) +{ + Check(this); + JointSubsystem *joints = GetJointSubsystem(); + Check(joints); + + // + //--------------------------------------------------------------- + // Check to see if the segment transforms need to be recalculated + //--------------------------------------------------------------- + // + if (joints->AreJointsModified()) + { + EntitySegment::SegmentTableIterator iterator(segmentTable); + EntitySegment *current_segment; + while( (current_segment = iterator.ReadAndNext() ) != NULL) + { + current_segment->ModifySegment(); + } + joints->ModifyJoints(False); + } + + // + //----------------------------- + // Compute the actual transform + //----------------------------- + // + transform->Multiply( + my_segment.GetSegmentToEntity(), + localToWorld + ); + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointedMover::JointedMover( + JointedMover::MakeMessage *creation_message, + JointedMover::SharedData &virtual_data +): + Mover(creation_message, virtual_data), + jointSubsystem(NULL), + segmentTable(this, True) +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the JointSubsystem + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + JointSubsystem *joint_subsystem = new JointSubsystem( + (Entity*) this, + Entity::EntitySubsystemID + ); + + Register_Object(joint_subsystem); + jointSubsystem.Add(joint_subsystem); + Check(joint_subsystem); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get Resource Description + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *skl_resource = + application->GetResourceFile()->SearchList( + creation_message->resourceID, + ResourceDescription::SkeletonStreamResourceType + ); + Check(skl_resource); + skl_resource->Lock(); + + DynamicMemoryStream segment_stream( + skl_resource->resourceAddress, + skl_resource->resourceSize); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // read in segmentCount and jointCount + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int joint_count; + segment_stream >> segmentCount >> joint_count; + + int current_joint_type; + int current_joint_index = 0; + + CString segment_name; + EntitySegment *parent_segment; + EntitySegment *current_segment; + int segment_joint_index; + Joint *segment_joint_pointer; + int parent_index; + CString video_object_name; + LinearMatrix segment_offset(LinearMatrix::Identity); + Logical site_segment; + + int ii; + for(ii=0;ii> segment_name >> parent_index; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // read parent index & find parentSegment ptr + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(parent_index == -1) + { + parent_segment = NULL; + } + else + { + EntitySegment::SegmentTableIterator iterator(segmentTable); + parent_segment = iterator.GetNth(parent_index); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Determine if this segment is a site + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + segment_stream >> site_segment >> current_joint_type; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the joint type & init the joint + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(current_joint_type != Joint::NULLJointType) + { + segment_joint_index = current_joint_index; + segment_joint_pointer = + new Joint( + joint_subsystem, + (Joint::JointType)current_joint_type + ); + Register_Object(segment_joint_pointer); + joint_subsystem->AddJoint(current_joint_index, segment_joint_pointer); + + ++current_joint_index; + } + else + { + segment_joint_pointer = NULL; + segment_joint_index = -1; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the segment offset matrix + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + segment_stream >> segment_offset; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get The Primary Damage Zone + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int primary_dzone_index; + segment_stream >> primary_dzone_index; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create this segment and add + // add it to the segment table + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + current_segment = new EntitySegment( + segment_name, + ii, // my_index + parent_index, + segment_joint_index, + segment_joint_pointer, + segment_offset, + parent_segment, + site_segment, + primary_dzone_index + ); + Register_Object(current_segment); + segmentTable.AddValue(current_segment, ii); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int video_object_count; + EntitySegment::SkeletonType skl_type; + + segment_stream >> video_object_count; + Verify(video_object_count); + + int jj; + for(jj=0;jj> skl_type >> video_object_name; + if(video_object_name.Compare("None")) + { + current_segment->AddVideoObjectName( + video_object_name, + skl_type, + DamageZone::ExistsGraphicState + ); + } + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL DESTROYED VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int destroyed_video_object_count; + + segment_stream >> destroyed_video_object_count; + + for(jj=0;jj> skl_type >> video_object_name; + if(video_object_name.Compare("None")) + { + current_segment->AddVideoObjectName( + video_object_name, + skl_type, + DamageZone::DestroyedGraphicState + ); + } + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in DamageZone information + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int damage_zone_count; + int damage_zone_index; + + segment_stream >> damage_zone_count; + if(damage_zone_count) + { + + for(int dd=0;dd> damage_zone_index; + current_segment->AddDamageZone(damage_zone_index, dd); + } + } + // + // Read in the Children Information + // + int children_count; + int child_index; + + segment_stream >> children_count; + + if(children_count) + { + for(int jj=0;jj> child_index; + current_segment->AddChildIndex(child_index, jj); + } + } + } + skl_resource->Unlock(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize all the child Pointers for each segment + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(ii=0;iiMakeChildIndexTable(); + Register_Object(iterator); + EntitySegment::IntegerPlug *current_index; + int child_count=0; + while((current_index = iterator->ReadAndNext()) != NULL) + { + EntitySegment *child_segment; + child_segment = segment_iterator.GetNth(current_index->GetItem()); + Check(child_segment); + current_segment->AddChildPointer(child_segment, child_count); + ++child_count; + } + Unregister_Object(iterator); + delete iterator; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointedMover::~JointedMover() +{ + EntitySegment::SegmentTableIterator iterator(segmentTable); + iterator.DeletePlugs(); +// +//--------------------------------------------------------------------- +// This should be deleted by the entity subsystemArray[jointSubsystem] +//--------------------------------------------------------------------- +// +#if 0 + JointSubsystem *joint_subsystem = jointSubsystem.GetCurrent(); + Unregister_Object(joint_subsystem); + delete joint_subsystem; +#endif +} + +//######################################################################## +// DamageZone Support +// +ResourceDescription::ResourceID + JointedMover::CreateDamageZoneStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .skl file + //------------------- + // + const char* skl_entry; + if ( + !model_file->GetEntry( + "video", + "skeleton", + &skl_entry + ) + ) + { + DEBUG_STREAM << model_name << " is missing .skl file specification!\n"; + return -1; + } + char *skl_filename = + MakePathedFilename(directories->videoDirectory, skl_entry); + Register_Pointer(skl_filename); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!\n"; +Dump_And_Die_1: + Unregister_Pointer(skl_filename); + delete[] skl_filename; + Unregister_Object(skl_file); + delete skl_file; + return ResourceDescription::NullResourceID; + } + + // + //------------------- + // Find the .dmg file + //------------------- + // + const char* dmg_entry; + if ( + !model_file->GetEntry( + "gamedata", + "DamageZones", + &dmg_entry + ) + ) + { + DEBUG_STREAM << model_name << " is missing .dmg file specification!\n"; + goto Dump_And_Die_1; + } + + char *dmg_filename = + MakePathedFilename(directories->modelDirectory, dmg_entry); + Register_Pointer(dmg_filename); + + NotationFile *dmg_file = new NotationFile(dmg_filename); + Register_Object(dmg_file); + + if (!dmg_file->PageCount()) + { + DEBUG_STREAM << dmg_filename << " is empty or missing!\n"; +Dump_And_Die_2: + Unregister_Pointer(dmg_filename); + delete[] dmg_filename; + Unregister_Object(dmg_file); + delete dmg_file; + goto Dump_And_Die_1; + } + + // + // Get the number of Damage zones + // + int dzone_count; + if ( + !skl_file->GetEntry( + "ROOT", + "DZoneCount", + &dzone_count + ) + ) + { + DEBUG_STREAM << model_name << " is missing DZoneCount \n"; + goto Dump_And_Die_2; + } + + DynamicMemoryStream damage_zone_stream; + + // + // write the Damage Zone Count Info from the + // .dmg file to the stream + // + damage_zone_stream << dzone_count; + + // + // Make an entry list of all the entries in the damage zone page + // + NameList *dzone_namelist = + skl_file->MakeEntryList("DamageZones","dz_"); + Register_Object(dzone_namelist); + + if (dzone_namelist->EntryCount() == 0) + { + DEBUG_STREAM << "No dZones listed in DamageZones Page"<GetFirstEntry(); + + while (dzone_entry) + { + ++num_dzones_found; + // + // Get dzone name in .skl file + // + Str_Copy( + current_dzone_name, + dzone_entry->GetName(), + sizeof(current_dzone_name) + ); + + // + // Create the stream for this damage zone + // + DamageZone::CreateStreamedDamageZone( + model_file, + model_name, + skl_file, + current_dzone_name, + &damage_zone_stream, + dmg_file, + directories + ); + + // + // Get next dzone entry in this segment page + // + dzone_entry = dzone_entry->GetNextEntry(); + } // End while more dzone_entries + + if(dzone_count != num_dzones_found) + { + DEBUG_STREAM <<"DZoneCount != damage zones found in Page DamageZones"<AddResourceMemoryStream( + model_name, + ResourceDescription::DamageZoneStreamResourceType, + 1, + ResourceDescription::Preload, + &damage_zone_stream + ); + Check(new_res); + // + // Free mem + // + Unregister_Pointer(skl_filename); + delete skl_filename; + Unregister_Object(skl_file); + delete skl_file; + Unregister_Pointer(dmg_filename); + delete dmg_filename; + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dzone_namelist); + delete dzone_namelist; + return new_res->resourceID; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + JointedMover::CreateSkeletonStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .skl file + //------------------- + // + const char *entry_data; + if ( + !model_file->GetEntry( + "video", + "skeleton", + &entry_data + ) + ) + { + DEBUG_STREAM << model_name << " is missing .skl file specification!\n"; + return -1; + } + // + // Get the name of the SKL File + // + char *filename = MakePathedFilename(directories->videoDirectory, entry_data); + Register_Pointer(filename); + + // + // Create a Notation file from the skl ASCII File + // + NotationFile *skl_file = new NotationFile(filename); + Register_Object(skl_file); + + // + // Get number of Segments(or Pages) + // + int segment_count = skl_file->PageCount(); + + // + // Do not count Lab_Only and DamageZones they are not included + // + if (skl_file->PageExists("LAB_ONLY")) + --segment_count; + if(skl_file->PageExists("DamageZones")) + --segment_count; + + if (!segment_count) + { + DEBUG_STREAM << model_name << " has no Segments!\n"; +Dump_And_Die: + Unregister_Pointer(filename); + delete filename; + Unregister_Object(skl_file); + delete skl_file; + return -1; + } + int joint_count; + if ( + !skl_file->GetEntry( + "ROOT", + "JointCount", + &joint_count + ) + ) + { + DEBUG_STREAM << model_name << " is missing JointCount \n"; + goto Dump_And_Die; + } + DynamicMemoryStream segment_stream; + + // + // Write Segment Count to the stream + // + segment_stream << segment_count << joint_count; + + // + // Create a list of the pages and get the first entry + // + NameList *segment_namelist = skl_file->MakePageList(); + Register_Object(segment_namelist); + NameList::Entry *segment_entry = segment_namelist->GetFirstEntry(); + int + parent_index = -1, + children_count; + + CString + segment_page_name; + + EulerAngles + rotation; + + Point3D + translation; + + LinearMatrix + base_offset(LinearMatrix::Identity); + + while(segment_entry) + { + segment_page_name = segment_entry->GetName(); + + if( + (strcmp(segment_page_name, "LAB_ONLY") == 0) || + (strcmp(segment_page_name,"DamageZones") ==0) + ) + { + segment_entry = segment_entry->GetNextEntry(); + continue; + } + + segment_stream << segment_page_name; + // + // Get the information about the parent + // + const char *parent_name; + if( + skl_file->GetEntry( + segment_page_name, + "parent", + &parent_name + ) + ) + { + parent_index = GetSegmentIndex(parent_name, skl_file); + if(parent_index == -1) + { + DEBUG_STREAM<GetEntry( + segment_page_name, + "Type", + &joint_name) + ) + { + if( strcmp("ROOT", segment_page_name) != 0) + { + is_site = True; + } + } + else + { + if(strcmp(joint_name,"static")==0) + { + joint_type = Joint::StaticJointType; + } + else + if(strcmp(joint_name, "hingex")==0) + { + joint_type = Joint::HingeXJointType; + } + else + if(strcmp(joint_name,"hingey")==0) + { + joint_type = Joint::HingeYJointType; + } + else + if(strcmp(joint_name,"hingez")==0) + { + joint_type = Joint::HingeZJointType; + } + else + if(strcmp(joint_name,"ball")==0) + { + joint_type = Joint::BallJointType; + } + else + if(strcmp(joint_name,"balltranslate")==0) + { + joint_type = Joint::BallTranslationJointType; + } + } + segment_stream << is_site << joint_type; + // + // Get offsets + // + skl_file->GetEntry(segment_page_name, "tranx" ,&translation.x); + skl_file->GetEntry(segment_page_name, "trany" ,&translation.y); + skl_file->GetEntry(segment_page_name, "tranz" ,&translation.z); + skl_file->GetEntry(segment_page_name, "pitch" ,&rotation.pitch.angle); + skl_file->GetEntry(segment_page_name, "yaw" ,&rotation.yaw.angle); + skl_file->GetEntry(segment_page_name, "roll" ,&rotation.roll.angle); + + base_offset = translation; + base_offset = rotation; + + // + // Write out the base offset + // + segment_stream << base_offset; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Primary Damage Zone + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char* skl_entry; + if (!model_file->GetEntry( + "video", + "skeleton", + &skl_entry + ) + ) + { + goto Dump_And_Die; + } + else + { + CString skl_filename = + MakePathedFilename(directories->videoDirectory, skl_entry); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!"<GetEntry( + segment_page_name, + "dzone", + &dzone_name + ) + ) + { + primary_damage_zone = GetDamageZoneIndex(dzone_name, skl_file); + } + else + { + primary_damage_zone = -1; + } + segment_stream << primary_damage_zone; + Unregister_Object(skl_file); + delete skl_file; + } + + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (! + InitVideoObjectNames( + &segment_stream, + model_file, + segment_page_name, + directories + ) + ) + { + goto Dump_And_Die; + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL DESTROYED VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (! + InitDestroyedVideoObjectNames( + &segment_stream, + model_file, + segment_page_name, + directories + ) + ) + { + goto Dump_And_Die; + } + + // + // Get the damageZones associated with this segment + // + NameList *damage_zone_list = + skl_file->MakeEntryList(segment_entry->GetName(), "dzone"); + Register_Object(damage_zone_list); + + NameList::Entry *damage_zone_entry = damage_zone_list->GetFirstEntry(); + + int damage_zone_count = damage_zone_list->EntryCount(); + + segment_stream << damage_zone_count; + + if (damage_zone_count) + { + for (int dd=0;ddGetChar(); + + int damage_zone_index; + damage_zone_index = + GetDamageZoneIndex(damage_zone_name, skl_file); + + if(damage_zone_index == -1) + { + + DEBUG_STREAM<GetNextEntry(); + } + } + Unregister_Object(damage_zone_list); + delete damage_zone_list; + + // + // Get the number of children, 0 if no children + // + NameList *children_list = + skl_file->MakeEntryList(segment_entry->GetName(),"joint"); + Register_Object(children_list); + NameList::Entry *child_entry = children_list->GetFirstEntry(); + children_count = 0; + while(child_entry) + { + ++children_count; + child_entry = child_entry->GetNextEntry(); + } + // + // Write how many children + // + segment_stream << children_count; + if(children_count) + { + child_entry = children_list->GetFirstEntry(); + // + // Write out the segment index for every child + // + for(int cc=0;ccGetChar(), skl_file); + if(child_index == -1) + { + DEBUG_STREAM<GetName()<<" Not Found!!"<GetNextEntry(); + } + } + Unregister_Object(children_list); + delete children_list; + segment_entry = segment_entry->GetNextEntry(); + } + + // + //-------------------------------------------------------------------- + // Write the stream out to disk. + //-------------------------------------------------------------------- + // + ResourceDescription *new_res = + resource_file->AddResourceMemoryStream( + model_name, + ResourceDescription::SkeletonStreamResourceType, + 1, + ResourceDescription::Preload, + &segment_stream + ); + Check(new_res); + + // + // Fre Mem + // + Unregister_Pointer(filename); + delete filename; + Unregister_Object(skl_file); + delete skl_file; + Unregister_Object(segment_namelist); + delete segment_namelist; + + return new_res->resourceID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + JointedMover::InitDestroyedVideoObjectNames( + MemoryStream *mem_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ) +{ + Check(model_file); + Check(mem_stream); + + NameList *skl_namelist = model_file->MakeEntryList("video","destroyed"); + Register_Object(skl_namelist); + int entry_count = skl_namelist->EntryCount(); + *mem_stream << entry_count; + + if (!entry_count) + { + Unregister_Object(skl_namelist); + delete skl_namelist; + return True; + } + Verify(entry_count); + + NameList::Entry *skl_entry = skl_namelist->GetFirstEntry(); + while(skl_entry) + { + CString entry_name = skl_entry->GetName(); + EntitySegment::SkeletonType skeleton_type; + if (! entry_name.Compare("destroyed") ) + { + skeleton_type = EntitySegment::SkeletonType_N; + } + else if (! entry_name.Compare("destroyeds") ) + { + skeleton_type = EntitySegment::SkeletonType_S; + } + else if (! entry_name.Compare("destroyedt") ) + { + skeleton_type = EntitySegment::SkeletonType_T; + } + else if (! entry_name.Compare("destroyedo") ) + { + skeleton_type = EntitySegment::SkeletonType_O; + } + else if (! entry_name.Compare("destroyeda") ) + { + skeleton_type = EntitySegment::SkeletonType_A; + } + else if (! entry_name.Compare("destroyedb") ) + { + skeleton_type = EntitySegment::SkeletonType_B; + } + else if (! entry_name.Compare("destroyedc") ) + { + skeleton_type = EntitySegment::SkeletonType_C; + } + else if (! entry_name.Compare("destroyedd") ) + { + skeleton_type = EntitySegment::SkeletonType_D; + } + *mem_stream << skeleton_type; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the video object filename + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString short_skl_filename = skl_entry->GetChar(); + CString skl_filename = + MakePathedFilename(directories->videoDirectory, short_skl_filename); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!"<GetEntry( + page_name, + "Object", + &c_name + ) + ) + { + video_object_name = c_name; + } + else + { + video_object_name = "None"; + } + *mem_stream << video_object_name; + + Unregister_Object(skl_file); + delete skl_file; + + skl_entry = skl_entry->GetNextEntry(); + } + Unregister_Object(skl_namelist); + delete skl_namelist; + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + JointedMover::InitVideoObjectNames( + MemoryStream *mem_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ) +{ + Check(model_file); + Check(mem_stream); + + NameList *skl_namelist = model_file->MakeEntryList("video","skeleton"); + Register_Object(skl_namelist); + int entry_count = skl_namelist->EntryCount(); + + Verify(entry_count); + *mem_stream << entry_count; + + NameList::Entry *skl_entry = skl_namelist->GetFirstEntry(); + while(skl_entry) + { + CString entry_name = skl_entry->GetName(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write out the skeleton type + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + EntitySegment::SkeletonType skeleton_type; + if (! entry_name.Compare("skeleton") ) + { + skeleton_type = EntitySegment::SkeletonType_N; + } + else if (! entry_name.Compare("skeletons") ) + { + skeleton_type = EntitySegment::SkeletonType_S; + } + else if (! entry_name.Compare("skeletont") ) + { + skeleton_type = EntitySegment::SkeletonType_T; + } + else if (! entry_name.Compare("skeletono") ) + { + skeleton_type = EntitySegment::SkeletonType_O; + } + else if (! entry_name.Compare("skeletona") ) + { + skeleton_type = EntitySegment::SkeletonType_A; + } + else if (! entry_name.Compare("skeletonb") ) + { + skeleton_type = EntitySegment::SkeletonType_B; + } + else if (! entry_name.Compare("skeletonc") ) + { + skeleton_type = EntitySegment::SkeletonType_C; + } + else if (! entry_name.Compare("skeletond") ) + { + skeleton_type = EntitySegment::SkeletonType_D; + } + *mem_stream << skeleton_type; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the video object filename + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString short_skl_filename = skl_entry->GetChar(); + CString skl_filename = + MakePathedFilename(directories->videoDirectory, short_skl_filename); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!"<GetEntry( + page_name, + "Object", + &c_name + ) + ) + { + video_object_name = c_name; + } + else + { + video_object_name = "None"; + } + *mem_stream << video_object_name; + + Unregister_Object(skl_file); + delete skl_file; + + skl_entry = skl_entry->GetNextEntry(); + } + Unregister_Object(skl_namelist); + delete skl_namelist; + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + JointedMover::GetDamageZoneIndex( + CString damage_zone_name, + NotationFile *skl_file + ) +{ + int damage_zone_index = -1; + + NameList *name_list = skl_file->MakeEntryList("DamageZones", "dz_"); + Register_Object(name_list); + + if (name_list->EntryCount() == 0) + { + DEBUG_STREAM << "No dZones listed in DamageZones Page"<GetFirstEntry(); + while(damage_zone) + { + if(strcmp(damage_zone->GetName(), damage_zone_name) == 0) + { + Convert_From_Ascii(damage_zone->GetChar(), &damage_zone_index); + Unregister_Object(name_list); + delete name_list; + return damage_zone_index; + } + damage_zone = damage_zone->GetNextEntry(); + } + Unregister_Object(name_list); + delete name_list; + + return damage_zone_index; + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + JointedMover::GetSegmentIndex( + CString segment_name, + NotationFile *skl_file + ) +{ + int segment_index=-1; + + char page_name[128]; + NameList *page_list = skl_file->MakePageList(); + Register_Object(page_list); + NameList::Entry *current_entry = page_list->GetFirstEntry(); + while(current_entry) + { + Str_Copy( + page_name, + current_entry->GetName(), + sizeof(page_name) + ); + if( + (strcmp(page_name, "LAB_ONLY") == 0) || + (strcmp(page_name,"DamageZones") == 0) + ) + { + current_entry = current_entry->GetNextEntry(); + continue; + } + ++segment_index; + if((strcmp(page_name, segment_name) == 0)) + { + Unregister_Object(page_list); + delete page_list; + return segment_index; + } + current_entry = current_entry->GetNextEntry(); + } + Unregister_Object(page_list); + delete page_list; + return -1; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointedMover* + JointedMover::Make(JointedMover::MakeMessage *creation_message) +{ + return new JointedMover(creation_message, DefaultData); +} +//########################################################################## +//########################## Animation ############################### +//########################################################################## + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AnimationInstance::AnimationInstance(JointedMover *jointed_mover) +{ + Check_Pointer(this); + Check(jointed_mover); + + lerpToZero = False; + moverToAnimate = jointed_mover; + jointSubToAnimate = jointed_mover->GetJointSubsystem(); + animationResource = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + AnimationInstance::SetAnimation( + ResourceDescription::ResourceID animation_number, + JointedMover::AnimationCallback finished_callback + ) +{ + Check_Pointer(this); + finishedCallback = finished_callback; + currentTime = 0.0f; + currentFrame = 0; + + if (animationResource) + { + Check(animationResource); + animationResource->Unlock(); + } + animationResource = + application->GetResourceFile()->FindResourceDescription( + animation_number + ); + Check(animationResource); + animationResource->Lock(); + int *animation_data = (int*)animationResource->resourceAddress; + Check_Pointer(animation_data); + frameCount = animation_data[0]; + jointCount = animation_data[1]; + footStepThreshold = (float *)&animation_data[2]; + jointIndices = &animation_data[3]; + frameStart = (Scalar*)(jointIndices + jointCount); + + keyFrames = frameStart + frameCount; + currentFrameTo = keyFrames; + void* to; + to = keyFrames; + // + //----------------------------------- + // find the end of the keyframes data + //----------------------------------- + // + for(int ii=0;iiGetJoint(jointIndices[jj])->GetJointType()) + { + case Joint::BallTranslationJointType: + { + to = (void *)((char *)to+sizeof(EulerAngles)); + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeXJointType: + case Joint::HingeYJointType: + case Joint::HingeZJointType: + { + to = (void *)((char *)to+sizeof(Hinge)); + break; + } + case Joint::BallJointType: + to = (void *)((char *)to+sizeof(EulerAngles)); + break; + } + } + + // + // + // This should be contained in the keyframes + // + // keyJointPos = (Vector3D*)(keyFrames + jointCount*frameCount); + + rootTranslations = (Vector3D*)(to); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AnimationInstance::~AnimationInstance() +{ + if (animationResource) + { + Check(animationResource); + animationResource->Unlock(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + AnimationInstance::Animate(Scalar time_slice, Logical move_joints) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Find the frame to lerp towards. As each frame boundary is crossed, set + // the joints to the position of that boundary and adjust the remaining time + // to lerp + //-------------------------------------------------------------------------- + // + int i; + // + //----------------------------------------- + // This void * can point to any joint type + //----------------------------------------- + // + void + *to; + + + Scalar frame_time = currentTime + time_slice; + Scalar movement = 0.0f; + + // + //------------------------------------------------------------- + // to points to the place in the memory stream we left off at + // last time we were on this loop + //------------------------------------------------------------- + // + to = currentFrameTo; + Joint *current_joint; + + while (currentFrame < frameCount) + { + if (frame_time < frameStart[currentFrame]) + { + break; + } + for (i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Only modify the joint if the value has changed + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (current_joint->GetEulerAngles() != *(EulerAngles*)to) + { + if (move_joints) + { + current_joint->SetRotation(*(EulerAngles*)to); + } + } + to = (void *)((char *)to+sizeof(EulerAngles)); + + if (current_joint->GetTranslation() != *(Point3D*)to) + { + if (move_joints) + { + current_joint->SetTranslation(*(Point3D*)to); + } + } + + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeXJointType: + case Joint::HingeYJointType: + case Joint::HingeZJointType: + { + if (current_joint->GetHinge() != *(Hinge*) to) + { + if (move_joints) + { + current_joint->SetHinge(*(Hinge*) to); + } + } + to = (void *)((char *)to+sizeof(Hinge)); + break; + } + case Joint::BallJointType: + + if (current_joint->GetEulerAngles() != *(EulerAngles*)to) + { + if (move_joints) + { + current_joint->SetRotation(*(EulerAngles*)to); + } + } + to = (void *)((char *)to+sizeof(EulerAngles)); + break; + case Joint::StaticJointType: + break; + } + } + movement += + (frameStart[currentFrame] - currentTime) + * rootTranslations[currentFrame].z; + currentTime = frameStart[currentFrame]; + ++currentFrame; + } + + // + //---------------------------------------------------------------------- + // We we have run off the end of the animation, trigger the callback and + // return + //---------------------------------------------------------------------- + // + if (currentFrame == frameCount) + { + + movement += + (moverToAnimate->*finishedCallback)( + animationResource->resourceID, + frame_time - frameStart[frameCount - 1], + move_joints + ); + return movement; + } + + currentFrameTo = to; + // + //------------------------------------------------------- + // Set up to lerp the rotations between to two key frames + //------------------------------------------------------- + // + Verify(!Small_Enough(frameStart[currentFrame] - currentTime)); + Scalar delta = + (frame_time - currentTime)/(frameStart[currentFrame] - currentTime); + + for (i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + Point3D new_trans; + EulerAngles new_angles; + + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + if (move_joints) + { + current_joint->SetRotation(new_angles); + } + } + to = (void *)((char *)to+sizeof(EulerAngles)); + + new_trans.Lerp( + current_joint->GetTranslation(), + *(Vector3D*)to, + delta + ); + if (current_joint->GetTranslation() != new_trans) + { + if (move_joints) + { + current_joint->SetTranslation(new_trans); + } + } + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeZJointType: + case Joint::HingeYJointType: + case Joint::HingeXJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + *(Hinge*)to, + delta + ); + if (current_joint->GetRadians() != new_hinge.rotationAmount) + { + if (move_joints) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + } + to = (void *)((char *)to+sizeof(Hinge)); + + break; + } + case Joint::BallJointType: + { + EulerAngles new_angles; + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + if (move_joints) + { + current_joint->SetRotation(new_angles); + } + } + + to = (void *)((char *)to+sizeof(EulerAngles)); + + break; + } + case Joint::StaticJointType: + break; + } + } + movement += (frame_time - currentTime) * rootTranslations[currentFrame].z; + currentTime = frame_time; + return movement; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +Logical + AnimationInstance::LerpToPose(Scalar time_slice, Scalar time_to_lerp, Logical move_joints) +{ + Check(this); + + int i; + // + //----------------------------------------- + // This void * can point to any joint type + //----------------------------------------- + // + void + *to; + + + if (!lerpToZero) + { + lerpToZero = True; + deltaTime = time_to_lerp; + } + + Scalar delta = time_slice / deltaTime; + + + // + //------------------------------------------------------------- + // to points to the place in the memory stream we left off at + // last time we were on this loop + //------------------------------------------------------------- + // + + to = currentFrameTo; + Joint *current_joint; + + if (move_joints) + { + for (i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + Point3D new_trans; + EulerAngles new_angles; + + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + to = (void *)((char *)to+sizeof(EulerAngles)); + + new_trans.Lerp( + current_joint->GetTranslation(), + *(Vector3D*)to, + delta + ); + if (current_joint->GetTranslation() != new_trans) + { + current_joint->SetTranslation(new_trans); + } + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeZJointType: + case Joint::HingeYJointType: + case Joint::HingeXJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + *(Hinge*)to, + delta + ); + if (current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + to = (void *)((char *)to+sizeof(Hinge)); + + break; + } + case Joint::BallJointType: + { + EulerAngles new_angles; + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + + to = (void *)((char *)to+sizeof(EulerAngles)); + + break; + } + case Joint::StaticJointType: + break; + } + } + + } + + deltaTime -= time_slice; + if (deltaTime <= 0.0f) + { + lerpToZero = False; + return False; + } + return True; + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +Logical + AnimationInstance::LerpToRest(Scalar time_slice, Scalar time_to_lerp, Logical move_joints) +{ + + + if (!lerpToZero) + { + lerpToZero = True; + deltaTime = time_to_lerp; + } + + Scalar delta = time_slice / deltaTime; + + if (move_joints) + { + EulerAngles zero_euler(0.0f, 0.0f, 0.0f); + Hinge zero_hingeX(0.0f, X_Axis); + Hinge zero_hingeY(0.0f, Y_Axis); + Hinge zero_hingeZ(0.0f, Z_Axis); + Vector3D zero_vector(0.0f, 0.0f, 0.0f); + + for (int i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + EulerAngles new_angles; + new_angles.Lerp( + current_joint->GetEulerAngles(), + zero_euler, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + + Point3D new_trans; + + new_trans.Lerp( + current_joint->GetTranslation(), + zero_vector, + delta + ); + if (current_joint->GetTranslation() != new_trans) + { + current_joint->SetTranslation(new_trans); + } + break; + } + case Joint::HingeXJointType: + { + Hinge new_hinge; + + new_hinge.Lerp( + current_joint->GetHinge(), + zero_hingeX, + delta + ); + if(current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + break; + + } + case Joint::HingeYJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + zero_hingeY, + delta + ); + if(current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + break; + } + case Joint::HingeZJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + zero_hingeZ, + delta + ); + if(current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + break; + } + case Joint::BallJointType: + { + EulerAngles new_angles; + + new_angles.Lerp( + current_joint->GetEulerAngles(), + zero_euler, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + + break; + } + case Joint::StaticJointType: + break; + } + } + } + deltaTime -= time_slice; + if (deltaTime <= 0.0f) + { + lerpToZero = False; + return False; + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void + AnimationInstance::SnapToRest(Logical move_joints) +{ + + if (!move_joints) + { + return; + } + + EulerAngles zero_euler(0.0f, 0.0f, 0.0f); + Hinge zero_hingeX(0.0f, X_Axis); + Hinge zero_hingeY(0.0f, Y_Axis); + Hinge zero_hingeZ(0.0f, Z_Axis); + Point3D zero_point(0.0f, 0.0f, 0.0f); + + for (int i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + current_joint->SetRotation(zero_euler); + current_joint->SetTranslation(zero_point); + break; + } + case Joint::HingeXJointType: + { + current_joint->SetHinge(zero_hingeX); + break; + } + case Joint::HingeYJointType: + { + current_joint->SetHinge(zero_hingeY); + break; + } + case Joint::HingeZJointType: + { + current_joint->SetHinge(zero_hingeZ); + break; + } + case Joint::BallJointType: + { + current_joint->SetRotation(zero_euler); + break; + } + case Joint::StaticJointType: + break; + } + } +} +//########################################################################## +//############## Sketon Notation file utilities #################### +//########################################################################## + + +int + Get_Active_Joint_Count(NotationFile *skl_file) +{ + NameList *namelist = skl_file->MakePageList("joint"); + Register_Object(namelist); + NameList::Entry *entry = namelist->GetFirstEntry(); + + int count = 0; + + while (entry) + { + ++count; + entry = entry->GetNextEntry(); + } + + Unregister_Object(namelist); + delete namelist; + + return count; +} + +Logical + JointedMover::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/JMOVER.HPP b/CODE/RP/MUNGA/JMOVER.HPP new file mode 100644 index 0000000..123cc41 --- /dev/null +++ b/CODE/RP/MUNGA/JMOVER.HPP @@ -0,0 +1,270 @@ +//===========================================================================// +// File: jmover.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(JMOVER_HPP) +# define JMOVER_HPP + +# if !defined(MOVER_HPP) +# include +# endif + +# if !defined(JOINT_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(SEGMENT_HPP) +# include +# endif + +//############################################################################## +//######################## JointedMover ################################## +//############################################################################## + + class JointedMover: + public Mover + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + #if 0 + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum{ + SegmentCountAttributeID = Mover::NextAttributeID, + SegmentTableAttributeID, + JointSubsystemAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Segment Support + // + public: + + EntitySegment::SegmentTable + segmentTable; + + int + segmentCount; + + EntitySegment* + GetSegmentFromDamageZone(CString damage_zone); + + EntitySegment* + GetSegment(CString segment_name); + + EntitySegment* + GetSegment(int segment_index) + { + Check(this); + EntitySegment::SegmentTableIterator iterator(segmentTable); + return iterator.GetNth(segment_index); + } + + SlotOf + jointSubsystem; + + JointSubsystem* + GetJointSubsystem() + { + Check(this); return jointSubsystem.GetCurrent(); + } + + void + GetSegmentToWorld( + EntitySegment &my_segment, + LinearMatrix *transform + ); + + protected: + void + InitializeChildPointers(EntitySegment *current_segment); + + void + CalcSegmentTransforms(EntitySegment *final_segment); + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Animation Support + // + public: + + typedef + Scalar (JointedMover::*AnimationCallback)( + ResourceDescription::ResourceID animation_number, + Scalar carryover, + Logical animate_joints + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (JointedMover::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + + static JointedMover* + Make(MakeMessage *creation_message); + + static int + CreateDamageZoneStream ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static ResourceDescription::ResourceID + CreateSkeletonStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static Logical + InitDestroyedVideoObjectNames( + MemoryStream *segment_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ); + + + static Logical + InitVideoObjectNames( + MemoryStream *segment_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ); + static int + GetSegmentIndex( + CString segment_name, + NotationFile *skl_file + ); + + static int + GetDamageZoneIndex( + CString damage_zone_name, + NotationFile *skl_file + ); + + JointedMover( + MakeMessage *creation_message, + SharedData &virtual_data + ); + ~JointedMover(); + + Logical + TestInstance() const; + }; + +//########################################################################## +//########################## Animation ############################### +//########################################################################## + + class AnimationInstance: + public Plug + { + private: + Logical lerpToZero; + Scalar deltaTime; + public: + AnimationInstance(JointedMover *jointed_mover); + ~AnimationInstance(); + + Scalar Animate(Scalar time_slice, Logical move_joints = True); + + Logical + LerpToPose(Scalar time_slice, Scalar time_to_lerp, Logical move_joints = True); + + Logical LerpToRest(Scalar time_slice, Scalar time_to_lerp, Logical move_joints = True); + + void SnapToRest(Logical move_joints = True); + + void + SetAnimation( + ResourceDescription::ResourceID animation_number, + JointedMover::AnimationCallback finished_callback + ); + + int + frameCount, + jointCount, + *jointIndices; + float + *footStepThreshold; + Scalar + *frameStart; + + void + *keyFrames; + + void + *currentFrameTo; + + Vector3D + *keyJointPos, + *rootTranslations; + + JointSubsystem + *jointSubToAnimate; + + protected: + int currentFrame; + JointedMover *moverToAnimate; + ResourceDescription *animationResource; + JointedMover::AnimationCallback finishedCallback; + Scalar currentTime; + }; + +#endif diff --git a/CODE/RP/MUNGA/JOINT.CPP b/CODE/RP/MUNGA/JOINT.CPP new file mode 100644 index 0000000..d9f8deb --- /dev/null +++ b/CODE/RP/MUNGA/JOINT.CPP @@ -0,0 +1,534 @@ +//============================================================================// +// File: joint.cc // +// Project: Munga // // +// Contents: CLASS Joint Subsystem Imp // +// Implementation details of Class Joint // +//----------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ------------------------------------------------------------// +// 05/11/95 JM Initial coding. // +//----------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//============================================================================// + +#include +#pragma hdrstop + +#if !defined(JOINT_HPP) +# include +#endif + +#if !defined(JMOVER_HPP) +# include +#endif + +//########################################################################## +//######################## BallTranslation ############################ +//########################################################################## + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile BallTranslation *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BallTranslation::BallTranslation() +{ + ballJoint = EulerAngles::Identity; + jointTranslation = Point3D::Identity; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BallTranslation::BallTranslation(const BallTranslation &new_ball) +{ + Check(&new_ball); + ballJoint = new_ball.ballJoint; + jointTranslation = new_ball.jointTranslation; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BallTranslation::TestInstance() const +{ + return True; +} + +//########################################################################## +//########################## Joint ############################### +//########################################################################## + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Joint *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::Joint(JointSubsystem *subsystem) +{ + Check(subsystem); + + jointType = StaticJointType; + jointModified = True; + ballJoint = NULL; + jointSubsystem = subsystem; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::Joint( + JointSubsystem *subsystem, + JointType joint_type +) +{ + Check(subsystem); + + jointType = joint_type; + jointModified = True; + jointSubsystem = subsystem; + ballJoint = NULL; + + switch(joint_type) + { + case Joint::BallJointType: + ballJoint = new EulerAngles(EulerAngles::Identity); + Register_Object(ballJoint); + break; + + case Joint::BallTranslationJointType: + ballTranslationJoint = new BallTranslation; + Register_Object(ballTranslationJoint); + break; + + case Joint::HingeXJointType: + hingeJoint = new Hinge(X_Axis, 0.0f); + Register_Object(hingeJoint); + break; + + case Joint::HingeYJointType: + hingeJoint = new Hinge(Y_Axis, 0.0f); + Register_Object(hingeJoint); + break; + + case Joint::HingeZJointType: + hingeJoint = new Hinge(Z_Axis, 0.0f); + Register_Object(hingeJoint); + break; + + case Joint::StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::Joint(const Joint &new_joint) +{ + jointModified = True; + jointSubsystem = new_joint.jointSubsystem; + jointType = new_joint.jointType; + ballJoint = NULL; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a new joint of correct size + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + switch(new_joint.jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + hingeJoint = new Hinge(*new_joint.hingeJoint); + Register_Object(hingeJoint); + break; + + case BallJointType: + ballJoint = new EulerAngles(*new_joint.ballJoint); + Register_Object(ballJoint); + break; + + case BallTranslationJointType: + ballTranslationJoint = + new BallTranslation(*new_joint.ballTranslationJoint); + Register_Object(ballTranslationJoint); + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint& + Joint::operator=(const Joint &new_joint) +{ + Check(this); + + jointModified = True; + + // + //--------------------------------------------------- + // If not same kind of joint free up old joint memory + //--------------------------------------------------- + // + if(new_joint.jointType != jointType) + { + switch(jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + Unregister_Object(hingeJoint); + delete hingeJoint; + break; + + case BallJointType: + Unregister_Object(ballJoint); + delete ballJoint; + break; + + case BallTranslationJointType: + Unregister_Object(ballTranslationJoint); + delete ballTranslationJoint; + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } + jointType = new_joint.jointType; + + // + //----------------------------------- + // Create a new joint of correct size + //----------------------------------- + // + switch(new_joint.jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + hingeJoint = new Hinge(*new_joint.hingeJoint); + Register_Object(hingeJoint); + break; + + case BallJointType: + ballJoint = new EulerAngles(*new_joint.ballJoint); + Register_Object(ballJoint); + break; + + case BallTranslationJointType: + ballTranslationJoint = + new BallTranslation(*new_joint.ballTranslationJoint); + Register_Object(ballTranslationJoint); + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } + } + + // + //----------------------------------- + // Otherwise simply copy all the data + //----------------------------------- + // + else + { + switch(new_joint.jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + hingeJoint = new_joint.hingeJoint; + break; + + case BallJointType: + ballJoint = new_joint.ballJoint; + break; + + case BallTranslationJointType: + ballTranslationJoint = new_joint.ballTranslationJoint; + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } + } + return (*this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::~Joint() +{ + switch(jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + Unregister_Object(hingeJoint); + delete hingeJoint; + break; + + case BallJointType: + Unregister_Object(ballJoint); + delete ballJoint; + break; + + case BallTranslationJointType: + Unregister_Object(ballTranslationJoint); + delete ballTranslationJoint; + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const EulerAngles& + Joint::GetEulerAngles() +{ + Check(this); + switch(jointType) + { + case BallJointType: + return *ballJoint; + case BallTranslationJointType: + return ballTranslationJoint->GetEulerAngles(); +#if DEBUG_LEVEL>0 + default: + Fail("Joint must be a BallJoint of BallTranslationJoint \n"); + break; +#endif + } + return *ballJoint; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetHinge(const Hinge &new_hinge) +{ + Check(this); + if(*hingeJoint != new_hinge) + { + jointModified = True; + (*hingeJoint) = new_hinge; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetRotation(const EulerAngles &new_angles) +{ + Check(this); + + switch(jointType) + { + case BallJointType: + if ((*ballJoint) != new_angles) + { + (*ballJoint) = new_angles; +Joint_Modified: + jointModified = True; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } + break; + + case BallTranslationJointType: + if (ballTranslationJoint->GetEulerAngles() != new_angles) + { + ballTranslationJoint->SetEulerAngles(new_angles); + goto Joint_Modified; + } + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Joint must be a Ball or Ball Translation Joint! \n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetRotation(const Radian &new_radian) +{ + Check(this); + + Verify ( + (jointType == HingeXJointType ) || + (jointType == HingeYJointType ) || + (jointType == HingeZJointType ) + ); + if(hingeJoint->rotationAmount != new_radian) + { + hingeJoint->rotationAmount = new_radian; + jointModified = True; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetTranslation(const Point3D &new_trans) +{ + Check(this); + jointModified = True; + + Verify(jointType == BallTranslationJointType); + if (ballTranslationJoint->GetTranslation() != new_trans) + { + ballTranslationJoint->SetTranslation(new_trans); + jointModified = True; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } +} + +//############################################################################# +// Shared Data Support +// +JointSubsystem::SharedData + JointSubsystem::DefaultData( + JointSubsystem::ClassDerivations, + JointSubsystem::MessageHandlers, + JointSubsystem::AttributeIndex, + JointSubsystem::StateCount + ); + +Derivation + JointSubsystem::ClassDerivations( + Subsystem::ClassDerivations, + "JointSubsystem" + ); + +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + JointSubsystem::JointSubsystemSimulation(Scalar ) +{ + Check(this); + + + Joint *current_joint; + JointTableIterator iterator(jointTable); + + while ((current_joint = iterator.ReadAndNext() )!= NULL) + { + if (current_joint->IsJointModified()) + { + JointedMover *jointed_mover = Cast_Object( + JointedMover*, + GetEntity() + ); + jointed_mover->ForceSegmentTransformUpdate(); + break; + } + } + +} +#endif + +//############################################################################# +// Constructer/Destructor Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointSubsystem::JointSubsystem( + Entity *owner, + int subsystem_ID, + SharedData &shared_data +): + Subsystem( + owner, + subsystem_ID, + "Joint Subsystem", + JointSubsystemClassID, + shared_data + ), + jointTable(NULL, False) +{ + damageZone = new DamageZone(this, 0); + Register_Object(damageZone); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointSubsystem::~JointSubsystem() +{ + JointTableIterator iterator(jointTable); + iterator.DeletePlugs(); + Unregister_Object(damageZone); + delete damageZone; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + JointSubsystem::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + + diff --git a/CODE/RP/MUNGA/JOINT.HPP b/CODE/RP/MUNGA/JOINT.HPP new file mode 100644 index 0000000..da929ba --- /dev/null +++ b/CODE/RP/MUNGA/JOINT.HPP @@ -0,0 +1,297 @@ +//============================================================================// +// File: joint.hh // +// Project: Munga // // +// Contents: Sets up Joint Subsystem // +// Definition of Class Joint // +//----------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ------------------------------------------------------------// +// 05/11/95 JM Initial coding. // +//----------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//============================================================================// +#if !defined JOINT_HPP +# define JOINT_HPP + +# if !defined(SUBSYSTM_HPP) +# include +# endif + +# if !defined(ROTATION_HPP) +# include +# endif + +# if !defined(MEMSTRM_HPP) +# include +# endif + + + //##################### Forward Class Declarations ########################## + class Entity; + class Joint; + class JointSubsystem; + + //########################################################################## + //######################## BallTranslation ############################ + //########################################################################## + + class BallTranslation + { + friend class Joint; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile BallTranslation *); + #endif + + protected: + Point3D + jointTranslation; + EulerAngles + ballJoint; + + const EulerAngles& + GetEulerAngles() + {Check(this); return ballJoint;} + const Point3D& + GetTranslation() + {Check(this); return jointTranslation;} + + void + SetTranslation(const Point3D &new_trans) + {Check(this); jointTranslation = new_trans; } + void + SetEulerAngles(const EulerAngles &new_angles) + {Check(this); ballJoint = new_angles;} + + BallTranslation(); + BallTranslation(const BallTranslation &new_ball); + + Logical + TestInstance() const; + + BallTranslation& + operator=(const BallTranslation &new_ball) + { + ballJoint = new_ball.ballJoint; + jointTranslation = new_ball.jointTranslation; + return (*this); + } + }; + +//########################################################################## +//############################ Joint ################################# +//########################################################################## + + class Joint : + public Plug + { + friend class BallTranslation; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Joint *); + #endif + + public: + enum JointType { + NULLJointType = -1, + HingeXJointType, + HingeYJointType, + HingeZJointType, + StaticJointType, + BallJointType, + BallTranslationJointType + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructors + // + public: + Joint(JointSubsystem *subsystem); + Joint(const Joint &new_joint); + Joint( + JointSubsystem *subsystem, + JointType joint_type + ); + ~Joint(); + + Joint& + operator=(const Joint &new_joint); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Joint Data + // + protected: + union { + EulerAngles *ballJoint; + Hinge *hingeJoint; + BallTranslation *ballTranslationJoint; + }; + + JointType + jointType; + Logical + jointModified; + JointSubsystem + *jointSubsystem; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Reading Joints + // + public: + const Hinge& + GetHinge() + {Check(this); return *hingeJoint;} + + const EulerAngles& + GetEulerAngles(); + + const Point3D& + GetTranslation() + { + Check(this); + Verify(jointType == BallTranslationJointType); + return ballTranslationJoint->GetTranslation(); + } + + Radian + GetRadians() const + { + Check(this); + Verify ( + (jointType == HingeXJointType ) || + (jointType == HingeYJointType ) || + (jointType == HingeZJointType ) + ); + return hingeJoint->rotationAmount; + } + + JointType + GetJointType() const + {Check(this); return jointType; } + + Logical + IsJointModified() const + {Check(this); return jointModified;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Writing Joints + // + public: + void + SetHinge(const Hinge &new_hinge); + + void + SetRotation(const EulerAngles &new_angles); + + void + SetRotation(const Radian &new_radian); + + void + SetTranslation(const Point3D &new_trans); + + void + JointModified(Logical new_value=True) + {Check(this); jointModified = new_value;} + }; + +//############################################################################## +//####################### Class JointSubsystem ################################# +//############################################################################## + +class JointSubsystem : + public Subsystem +{ + friend Joint; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + typedef void + (JointSubsystem::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // local Support + // + public: + + typedef TableOf + JointTable; + + typedef TableIteratorOf + JointTableIterator; + + Joint* + GetJoint(int joint_index) + { + Check(this); + JointTableIterator iterator(jointTable); + return iterator.GetNth(joint_index); } + + void + AddJoint( + int joint_index, + Joint *new_joint + ) + {Check(this); jointTable.AddValue(new_joint,joint_index);} + + int + GetJointCount() + { + Check(this); + JointTableIterator iterator(jointTable); + return iterator.GetSize(); + } + + Logical + AreJointsModified() + {Check(this); return jointsModified;} + void + ModifyJoints(Logical modified=True) + {Check(this); jointsModified=modified;} + + protected: + + JointTable + jointTable; + Logical + jointsModified; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction Support + // + + public: + + JointSubsystem( + Entity *owner, + int subsystem_ID, + SharedData &shared_data = DefaultData + ); + ~JointSubsystem(); + + void + InitializeJoint(int joint_index, Joint::JointType joint_type); + + Logical + TestInstance() const; +}; + + +#endif diff --git a/CODE/RP/MUNGA/LAMP.CPP b/CODE/RP/MUNGA/LAMP.CPP new file mode 100644 index 0000000..587ac45 --- /dev/null +++ b/CODE/RP/MUNGA/LAMP.CPP @@ -0,0 +1,380 @@ +//===========================================================================// +// File: gauge.cc // +// Project: MUNGA Brick: Gauges // +// Contents: Interface specification for Gauges // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/10/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(LAMP_HPP) +# include +#endif + +//######################################################################### +//############################# LampManager ############################### +//######################################################################### +LampManager::LampManager(): + lampList(NULL), + activeLampList(NULL), + inactiveLampList(NULL) +{ + previousModeMask = (ModeMask) 0; + Check_Fpu(); +} + +LampManager::~LampManager() +{ + Check(this); + RemoveAllLamps(); + Check_Fpu(); +} + +Logical + LampManager::TestInstance() const +{ + return True; +} + +void + LampManager::Update(ModeMask current_mode_mask) +{ + Check(this); + //--------------------------------------------------------------- + // If the modeMask has changed, update the active/inactive lists. + //--------------------------------------------------------------- + if (previousModeMask != current_mode_mask) + { + previousModeMask = current_mode_mask; + + ActivateLamps(current_mode_mask); + DeactivateLamps(current_mode_mask); + } + //----------------------------------------------------------------- + // Process all active lamps + //----------------------------------------------------------------- + ChainIteratorOf + i(activeLampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + lamp_pointer->Update(); + } + Check_Fpu(); +} + +void + LampManager::ActivateLamps(ModeMask current_mode_mask) +{ + Check(this); + //----------------------------------------------------------- + // Test the lamps in the 'inactive' list. If any of them + // have bits in their modeMask corresponding to the + // new mode mask, move them to the 'active' list. + //----------------------------------------------------------- + ChainIteratorOf + i(inactiveLampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.GetCurrent()) != NULL) + { + Check(lamp_pointer); + //----------------------------------- + // Became active? + //----------------------------------- + if (lamp_pointer->modeMask & current_mode_mask) + { + //----------------------------------- + // Yes, move to 'active' list + //----------------------------------- + i.Remove(); + activeLampList.Add(lamp_pointer); + //----------------------------------- + // Cause lamp to update itself + //----------------------------------- + lamp_pointer->Update(True); // force notification of state change + } + else + { + //----------------------------------- + // No, try the next one + //----------------------------------- + i.Next(); + } + } + Check_Fpu(); +} + +void + LampManager::DeactivateLamps(ModeMask current_mode_mask) +{ + Check(this); + //--------------------------------------------------------------- + // Test the lamps in the 'active' list. If any of them do NOT + // have bits in their modeMask corresponding to the new mode + // mask, move them to the 'inactive' list. + //--------------------------------------------------------------- + ChainIteratorOf + i(activeLampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.GetCurrent()) != NULL) + { + Check(lamp_pointer); + //----------------------------------- + // Became inactive? + //----------------------------------- + if (!(lamp_pointer->modeMask & current_mode_mask)) + { + //----------------------------------- + // Yes, move to 'inactive' list + //----------------------------------- + i.Remove(); + inactiveLampList.Add(lamp_pointer); + } + else + { + //----------------------------------- + // No, try the next one + //----------------------------------- + i.Next(); + } + } + Check_Fpu(); +} + +Lamp* + LampManager::FindLamp(LampID lamp_id, ModeMask mode_mask) +{ + Check(this); + + //--------------------------------------------------------------- + // Search for lamp with both proper ID and modeMask + //--------------------------------------------------------------- + ChainIteratorOf + i(lampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + + if (lamp_pointer->lampID == lamp_id) + { + if (lamp_pointer->modeMask == mode_mask) + { + Check_Fpu(); + return lamp_pointer; + } + } + } + Check_Fpu(); + return NULL; +} + +void + LampManager::AddLamp(Lamp *new_lamp) +{ + Check(this); + // + // Don't call Check(new_lamp) here! + // The Lamp creator calls AddLamp before the lamp is fully built! + // + Check_Pointer(new_lamp); + + lampList.Add(new_lamp); + + if (new_lamp->modeMask & previousModeMask) + { + activeLampList.Add(new_lamp); + } + else + { + inactiveLampList.Add(new_lamp); + } + + Check_Fpu(); +} + +void + LampManager::RemoveLamp(LampID lamp_id, ModeMask mode_mask) +{ + Check(this); + Lamp + *lamp_pointer = FindLamp(lamp_id, mode_mask); + if (lamp_id != NULL) + { + Unregister_Object(lamp_pointer); + delete lamp_pointer; + } + + Check_Fpu(); +} + +void + LampManager::RemoveAllLamps() +{ + Check(this); + //------------------------------------------- + // Delete all lamps + //------------------------------------------- + ChainIteratorOf + i(lampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + Unregister_Object(lamp_pointer); + delete lamp_pointer; + } + Check_Fpu(); +} + +//######################################################################### +//################################# Lamp ################################## +//######################################################################### +Lamp::Lamp( + LampID lamp_id, + ModeMask mode_mask, + LampManager *lamp_manager +): + Node(Gauge::GaugeClassID) +{ + Check(lamp_manager); + Verify(mode_mask != (ModeMask) 0); // if zero, it would NEVER execute + + lampID = lamp_id; + modeMask = mode_mask; + previousState = LampStateUndefined; + manager = lamp_manager; + alertActive = 0; + + manager->AddLamp(this); + Check_Fpu(); +} + +Lamp::~Lamp() +{ + Check(this); + Check_Fpu(); +} + +Logical + Lamp::TestInstance() const +{ + return True; +} + +void + Lamp::SetState(LampState new_state) +{ + Check(this); + + if (new_state != previousState) + { + previousState = new_state; + //--------------------------------------------- + // Update if mode is currently allowed + //--------------------------------------------- + Check(manager); + if (modeMask & manager->previousModeMask) + { + NotifyOfStateChange(); + } + } + Check_Fpu(); +} + +void + Lamp::SetAlertState(Logical alert_state) +{ + Check(this); + + if (alert_state) + { + ++alertActive; + } + else + { + --alertActive; + if (alertActive < 0) + { + alertActive = 0; + } + } + + //--------------------------------------------- + // Update if mode is currently allowed + //--------------------------------------------- + Check(manager); + if (modeMask & manager->GetPreviousModeMask()) + { + NotifyOfStateChange(); + } + Check_Fpu(); +} + +void + Lamp::Update(Logical /*force_notification*/) +{ + Fail("Lamp::Update method not overridden!"); +} + +void + Lamp::NotifyOfStateChange() +{ + Check(this); + Check_Fpu(); +} + +//######################################################################### +//############################## GraphicLamp ############################## +//######################################################################### +GraphicLamp::GraphicLamp( + LampID lamp_id, + ModeMask mode_mask, + LampManager *lamp_manager, + GaugeRenderer *the_renderer, + int graphics_port_number +): + Lamp(lamp_id, mode_mask, lamp_manager), + renderer(the_renderer), + localView( + the_renderer == NULL ? + NULL : + the_renderer->GetGraphicsPort(graphics_port_number) + ) +{ + Check_Fpu(); +} + +GraphicLamp::~GraphicLamp() +{ + Check(this); + Check_Fpu(); +} + +Logical + GraphicLamp::TestInstance() const +{ + Check(&localView); + Check_Fpu(); + return Lamp::TestInstance(); +} + + diff --git a/CODE/RP/MUNGA/LATTICE.CPP b/CODE/RP/MUNGA/LATTICE.CPP new file mode 100644 index 0000000..68a12a5 --- /dev/null +++ b/CODE/RP/MUNGA/LATTICE.CPP @@ -0,0 +1,718 @@ +//===========================================================================// +// File: lattice.cc // +// Project: MUNGA Brick: lattice Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/20/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(COLLORGN_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +//############################################################################# +//########################### LatticeZone ############################### +//############################################################################# + +LatticeZone::LatticeZone(const ExtentBox &extents): + boundingBox(extents, this) +{ +} + +LatticeZone::~LatticeZone() +{ +} + +//############################################################################# +//######################### EnvironmentZone ############################# +//############################################################################# + +EnvironmentZone::EnvironmentZone( + const ExtentBox &extents, + const Environment &the_environment +): + LatticeZone(extents) +{ + environment = the_environment; +} + +EnvironmentZone::~EnvironmentZone() +{ +} + +Logical + EnvironmentZone::TestInstance() const +{ + LatticeZone::TestInstance(); + Check(&environment); + return True; +} + +//############################################################################# +//########################### InterestZone ############################## +//############################################################################# + +InterestZone::InterestZone( + const ExtentBox &extents, + InterestZoneID interest_zone_id, + BoxedSolidTree *collision_root, + EnvironmentZone *environment_zone, + BoundingBoxTree *existance_root +): + LatticeZone(extents) +{ + Verify(interest_zone_id != NullInterestZoneID); + Check(collision_root); + Check(environment_zone); + Check(existance_root); + + interestZoneID = interest_zone_id; + collisionRoot = collision_root; + environmentZone = environment_zone; + collisionOrigin = NULL; + existanceRoot = existance_root; +} + +InterestZone::~InterestZone() +{ + // + // HACK - delete collision tree + // + Unregister_Object(collisionRoot); + delete collisionRoot; + collisionRoot = NULL; + + // + // HACK - delete environment zone + // + Unregister_Object(environmentZone); + delete environmentZone; + environmentZone = NULL; + + // + // HACK - delete existance tree + // + Unregister_Object(existanceRoot); + delete existanceRoot; + existanceRoot = NULL; + + // + // HACK - delete collision origin + // + if (collisionOrigin != NULL) + { + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->OrphanInterestOrigin(collisionOrigin); + CollisionOrigin *col_origin = collisionOrigin; + collisionOrigin = NULL; + Unregister_Object(col_origin); + delete col_origin; + } +} + +Logical + InterestZone::TestInstance() const +{ + LatticeZone::TestInstance(); + + Verify(interestZoneID != NullInterestZoneID); + + if (collisionOrigin != NULL) + { + Check(collisionOrigin); + } + if (collisionRoot != NULL) + { + Check(collisionRoot); + } + if (environmentZone != NULL) + { + Check(environmentZone); + } + if (existanceRoot != NULL) + { + Check(existanceRoot); + } + + return True; +} + +//############################################################################# +//########################### InterestArena ############################# +//############################################################################# + +InterestArena::InterestArena(InterestZone *interest_zone): + interestZoneSocket(NULL) +{ + Check(interest_zone); + Check(&interestZoneSocket); + interestZoneSocket.Add(interest_zone); +} + +InterestArena::~InterestArena() +{ + // + // deconnect from interest zone + // + Check(&interestZoneSocket); + #if DEBUG_LEVEL>0 + InterestZone *interest_zone = interestZoneSocket.GetCurrent(); + Check(interest_zone); + #endif + interestZoneSocket.Remove(); + + #if 0 + // + // If the interest zone is not in any interest arenas then delete + // + PlugIterator iterator(interest_zone); + Check(&iterator); + if (iterator.GetSize() == 0) + { + Unregister_Object(interest_zone); + delete interest_zone; + } + #endif +} + +Logical + InterestArena::TestInstance() const +{ + Node::TestInstance(); + Check(&interestZoneSocket); + return True; +} + +//############################################################################# +//########################### LatticeManager ############################ +//############################################################################# + +LatticeManager::LatticeManager() +{ +} + +LatticeManager::~LatticeManager() +{ +} + +//############################################################################# +//####################### InterestLatticeManager ######################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +InterestLatticeManager::InterestLatticeManager(): + interestZoneSocket(NULL) +{ +} + +// +//############################################################################# +//############################################################################# +// +InterestLatticeManager::~InterestLatticeManager() +{ + InterestZone *interest_zone; + + Check(&interestZoneSocket); + if ((interest_zone = interestZoneSocket.GetCurrent()) != NULL) + { + Unregister_Object(interest_zone); + delete interest_zone; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + InterestLatticeManager::TestInstance() const +{ + Node::TestInstance(); + Check(&interestZoneSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +InterestArena* + InterestLatticeManager::MakeInterestArena( + InterestZoneID, + InterestType, + InterestDepth + ) +{ + Check(this); + + // + //--------------------------------------------------------------------- + // HACK - See if the one interest zone has been created + //--------------------------------------------------------------------- + // + InterestZone *interest_zone; + + if ((interest_zone = interestZoneSocket.GetCurrent()) == NULL) + { + // + //--------------------------------------------------------------------- + // Create the one environment + //--------------------------------------------------------------------- + // + EnvironmentZone *environment_zone; + + // + // Make the memory stream + // + Check(application); + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + + ResourceDescription *resource_description = + res_file->FindResourceDescription( + "EnvironmentZone", + ResourceDescription::EnvironmentZoneResourceType + ); + if (resource_description) + { + Check(resource_description); + resource_description->Lock(); + + MemoryStream + memory_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + + // + // Get the construction arguments + // + ExtentBox extent_box; + Environment environment; + + memory_stream >> extent_box >> environment; + + resource_description->Unlock(); + + // + // Make the environment zone + // + environment_zone = new EnvironmentZone(extent_box, environment); + Register_Object(environment_zone); + } + + // + //--------------------------------------------------------------------- + // Create the one interest zone + //--------------------------------------------------------------------- + // + resource_description = + res_file->FindResourceDescription( + "InterestZone", + ResourceDescription::InterestZoneResourceType + ); + if (resource_description) + { + Check(resource_description); + resource_description->Lock(); + + MemoryStream + memory_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + + // + // Get the construction arguments + // + ExtentBox extent_box; + InterestZoneID interest_zone_ID; + CString map_resource_name; + + memory_stream >> extent_box >> interest_zone_ID >> map_resource_name; + + resource_description->Unlock(); + + // + // Make the collision tree root + // + BoxedSolidTree *collision_root = new BoxedSolidTree; + Register_Object(collision_root); + + // + // Make the existance tree root + // + BoundingBoxTree *existance_root = new BoundingBoxTree; + Register_Object(existance_root); + + // + // Make the interest zone + // + interest_zone = + new InterestZone( + extent_box, + interest_zone_ID, + collision_root, + environment_zone, + existance_root + ); + Register_Object(interest_zone); + } + + interestZoneSocket.Add(interest_zone); + Verify(interest_zone == interestZoneSocket.GetCurrent()); + } + Check(interest_zone); + + // + //--------------------------------------------------------------------- + // Create an interest arena pointing at this zone + //--------------------------------------------------------------------- + // + return new InterestArena(interest_zone); +} +#if 0 +InterestArena* + InterestLatticeManager::MakeInterestArena( + InterestZoneID, + InterestType, + InterestDepth + ) +{ + Check(this); + + // + //--------------------------------------------------------------------- + // HACK - Create one interest zone + //--------------------------------------------------------------------- + // + InterestZone *interest_zone; + + if ((interest_zone = interestZoneSocket.GetCurrent()) == NULL) + { + const Scalar min_dimension = -100000.0f; + const Scalar max_dimension = 100000.0f; + + Vector3D min_vector(min_dimension, min_dimension, min_dimension); + Vector3D max_vector(max_dimension, max_dimension, max_dimension); + ExtentBox big_extent(min_vector, max_vector); + + // + // Pick one interest zone id + // + InterestZoneID interest_zone_ID = NullInterestZoneID + 1; + + // + // Set up one environment + // + Environment environment; + EnvironmentZone *environment_zone; + + environment.gravityConstant = 6.5f; + environment.airDensity = 1.0f; + environment.windVelocity = Vector3D::Identity; + environment.ambientTemperature = 294.26f; // Seventy degrees farenheit + + environment_zone = new EnvironmentZone(big_extent, environment); + Register_Object(environment_zone); + + // + // Load entire collision tree + // + BoxedSolidTree *collision_root = new BoxedSolidTree; + Register_Object(collision_root); + + // + // Make one interest zone for everything + // + interest_zone = + new InterestZone( + big_extent, + interest_zone_ID, + collision_root, + environment_zone + ); + Register_Object(interest_zone); + + interestZoneSocket.Add(interest_zone); + Verify(interest_zone == interestZoneSocket.GetCurrent()); + } + Check(interest_zone); + + // + //--------------------------------------------------------------------- + // Create an interest arena pointing at this zone + //--------------------------------------------------------------------- + // + return new InterestArena(interest_zone); +} +#endif + +#if 0 +// +//############################################################################# +//############################################################################# +// +void + InterestLatticeManager::DestroyInterestArena(InterestArena *interest_arena) +{ + Check(this); + Check(interest_arena); + + // + //--------------------------------------------------------------------- + // Delete the interest arena + //--------------------------------------------------------------------- + // + Unregister_Object(interest_arena); + delete interest_arena; +} +#endif + +// +//############################################################################# +//############################################################################# +// +InterestZoneID + InterestLatticeManager::SearchForEntityInterestZone( + InterestZoneID, + const EntityID& + ) +{ + Check(this); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetInterestZoneID(); +} + +// +//############################################################################# +//############################################################################# +// +InterestZone* + InterestLatticeManager::GetInterestZone(InterestZoneID) +{ + Check(this); + return interestZoneSocket.GetCurrent(); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestLatticeManager::CreateZoneResources( + ResourceFile *resource_file, + NotationFile *zone_notation_file + ) +{ + Check(zone_notation_file); + + // + //--------------------------------------------------------------------- + // HACK - Create the one environment zone resource + //--------------------------------------------------------------------- + // + { + // + // Environment zone construction arguments + // + ExtentBox extent_box; + Environment environment; + + // + // Get environment zone construction arguments + // + const char *contents; + + #if DEBUG_LEVEL>0 + int ret = zone_notation_file->GetEntry( + "EnvironmentZone", + "extent_box", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "EnvironmentZone", + "extent_box", + &contents + ); + #endif + Convert_From_Ascii(contents, &extent_box); + + #if DEBUG_LEVEL>0 + ret = zone_notation_file->GetEntry( + "EnvironmentZone", + "environment", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "EnvironmentZone", + "environment", + &contents + ); + #endif + Convert_From_Ascii(contents, &environment); + + // + // Create environment zone memory stream + // + DynamicMemoryStream environment_zone_memory_stream; + + environment_zone_memory_stream << extent_box << environment; + + // + // Add environment zone resource + // + CString environment_zone_resource_name("EnvironmentZone"); + + #if DEBUG_LEVEL>0 + ResourceDescription *res_description = + resource_file->AddResourceMemoryStream( + environment_zone_resource_name, + ResourceDescription::EnvironmentZoneResourceType, + 1, + ResourceDescription::Preload, + &environment_zone_memory_stream + ); + Check(res_description); + #else + resource_file->AddResourceMemoryStream( + environment_zone_resource_name, + ResourceDescription::EnvironmentZoneResourceType, + 1, + ResourceDescription::Preload, + &environment_zone_memory_stream + ); + #endif + } + + // + //--------------------------------------------------------------------- + // HACK - Create the one interest zone resource + //--------------------------------------------------------------------- + // + { + // + // Interest zone construction arguments + // + ExtentBox extent_box; + InterestZoneID interest_zone_ID; + CString map_resource_name; + + // + // Get interest zone construction arguments + // + const char *contents; + + #if DEBUG_LEVEL>0 + int ret = zone_notation_file->GetEntry( + "InterestZone", + "extent_box", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "InterestZone", + "extent_box", + &contents + ); + #endif + Convert_From_Ascii(contents, &extent_box); + + #if DEBUG_LEVEL>0 + ret = zone_notation_file->GetEntry( + "InterestZone", + "interest_zone_ID", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "InterestZone", + "interest_zone_ID", + &contents + ); + #endif + Convert_From_Ascii(contents, &interest_zone_ID); + + #if DEBUG_LEVEL>0 + ret = zone_notation_file->GetEntry( + "InterestZone", + "map_resource_name", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "InterestZone", + "map_resource_name", + &contents + ); + #endif + map_resource_name = contents; + + // + // Create interest zone memory stream + // + DynamicMemoryStream interest_zone_memory_stream; + + interest_zone_memory_stream << extent_box << interest_zone_ID; + interest_zone_memory_stream << map_resource_name; + + // + // Add interest zone resource + // + CString interest_zone_resource_name("InterestZone"); + + #if DEBUG_LEVEL>0 + ResourceDescription *res_description = + resource_file->AddResourceMemoryStream( + interest_zone_resource_name, + ResourceDescription::InterestZoneResourceType, + 1, + ResourceDescription::Preload, + &interest_zone_memory_stream + ); + Check(res_description); + #else + resource_file->AddResourceMemoryStream( + interest_zone_resource_name, + ResourceDescription::InterestZoneResourceType, + 1, + ResourceDescription::Preload, + &interest_zone_memory_stream + ); + #endif + } +} + diff --git a/CODE/RP/MUNGA/LATTICE.HPP b/CODE/RP/MUNGA/LATTICE.HPP new file mode 100644 index 0000000..64ebd70 --- /dev/null +++ b/CODE/RP/MUNGA/LATTICE.HPP @@ -0,0 +1,512 @@ +//===========================================================================// +// File: lattice.hpp // +// Project: MUNGA Brick: Lattice Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/20/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LATTICE_HPP) +# define LATTICE_HPP + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(BNDGBOX_HPP) +# include +# endif + +# if !defined(ENVIRNMT_HPP) +# include +# endif + +# if !defined(NETWORK_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + + class BoundingBoxTree; + + //########################################################################## + //######## Support types for InterestOrigin & InterestManager ######## + //########################################################################## + + enum InterestType + { + VisualInterestType, + AudioInterestType, + GaugeInterestType, + CollisionInterestType + }; + + typedef int InterestDepth; + + const InterestDepth DefaultInterestDepth = 1; + + enum InterestPriority + { + LowInterestPriority = 0, + HighInterestPriority + }; + + //########################################################################## + //########################### LatticeZone ############################ + //########################################################################## + + class ExtentBox; + + // + // HACK - Lattice zones support being connected to each in variously + // interesting ways. For now there is only one. + // + + class LatticeZone: + public Plug + { + public: + LatticeZone(const ExtentBox &extents); + ~LatticeZone(); + + private: + TaggedBoundingBoxOf + boundingBox; + }; + + //########################################################################## + //######################### EnvironmentZone ########################## + //########################################################################## + + class EnvironmentZone: + public LatticeZone + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + EnvironmentZone( + const ExtentBox &extents, + const Environment &environment + ); + ~EnvironmentZone(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // HACK - Accessors + // + public: + Environment* + GetEnvironment() + {return &environment;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + Environment + environment; + }; + + //########################################################################## + //########################### InterestZone ########################### + //########################################################################## + + class BoxedSolidTree; + class CollisionOrigin; + + // + // HACK - Right now the interest zone holds data that would normally + // be within its own zone, i.e., environment zones, collision zones, + // audio zones, etc..., The interest zone should hold sockets to + // zones which are included in its interesting "domain" + // + + class InterestZone: + public LatticeZone + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + InterestZone( + const ExtentBox &extents, + InterestZoneID interest_zone_id, + BoxedSolidTree *collision_root, + EnvironmentZone *environment_zone, + BoundingBoxTree *existance_root + ); + ~InterestZone(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // HACK - Accessors + // + public: + InterestZoneID + GetInterestZoneID(); + BoxedSolidTree* + GetCollisionRoot(); + Environment* + GetEnvironment(); + BoundingBoxTree* + GetExistanceRoot(); + + void + AdoptCollisionOrigin(CollisionOrigin *collision_origin); + CollisionOrigin* + GetCollisionOrigin(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + InterestZoneID + interestZoneID; + BoxedSolidTree + *collisionRoot; + EnvironmentZone + *environmentZone; + CollisionOrigin + *collisionOrigin; + BoundingBoxTree + *existanceRoot; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ InterestZone inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline InterestZoneID + InterestZone::GetInterestZoneID() + { + Check(this); + return interestZoneID; + } + + inline BoxedSolidTree* + InterestZone::GetCollisionRoot() + { + Check(this); + return collisionRoot; + } + + inline Environment* + InterestZone::GetEnvironment() + { + Check(this); + Check(environmentZone); + return environmentZone->GetEnvironment(); + } + + inline BoundingBoxTree* + InterestZone::GetExistanceRoot() + { + Check(this); + return existanceRoot; + } + + inline void + InterestZone::AdoptCollisionOrigin(CollisionOrigin *collision_origin) + { + Check(this); + Verify(collisionOrigin == NULL); + Check_Pointer(collision_origin); + collisionOrigin = collision_origin; + } + + inline CollisionOrigin* + InterestZone::GetCollisionOrigin() + { + Check(this); + return collisionOrigin; + } + + //########################################################################## + //########################### InterestArena ########################## + //########################################################################## + + // + // HACK - The interest arena maintains sets of interest zones. Since + // we only have one interest zone at present the interest arena has + // only the capability to reference one interest zone + // + + class InterestArena: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + InterestArena(InterestZone *interest_zone); + ~InterestArena(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // HACK - Accessors + // + public: + InterestZoneID + GetInterestZoneID(); + BoxedSolidTree* + GetCollisionRoot(); + Environment* + GetEnvironment(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Zone and Entity support + // + public: + // + //-------------------------------------------------------------- + // Boolean IncludesInterestZone(InterestArena, InterestZoneID) + // + // Description: + // Does the interest arena include the interest zone? + // + // Parameters: + // InterestArena - reference to the interest arena. + // InterestZoneID - id of the interest zone. + // + // Returns: + // True if it does, otherwise False + //-------------------------------------------------------------- + // + + // + //-------------------------------------------------------------- + // Boolean IncludesPosition(InterestArena, 3DPosition) + // + // Description: + // Does the interest arena include the spatial position? + // + // Parameters: + // InterestArena - reference to the interest arena. + // 3DPosition- the spatial position. + // + // Returns: + // True if it does, otherwise False + //-------------------------------------------------------------- + // + + // + //-------------------------------------------------------------- + // ArenaEntityList GetArenaList(InterestArena) + // + // Description: + // Returns a list of resident entities and associated attributes + // based on interest zone connectivity. The actual return will + // probably by a safe iterator, meaning that it is resilient to + // changes in the underlying data structures. + // + // Parameters: + // Reference to the interest arena. + // + // Return: + // ArenaEntityList - a list of resident entities and extracted + // data from interest zone connectivity. + //-------------------------------------------------------------- + // + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + SlotOf + interestZoneSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ InterestArena inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + + inline InterestZoneID + InterestArena::GetInterestZoneID() + { + Check(&interestZoneSocket); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetInterestZoneID(); + } + + inline BoxedSolidTree* + InterestArena::GetCollisionRoot() + { + Check(&interestZoneSocket); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetCollisionRoot(); + } + + inline Environment* + InterestArena::GetEnvironment() + { + Check(&interestZoneSocket); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetEnvironment(); + } + + //########################################################################## + //########################### LatticeManager ######################### + //########################################################################## + + // + // HACK - The lattice manager managers connected lattices of zones + // of a particular type + // + + class LatticeManager: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + LatticeManager(); + ~LatticeManager(); + }; + + //########################################################################## + //####################### InterestLatticeManager ##################### + //########################################################################## + + class EntityID; + class ResourceFile; + + // + // HACK - the interest lattice manager manages the lattice of interest + // zones. Right now, is stubbed out for one interest zone. + // + + class InterestLatticeManager: + public LatticeManager + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + InterestLatticeManager(); + ~InterestLatticeManager(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest arena and entity support + // + public: + // + //-------------------------------------------------------------- + // InterestArena + // MakeInterestArena(OriginInterestZoneID, Type, DepthCalibration) + // + // Description: + // Establishes an interest arena the locus of which is an interest + // zone, The arena is established with a type and depth + // specification (see interest manager). + // + // Parameters: + // OriginInterestZoneID- id of the interest zone. + // Type - a type of interest. + // DepthCalibration - a specification of the "depth" or "cost" associated + // with extent of the arena. + // + // Return: + // InterestArena - a reference to the created interest arena. + //-------------------------------------------------------------- + // + InterestArena* + MakeInterestArena( + InterestZoneID, + InterestType, + InterestDepth + ); + + #if 0 + // + //-------------------------------------------------------------- + // DestroyInterestArena(InterestArena) + // + // Description: + // Destroys the interest arena. + // + // Parameters: + // InterestArena - Reference to the interest arena. + // UpdateInterestArena(InterestArena, DepthCalibration) + // + // Description: + // Updates the interest arenas internal data structures. This method + // is called by the interest manager. + // + // Parameters: + // InterestArena - Reference to the interest arena. + // DepthCalibration - new depth of arena extent. + //-------------------------------------------------------------- + // + void + DestroyInterestArena(InterestArena*); + #endif + + // + //-------------------------------------------------------------- + // InterestZoneID + // SearchForEntityInterestZone(OriginInterestZoneID, EntityID) + // + // Description: + // If an entity has changed interest zones (its current location + // is not within the bounding volume of it interest zone) then + // this method searches prior adjacent interest zones for the entity. + // + // Parameters: + // OriginInterestZoneID - id of the interest zone to begin the + // search from. + // EntityID - id of the entity. + // + // Return: + // A reference to the interest zone if found, otherwise NULL. + //-------------------------------------------------------------- + // + InterestZoneID + SearchForEntityInterestZone( + InterestZoneID old_interest_zone_ID, + const EntityID &entityID + ); + + // + //-------------------------------------------------------------- + // InterestZoneID + //-------------------------------------------------------------- + // + InterestZone* + GetInterestZone(InterestZoneID interest_zone_ID); + + // + //-------------------------------------------------------------- + // HACK ****************** + //-------------------------------------------------------------- + // + static void + CreateZoneResources( + ResourceFile *resource_file, + NotationFile *zone_notation_file + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + SlotOf + interestZoneSocket; + }; + +#endif + diff --git a/CODE/RP/MUNGA/LINE.CPP b/CODE/RP/MUNGA/LINE.CPP new file mode 100644 index 0000000..b2f9f3f --- /dev/null +++ b/CODE/RP/MUNGA/LINE.CPP @@ -0,0 +1,87 @@ +//=======================================================================// +// File: line.cpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#include +#pragma hdrstop + +#if !defined(LINE_HPP) +# include +#endif + +#if !defined(PLANE_HPP) +# include +#endif + +// +//########################################################################### +//########################################################################### +// +Line& + Line::operator=(const Vector3D &vector) +{ + Check_Pointer(this); + Check(&vector); +// +// Make sure length of vector is non-zero +// + length = vector.Length(); + Verify(length); +// +// Normalize the vector and put it into the line +// + direction.x = vector.x/length; + direction.y = vector.y/length; + direction.z = vector.z/length; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Line& + Line::operator=(const Point3D &point) +{ + Check_Pointer(this); + Check(&point); +// +// Copy the point over into the line. +// + origin.x = point.x; + origin.y = point.y; + origin.z = point.z; + return *this; +} + +Scalar + Line::DistanceTo( + const Plane &plane, + Scalar *product + ) const +{ + *product = direction * plane.normal; + if (Small_Enough(*product)) + { + Check_Fpu(); + return -1.0f; + } + Scalar result = -plane.DistanceTo(origin) / *product; + Check_Fpu(); + return result; +} + +Scalar + Line::DistanceTo( + const Sphere &,//sphere, + Scalar *//penetration + ) const +{ + return -1.0f; // HACK +} + diff --git a/CODE/RP/MUNGA/LINE.HPP b/CODE/RP/MUNGA/LINE.HPP new file mode 100644 index 0000000..87e65d3 --- /dev/null +++ b/CODE/RP/MUNGA/LINE.HPP @@ -0,0 +1,70 @@ +//=======================================================================// +// File: line.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainments, // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(LINE_HPP) +# define LINE_HPP + +# if !defined(RAY_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Line3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Line: + public Ray + { + public: + Scalar + length; + + Line() {} + Line( + const Ray &ray, + Scalar length + ): + Ray(ray), + length(length) + {} + Line( + const Point3D &start, + const UnitVector &direction, + Scalar length + ): + Ray(start,direction), + length(length) + {} + + void + FindEnd(Point3D *result) + {Check(this); Check_Pointer(result); Ray::Project(length, result);} + + // + // Assignment operators + // + Line& + operator=(const Vector3D &vector); + Line& + operator=(const Point3D &point); + // + // Ray intersection functions + // + Scalar + DistanceTo( + const Plane &plane, + Scalar *product + ) const; + Scalar + DistanceTo( + const Sphere &sphere, + Scalar *penetration + ) const; + + }; + +#endif diff --git a/CODE/RP/MUNGA/LINK.CPP b/CODE/RP/MUNGA/LINK.CPP new file mode 100644 index 0000000..a9ef7e9 --- /dev/null +++ b/CODE/RP/MUNGA/LINK.CPP @@ -0,0 +1,128 @@ +//===========================================================================// +// File: link.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of base Link // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/28/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(LINK_HPP) + #include +#endif + +#if !defined(PLUG_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Link ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Link +//############################################################################# +// +Link::Link( + Socket *socket, + Plug *plug +) +{ + this->socket = socket; + this->plug = plug; + + // + //---------------------------------------------------- + // Add this new link to the plugs current set of links + //---------------------------------------------------- + // + AddToPlug(plug); +} + +// +//############################################################################# +// ~Link +//############################################################################# +// +Link::~Link() +{ + // + //----------------------------------------------------- + // Remove this link from the plugs current set of links + //----------------------------------------------------- + // + ReleaseFromPlug(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Link::TestInstance() const +{ + Check_Signature(socket); + Check_Signature(plug); + return True; +} + +// +//############################################################################# +// ReleaseFromPlug +//############################################################################# +// +void + Link::ReleaseFromPlug() +{ + // + //----------------------------------------------------- + // Remove this link from the plugs current set of links + //----------------------------------------------------- + // + Check(plug); + if (plug->linkHead == this) + { + plug->linkHead = nextLink; + } + if (prevLink != NULL) + { + Check(prevLink); + prevLink->nextLink = nextLink; + } + if (nextLink != NULL) + { + Check(nextLink); + nextLink->prevLink = prevLink; + } + prevLink = nextLink = NULL; +} + +// +//############################################################################# +// AddToPlug +//############################################################################# +// +void + Link::AddToPlug(Plug *plug) +{ + Check(plug); + if ((nextLink = plug->linkHead) != NULL) + { + Check(nextLink); + nextLink->prevLink = this; + } + this->prevLink = NULL; + plug->linkHead = this; +} diff --git a/CODE/RP/MUNGA/LINK.HPP b/CODE/RP/MUNGA/LINK.HPP new file mode 100644 index 0000000..dfd1066 --- /dev/null +++ b/CODE/RP/MUNGA/LINK.HPP @@ -0,0 +1,99 @@ +//===========================================================================// +// File: link.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification of base Link // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LINK_HPP) +# define LINK_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + class Socket; + class Plug; + class PlugIterator; + class Node; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Link ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Link SIGNATURED + { + friend class PlugIterator; + + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + virtual + ~Link(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Socket* + GetSocket() + {return socket;} + Plug* + GetPlug() + {return plug;} + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Link( + Socket *socket, + Plug *plug + ); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + ReleaseFromPlug(); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Socket *socket; + Plug *plug; + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + AddToPlug(Plug *plug); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Link *nextLink; + Link *prevLink; + }; + +#endif diff --git a/CODE/RP/MUNGA/LINMTRX.CPP b/CODE/RP/MUNGA/LINMTRX.CPP new file mode 100644 index 0000000..574e171 --- /dev/null +++ b/CODE/RP/MUNGA/LINMTRX.CPP @@ -0,0 +1,165 @@ +//===========================================================================// +// File: linmtrx.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the linear matrices // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(LINMTRX_HPP) +# include +#endif + +#if !defined(MATRIX_HPP) +# include +#endif + +#if !defined(LINMTRX_HPP) + #include +#endif + +const LinearMatrix + LinearMatrix::Identity(True); + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::operator=(const AffineMatrix &m) +{ + // + // Make sure to test linearness on m + // + AffineMatrix::operator=(m); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::operator=(const Matrix4x4 &m) +{ + // + // Make sure to test linearness on m + // + AffineMatrix::operator=(m); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::operator=(const TransposedMatrix &m) +{ + // + // Make sure to test linearness on m + // + AffineMatrix::operator=(m); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::Invert(const LinearMatrix& Source) +{ + + // + //----------------------------------------- + // First, transpose the 3x3 rotation matrix + //----------------------------------------- + // + (*this)(0,0) = Source(0,0); + (*this)(0,1) = Source(1,0); + (*this)(0,2) = Source(2,0); + (*this)(1,0) = Source(0,1); + (*this)(1,1) = Source(1,1); + (*this)(1,2) = Source(2,1); + (*this)(2,0) = Source(0,2); + (*this)(2,1) = Source(1,2); + (*this)(2,2) = Source(2,2); + + // + //---------------------------- + // Now run the offsets through + //---------------------------- + // + (*this)(3,0) = + -Source(3,0)*Source(0,0) + -Source(3,1)*Source(0,1) + -Source(3,2)*Source(0,2); + (*this)(3,1) = + -Source(3,0)*Source(1,0) + -Source(3,1)*Source(1,1) + -Source(3,2)*Source(1,2); + (*this)(3,2) = + -Source(3,0)*Source(2,0) + -Source(3,1)*Source(2,1) + -Source(3,2)*Source(2,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::Normalize() +{ + (*this)(0,2) = (*this)(1,0)*(*this)(2,1) - (*this)(1,1)*(*this)(2,0); + (*this)(1,2) = (*this)(2,0)*(*this)(0,1) - (*this)(2,1)*(*this)(0,0); + (*this)(2,2) = (*this)(0,0)*(*this)(1,1) - (*this)(0,1)*(*this)(1,0); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + LinearMatrix::TestInstance() const +{ + UnitVector v1; + GetFromAxis(X_Axis,&v1); + if (!v1.TestInstance()) + { + Dump(*this); + Dump(v1); + return False; + } + + UnitVector v2; + GetFromAxis(Y_Axis,&v2); + if (!v2.TestInstance()) + { + Dump(*this); + Dump(v1); + return False; + } + + UnitVector v3; + v3.Vector3D::Cross(v1,v2); + GetFromAxis(Z_Axis,&v1); + return Close_Enough(v1,v3); +} + +#if defined(TEST_CLASS) +# include "linmtrx.tcp" +#endif + diff --git a/CODE/RP/MUNGA/LINMTRX.HPP b/CODE/RP/MUNGA/LINMTRX.HPP new file mode 100644 index 0000000..f007910 --- /dev/null +++ b/CODE/RP/MUNGA/LINMTRX.HPP @@ -0,0 +1,181 @@ +//===========================================================================// +// File: linmtrx.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for the linear matrices // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/94 JMA Initial coding. // +// 12/01/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LINMTRX_HPP) +# define LINMTRX_HPP + +# if !defined(AFFNMTRX_HPP) +# include +# endif + +# if !defined(UNITVEC_HPP) +# include +# endif + +# if !defined(ROTATION_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ LinearMatrix ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class LinearMatrix: + public AffineMatrix + { + public: + static const LinearMatrix + Identity; + + // + // Constructors + // + LinearMatrix() + {BuildIdentity(); }// JM 11-25-95 + LinearMatrix(int) + {BuildIdentity();} + + // + // Assignment Operators + // + LinearMatrix& + operator=(const LinearMatrix &m) + {AffineMatrix::operator=(m); return *this;} + LinearMatrix& + operator=(const Origin &p) + {AffineMatrix::operator=(p); return *this;} + LinearMatrix& + operator=(const Hinge &hinge) + {AffineMatrix::operator=(hinge); return *this;} + LinearMatrix& + operator=(const EulerAngles &angles) + {AffineMatrix::operator=(angles); return *this;} + LinearMatrix& + operator=(const YawPitchRoll &angles) + {AffineMatrix::operator=(angles); return *this;} + LinearMatrix& + operator=(const Quaternion &q) + {AffineMatrix::operator=(q); return *this;} + LinearMatrix& + operator=(const Point3D &p) + {AffineMatrix::operator=(p); return *this;} + LinearMatrix& + operator=(const AffineMatrix &m); + LinearMatrix& + operator=(const Matrix4x4 &m); + LinearMatrix& + operator=(const TransposedMatrix &m); + + // + // Axis Manipulation + // + void + GetFromAxis(size_t index, UnitVector *v) const + {AffineMatrix::GetFromAxis(index,v);} + void + GetToAxis(size_t index, UnitVector *v) const + {AffineMatrix::GetToAxis(index,v);} + + LinearMatrix& + SetFromAxis(size_t index, const UnitVector &v) + {AffineMatrix::SetFromAxis(index,v); return *this;} + LinearMatrix& + SetToAxis(size_t index, const UnitVector &v) + {AffineMatrix::SetToAxis(index,v); return *this;} + + // + // Matrix4x4 Multiplication + // + LinearMatrix& + Multiply( + const LinearMatrix& m1, + const LinearMatrix& m2 + ) + {AffineMatrix::Multiply(m1, m2); return *this;} + LinearMatrix& + operator *=(const LinearMatrix& M) + {LinearMatrix src(*this); return Multiply(src, M);} + + // + // Matrix4x4 Inversion + // + LinearMatrix& + Invert(const LinearMatrix& Source); + LinearMatrix& + Invert() + {LinearMatrix src(*this); return Invert(src);} + + // + // Rotation and Translation + // + LinearMatrix& + Multiply(const LinearMatrix &m,const Quaternion &q) + { + Check_Pointer(this); Check(&m); Check(&q); + AffineMatrix::Multiply(m,q); return *this; + } + LinearMatrix& + operator*=(const Quaternion &q) + {Check(this); LinearMatrix m(*this); return Multiply(m,q);} + LinearMatrix& + Multiply(const LinearMatrix &m,const Point3D &p) + { + Check_Pointer(this); Check(&m); Check(&p); + AffineMatrix::Multiply(m,p); return *this; + } + LinearMatrix& + operator*=(const Point3D& p) + {Check(this); LinearMatrix m(*this); return Multiply(m,p);} + + // + // Support functions + // + LinearMatrix& + Normalize(); + + Logical + TestInstance() const; + static Logical + TestClass(); + + private: + LinearMatrix& Solve(); + }; + + inline UnitVector& + UnitVector::Multiply( + const UnitVector &v, + const LinearMatrix &m + ) + {Check(&v); Vector3D::Multiply(v,m); return *this;} + + inline UnitVector& + UnitVector::operator*=(const LinearMatrix &m) + {UnitVector src(*this); return Multiply(src,m);} + + inline Quaternion& + Quaternion::Multiply( + const Quaternion &q, + const LinearMatrix &m + ) + { + Cast_Object(Vector3D*,this)->Multiply(SKIPPY_CAST(Vector3D,q),m); + return *this; + } + + inline Quaternion& + Quaternion::operator*=(const LinearMatrix &m) + {Quaternion t(*this); return Multiply(t,m);} + + +#endif diff --git a/CODE/RP/MUNGA/LINMTRX.TCP b/CODE/RP/MUNGA/LINMTRX.TCP new file mode 100644 index 0000000..7fef7b3 --- /dev/null +++ b/CODE/RP/MUNGA/LINMTRX.TCP @@ -0,0 +1,23 @@ +//===========================================================================// +// File: linmtrx.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the linear matrices // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#include "random.hpp" +// +//########################################################################### +//########################################################################### +// +Logical LinearMatrix::TestClass() +{ + return False; +} + diff --git a/CODE/RP/MUNGA/MATRIX.CPP b/CODE/RP/MUNGA/MATRIX.CPP new file mode 100644 index 0000000..cadde3c --- /dev/null +++ b/CODE/RP/MUNGA/MATRIX.CPP @@ -0,0 +1,689 @@ +//===========================================================================// +// File: matrix.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the matrix class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(MATRIX_HPP) +# include +#endif + +#if !defined(AFFNMTRX_HPP) +# include +#endif + +#if !defined(ORIGIN_HPP) +# include +#endif + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile AbstractMatrix4x4 *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +AbstractMatrix4x4& + AbstractMatrix4x4::operator=(const AbstractMatrix4x4 &m) +{ + #if sizeof(entries) > sizeof(m.entries) + # error memcpy size mismatch! + #endif + + memcpy(entries, m.entries, sizeof(m.entries)); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AbstractMatrix4x4& + AbstractMatrix4x4::Transpose(const AbstractMatrix4x4 &m) +{ + entries[0] = m.entries[0]; + entries[1] = m.entries[4]; + entries[2] = m.entries[8]; + entries[3] = m.entries[12]; + + entries[4] = m.entries[1]; + entries[5] = m.entries[5]; + entries[6] = m.entries[9]; + entries[7] = m.entries[13]; + + entries[8] = m.entries[2]; + entries[9] = m.entries[6]; + entries[10] = m.entries[10]; + entries[11] = m.entries[14]; + + entries[12] = m.entries[3]; + entries[13] = m.entries[7]; + entries[14] = m.entries[11]; + entries[15] = m.entries[15]; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + AbstractMatrix4x4::TestInstance() const +{ + return True; +} + +const Matrix4x4 + Matrix4x4::Identity(True); + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::BuildIdentity() +{ + (*this)(0,0) = 1.0f; + (*this)(1,0) = 0.0f; + (*this)(2,0) = 0.0f; + (*this)(3,0) = 0.0f; + + (*this)(0,1) = 0.0f; + (*this)(1,1) = 1.0f; + (*this)(2,1) = 0.0f; + (*this)(3,1) = 0.0f; + + (*this)(0,2) = 0.0f; + (*this)(1,2) = 0.0f; + (*this)(2,2) = 1.0f; + (*this)(3,2) = 0.0f; + + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const AffineMatrix &m) +{ + (*this)(0,0) = m(0,0); + (*this)(0,1) = m(0,1); + (*this)(0,2) = m(0,2); + (*this)(0,3) = 0.0f; + + (*this)(1,0) = m(1,0); + (*this)(1,1) = m(1,1); + (*this)(1,2) = m(1,2); + (*this)(1,3) = 0.0f; + + (*this)(2,0) = m(2,0); + (*this)(2,1) = m(2,1); + (*this)(2,2) = m(2,2); + (*this)(2,3) = 0.0f; + + (*this)(3,0) = m(3,0); + (*this)(3,1) = m(3,1); + (*this)(3,2) = m(3,2); + (*this)(3,3) = 1.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const Origin& p) +{ + Check_Pointer(this); + Check(&p); + + BuildRotation(p.angularPosition); + BuildTranslation(p.linearPosition); + + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Matrix4x4& + Matrix4x4::operator=(const EulerAngles &angles) +{ + Check_Pointer(this); + Check(&angles); + + SinCosPair + x, + y, + z; + + x = angles.pitch; + y = angles.yaw; + z = angles.roll; + + (*this)(0,0) = y.cosine*z.cosine; + (*this)(0,1) = y.cosine*z.sine; + (*this)(0,2) = -y.sine; + (*this)(0,3) = 0.0f; + + (*this)(1,0) = x.sine*y.sine*z.cosine - x.cosine*z.sine; + (*this)(1,1) = x.sine*y.sine*z.sine + x.cosine*z.cosine; + (*this)(1,2) = x.sine*y.cosine; + (*this)(1,3) = 0.0f; + + (*this)(2,0) = x.cosine*y.sine*z.cosine + x.sine*z.sine; + (*this)(2,1) = x.cosine*y.sine*z.sine - x.sine*z.cosine; + (*this)(2,2) = x.cosine*y.cosine; + (*this)(2,3) = 0.0f; + + (*this)(3,0) = 0.0f; + (*this)(3,1) = 0.0f; + (*this)(3,2) = 0.0f; + (*this)(3,3) = 1.0f; + + Check(this); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::BuildRotation(const Quaternion &q) +{ + Check_Pointer(this); + Check(&q); + + Scalar + a = q.x*q.y, + b = q.y*q.z, + c = q.z*q.x, + d = q.w*q.x, + e = q.w*q.y, + f = q.w*q.z, + g = q.w*q.w, + h = q.x*q.x, + i = q.y*q.y, + j = q.z*q.z; + + (*this)(0,0) = g + h - i - j; + (*this)(1,0) = 2.0f*(a - f); + (*this)(2,0) = 2.0f*(c + e); + + (*this)(0,1) = 2.0f*(f + a); + (*this)(1,1) = g - h + i - j; + (*this)(2,1) = 2.0f*(b - d); + + (*this)(0,2) = 2.0f*(c - e); + (*this)(1,2) = 2.0f*(b + d); + (*this)(2,2) = g - h - i + j; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const Quaternion &q) +{ + Check_Pointer(this); + Check(&q); + + BuildRotation(q); + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,0) = 0.0f; + (*this)(3,1) = 0.0f; + (*this)(3,2) = 0.0f; + (*this)(3,3) = 1.0f; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::BuildTranslation(const Point3D& p) +{ + Check_Pointer(this); + Check(&p); + + (*this)(3,0) = p.x; + (*this)(3,1) = p.y; + (*this)(3,2) = p.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const Point3D& p) +{ + Check_Pointer(this); + Check(&p); + + BuildTranslation(p); + + (*this)(0,0) = 1.0f; + (*this)(0,1) = 0.0f; + (*this)(0,2) = 0.0f; + (*this)(0,3) = 0.0f; + (*this)(1,0) = 0.0f; + (*this)(1,1) = 1.0f; + (*this)(1,2) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,0) = 0.0f; + (*this)(2,1) = 0.0f; + (*this)(2,2) = 1.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const Matrix4x4 &Source1, + const Matrix4x4 &Source2 + ) +{ + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0) + + Source1(0,3)*Source2(3,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0) + + Source1(1,3)*Source2(3,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0) + + Source1(2,3)*Source2(3,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source1(3,3)*Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1) + + Source1(0,3)*Source2(3,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1) + + Source1(1,3)*Source2(3,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1) + + Source1(2,3)*Source2(3,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source1(3,3)*Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2) + + Source1(0,3)*Source2(3,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2) + + Source1(1,3)*Source2(3,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2) + + Source1(2,3)*Source2(3,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source1(3,3)*Source2(3,2); + + (*this)(0,3) = + Source1(0,0)*Source2(0,3) + + Source1(0,1)*Source2(1,3) + + Source1(0,2)*Source2(2,3) + + Source1(0,3)*Source2(3,3); + (*this)(1,3) = + Source1(1,0)*Source2(0,3) + + Source1(1,1)*Source2(1,3) + + Source1(1,2)*Source2(2,3) + + Source1(1,3)*Source2(3,3); + (*this)(2,3) = + Source1(2,0)*Source2(0,3) + + Source1(2,1)*Source2(1,3) + + Source1(2,2)*Source2(2,3) + + Source1(2,3)*Source2(3,3); + (*this)(3,3) = + Source1(3,0)*Source2(0,3) + + Source1(3,1)*Source2(1,3) + + Source1(3,2)*Source2(2,3) + + Source1(3,3)*Source2(3,3); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const Matrix4x4 &Source1, + const AffineMatrix &Source2 + ) +{ + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0) + + Source1(0,3)*Source2(3,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0) + + Source1(1,3)*Source2(3,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0) + + Source1(2,3)*Source2(3,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source1(3,3)*Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1) + + Source1(0,3)*Source2(3,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1) + + Source1(1,3)*Source2(3,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1) + + Source1(2,3)*Source2(3,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source1(3,3)*Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2) + + Source1(0,3)*Source2(3,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2) + + Source1(1,3)*Source2(3,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2) + + Source1(2,3)*Source2(3,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source1(3,3)*Source2(3,2); + + (*this)(0,3) = Source1(0,3); + (*this)(1,3) = Source1(1,3); + (*this)(2,3) = Source1(2,3); + (*this)(3,3) = Source1(3,3); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const AffineMatrix &Source1, + const Matrix4x4 &Source2 + ) +{ + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source2(3,2); + + (*this)(0,3) = + Source1(0,0)*Source2(0,3) + + Source1(0,1)*Source2(1,3) + + Source1(0,2)*Source2(2,3); + (*this)(1,3) = + Source1(1,0)*Source2(0,3) + + Source1(1,1)*Source2(1,3) + + Source1(1,2)*Source2(2,3); + (*this)(2,3) = + Source1(2,0)*Source2(0,3) + + Source1(2,1)*Source2(1,3) + + Source1(2,2)*Source2(2,3); + (*this)(3,3) = + Source1(3,0)*Source2(0,3) + + Source1(3,1)*Source2(1,3) + + Source1(3,2)*Source2(2,3) + + Source2(3,3); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const AffineMatrix &m1, + const AffineMatrix &m2 + ) +{ + Cast_Object(AffineMatrix*,this)->Multiply(m1,m2); + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::SetToProjection( + Scalar Z_Plane, + Scalar Inv_Q, + Scalar Dx, + Scalar Dy, + Scalar Inv_Dz + ) +{ + Scalar + temp; + + // + // This may need to be transposed!!!! + // + (*this)(0,0) = 1.0; + (*this)(0,1) = 0.0; + (*this)(0,2) = 0.0; + (*this)(0,3) = 0.0; + + (*this)(1,0) = 0.0; + (*this)(1,1) = 1.0; + (*this)(1,2) = 0.0; + (*this)(1,3) = 0.0; + + temp = Dx * Inv_Dz; + (*this)(3,0) = temp * Z_Plane; + (*this)(2,0) = -temp; + temp = Dy * Inv_Dz; + (*this)(3,1) = temp * Z_Plane; + (*this)(2,1) = -temp; + + Inv_Dz *= -Inv_Q; + (*this)(2,2) = Z_Plane * Inv_Dz; + (*this)(2,3) = Z_Plane * (1.0 - (*this)(2,2)); + (*this)(3,2) = Inv_Dz; + (*this)(3,3) = 1.0 - (*this)(2,2); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator <<(ostream& Stream, const Matrix4x4 &A_Matrix) +{ + Stream << setprecision(4); + Stream << "\n\t| " << setw(9) << A_Matrix(0,0) << ", " << setw(9); + Stream << A_Matrix(0,1) << ", " << setw(9) << A_Matrix(0,2) << ", "; + Stream << setw(9) << A_Matrix(0,3) << " |\n\t| " << setw(9); + Stream << A_Matrix(1,0) << ", " << setw(9) << A_Matrix(1,1) << ", "; + Stream << setw(9) << A_Matrix(1,2) << ", " << setw(9) << A_Matrix(1,3); + Stream << " |\n\t| " << setw(9) << A_Matrix(2,0) << ", " << setw(9); + Stream << A_Matrix(2,1) << ", " << setw(9) << A_Matrix(2,2) << ", "; + Stream << setw(9) << A_Matrix(2,3) << " |\n\t| " << setw(9); + Stream << A_Matrix(3,0) << ", " << setw(9) << A_Matrix(3,1) << ", "; + Stream << setw(9) << A_Matrix(3,2) << ", " << setw(9) << A_Matrix(3,3); + return Stream << " |"; +} + +// +//########################################################################### +//########################################################################### +// +TransposedMatrix& + TransposedMatrix::operator=(const AffineMatrix &m) +{ + #if sizeof(m.entries) > sizeof(entries) + # error memcpy size mismatch! + #endif + + memcpy(entries, m.entries, sizeof(m.entries)); + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + return *this; +} + +#if defined(TEST_CLASS) +# include "matrix.tcp" +#endif diff --git a/CODE/RP/MUNGA/MATRIX.HPP b/CODE/RP/MUNGA/MATRIX.HPP new file mode 100644 index 0000000..636b17b --- /dev/null +++ b/CODE/RP/MUNGA/MATRIX.HPP @@ -0,0 +1,261 @@ +//===========================================================================// +// File: matrix.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for the matrix class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 JMA Initial coding. // +// 12/01/94 JMA Changed Matrix to Matrix4x4, based both matrix classes on // +// Matrix44Base // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MATRIX_HPP) +# define MATRIX_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + + class AffineMatrix; + class TransposedMatrix; + class Origin; + class Hinge; + class EulerAngles; + class YawPitchRoll; + class Point3D; + class Quaternion; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AbstractMatrix4x4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AbstractMatrix4x4 + { + public: + Scalar + entries[16]; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile AbstractMatrix4x4 *); + #endif + + AbstractMatrix4x4& + operator=(const AbstractMatrix4x4& m); + + Logical + TestInstance() const; + + protected: + AbstractMatrix4x4() + {} + AbstractMatrix4x4& + Transpose(const AbstractMatrix4x4 &m); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Matrix4x4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Matrix4x4: + public AbstractMatrix4x4 + { + public: + static const Matrix4x4 + Identity; + + // + // Constructors + // + Matrix4x4() + {} + Matrix4x4& + BuildIdentity(); + Matrix4x4(int) + {BuildIdentity();} + + // + // Assignment operators + // + Matrix4x4& + operator=(const Matrix4x4 &m) + { + Check_Pointer(this); Check(&m); + AbstractMatrix4x4::operator=(m); return *this; + } + Matrix4x4& + operator=(const TransposedMatrix &m); + Matrix4x4& + operator=(const AffineMatrix &m); + Matrix4x4& + operator=(const Origin &p); + Matrix4x4& + operator=(const Hinge &hinge); + Matrix4x4& + operator=(const EulerAngles &angles); + Matrix4x4& + operator=(const YawPitchRoll &angles); + Matrix4x4& + BuildRotation(const Quaternion &q); + Matrix4x4& + operator=(const Quaternion &q); + Matrix4x4& + BuildTranslation(const Point3D &p); + Matrix4x4& + operator=(const Point3D &p); + + // + // Index operators + // Note that Matrix4x4 is stored in row major format, not column major, + // although they are indexed the same + // + Scalar& + operator ()(size_t Row,size_t Column) + { + Check_Pointer(this); Warn(Row>3); Warn(Column>3); + return entries[(Row<<2)+Column]; + } + const Scalar& + operator ()(size_t Row,size_t Column) const + { + Check_Pointer(this); Warn(Row>3); Warn(Column>3); + return entries[(Row<<2)+Column]; + } + + // + // Matrix4x4 Multiplication + // + Matrix4x4& + Multiply( + const Matrix4x4& Source1, + const Matrix4x4& Source2 + ); + Matrix4x4& + operator *=(const Matrix4x4& m) + {Matrix4x4 temp(*this); return Multiply(temp,m);} + Matrix4x4& + Multiply( + const Matrix4x4& Source1, + const AffineMatrix &Source2 + ); + Matrix4x4& + operator *=(const AffineMatrix& m) + {Matrix4x4 temp(*this); return Multiply(temp,m);} + Matrix4x4& + Multiply( + const AffineMatrix &Source1, + const Matrix4x4& Source2 + ); + Matrix4x4& + Multiply( + const AffineMatrix &Source1, + const AffineMatrix &Source2 + ); + + // + // Matrix4x4 Inversion + // +#if 0 + Matrix4x4& + Invert(const Matrix4x4& Source); + Matrix4x4& + Invert() + {Matrix4x4 src(*this); return Invert(src);} +#endif + + // + // Viewpoint Calculation + // + Matrix4x4& + SetToProjection( + Scalar Z_Plane, + Scalar Inv_Q, + Scalar Dx, + Scalar Dy, + Scalar Dz + ); + Matrix4x4& + SetToPerspectiveProjection(Scalar Distance) + { + Verify(Distance != 0.0); + return SetToProjection(0.0,1.0/Distance,0.0,0.0,-1.0); + } + Matrix4x4& + SetToOrthogonalProjection() + {return SetToProjection(0.0,0.0,0.0,0.0,-1.0);} + + friend ostream& + operator <<( + ostream& stream, + const Matrix4x4& Matrix4x4 + ); + static Logical + TestClass(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Matrix4x4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class TransposedMatrix: + public AbstractMatrix4x4 + { + public: + // + // Constructors + // + TransposedMatrix() + {} + + // + // Assignment operators + // + TransposedMatrix& + operator=(const Matrix4x4 &m) + { + Check_Pointer(this); Check(&m); + AbstractMatrix4x4::Transpose(m); return *this; + } + TransposedMatrix& + operator=(const TransposedMatrix &m) + { + Check_Pointer(this); Check(&m); + AbstractMatrix4x4::operator=(m); return *this; + } + TransposedMatrix& + operator=(const AffineMatrix &m); + + // + // Index operators + // + Scalar& + operator ()(size_t Row,size_t Column) + { + Check_Pointer(this); Warn(Row>3); Warn(Column>3); + return entries[(Column<<2)+Row]; + } + const Scalar& + operator ()(size_t Row,size_t Column) const + { + Check_Pointer(this); Warn(Row>3); Warn(Column>3); + return entries[(Column<<2)+Row]; + } + + // + // Support Functions + // + friend ostream& + operator <<( + ostream& stream, + const TransposedMatrix& Matrix4x4 + ); + }; + + inline Matrix4x4& + Matrix4x4::operator=(const TransposedMatrix &m) + { + Check_Pointer(this); Check(&m); + AbstractMatrix4x4::Transpose(m); return *this; + } + +#endif + diff --git a/CODE/RP/MUNGA/MATRIX.TCP b/CODE/RP/MUNGA/MATRIX.TCP new file mode 100644 index 0000000..e84d3ca --- /dev/null +++ b/CODE/RP/MUNGA/MATRIX.TCP @@ -0,0 +1,22 @@ +//===========================================================================// +// File: matrix.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the matrix class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + Matrix4x4::TestClass() +{ + DEBUG_STREAM << "Starting Matrix4x4 test...\n"; + Tell(" Matrix4x4::TestClass() is stubbed out!\n"); + return False; +} + diff --git a/CODE/RP/MUNGA/MEMBLOCK.CPP b/CODE/RP/MUNGA/MEMBLOCK.CPP new file mode 100644 index 0000000..bed41a0 --- /dev/null +++ b/CODE/RP/MUNGA/MEMBLOCK.CPP @@ -0,0 +1,678 @@ +//===========================================================================// +// File: memblock.cc // +// Project: MUNGA Brick: Memory Manager // +// Contents: Implementation details of the blockMemory block class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/20/94 JMA Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(MEMBLOCK_HPP) + #include +#endif + +#if !defined(SCALAR_HPP) + #include +#endif + +//#define MEMORY_VERIFY + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlockHeader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile MemoryBlockHeader *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +Logical + MemoryBlockHeader::TestInstance() +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlockBase ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +MemoryBlockBase* + MemoryBlockBase::firstBlock = NULL; + +// +//############################################################################# +// +// This function constructs a MemoryBlockBase variable, allocating a block of +// blockMemory from heap, preparing it for suballocation of a constant record +// blockSize. +// +// NOTE: Record blockSize must be large enough to contain a void pointer in order +// to properly set up the re-use chain! +// +// Rec_Size - blockSize in bytes of the suballocation unit +// Start - number of records to allocate initially +// Delta - number of records to allocate when growing the blockMemory block +// +//############################################################################# +// +MemoryBlockBase::MemoryBlockBase( + size_t rec_size, + size_t start, + size_t delta, + const char* name +) +{ + // + //---------------------------------------------------------------------- + // Make sure that the requested record blockSize is large enough if debugging + // is enabled + //---------------------------------------------------------------------- + // + Verify(rec_size >= sizeof(MemoryBlockHeader)); + + // + //------------------------------------------------------------------------ + // Set up the blockSize variables for the blockMemory block, and figure out the byte + // sizes of the initial block and delta blocks + //------------------------------------------------------------------------ + // + recordSize = rec_size; + blockSize = start * recordSize; + deltaSize = delta * recordSize; + blockName = name; + + // + //------------------------------------------------------------------------- + // Allocate a block big enough for the requested blockMemory plus a link to + // the next blockMemory block, initializing this link to NULL + //------------------------------------------------------------------------- + // + #if !defined(MEMORY_VERIFY) + blockMemory = (MemoryBlockHeader*)new Byte[sizeof(MemoryBlockHeader) + blockSize]; + Verify(blockMemory); + blockMemory->nextBlock = NULL; + blockMemory->blockSize = blockSize; + + // + //---------------------------------------------------------------------- + // Establish the beginning of the firstHeaderRecord record block, and point + // the freeRecord record pointer to the beginning. There are no deletedRecord + // records yet, so make sure Deleted is NULL + //---------------------------------------------------------------------- + // + firstHeaderRecord = (Byte*)(blockMemory + 1); + freeRecord = firstHeaderRecord; + deletedRecord = NULL; + #endif + + // + //-------------------------------------------------------------------------- + // If this is the first memory block, set the first block pointer and + // initialize the ring. If not, insert the new block at the end of the ring + //-------------------------------------------------------------------------- + // + if (!firstBlock) + { + firstBlock = nextBlock = previousBlock = this; + } + else + { + MemoryBlockBase *block = firstBlock; + Check(block); + block = block->previousBlock; + Check(block); + nextBlock = firstBlock; + previousBlock = block; + block->nextBlock = this; + firstBlock->previousBlock = this; + } +} + +// +//############################################################################# +// +// This function destroys the MemoryBlockBase object, deleting any additional +// record blocks which were allocated +// +//############################################################################# +// +MemoryBlockBase::~MemoryBlockBase() +{ +#if !defined(MEMORY_VERIFY) + // + //------------------------------------------------------------------------ + // Find the address of the first record block, then delete blocks until we + // come to the end of the chain + //------------------------------------------------------------------------ + // + Check(this); + MemoryBlockHeader *block = blockMemory; + + while (block) + { + + // + //-------------------------------------------------------------------- + // Save the address of the next blockMemory block, then delete this one and + // get ready to delete the next one + //-------------------------------------------------------------------- + // + Check(block); + MemoryBlockHeader *next_block = block->nextBlock; + delete block; + block = next_block; + } +#endif + + // + //------------------------------------------------------------------------ + // Remove the block from the ring. If the block is the first one, set the + // first block pointer correctly. Note that we memoryblocks, as static + // objects, should deconstruct in the opposite order they constructed, so + // when we reach the first block, it should be the only one in the queue. + //------------------------------------------------------------------------ + // + if (firstBlock == this) + { + if (nextBlock == this) + { + firstBlock = NULL; + } + else + { + firstBlock = nextBlock; + goto Unlink; + } + } + else + { +Unlink: + MemoryBlockBase *next = nextBlock; + Check(next); + MemoryBlockBase *prev = previousBlock; + Check(prev); + next->previousBlock = prev; + prev->nextBlock = next; + } +} + +// +//############################################################################# +// +// This function allocates a fixed blockSize record from the record blocks +// +//############################################################################# +// +void* + MemoryBlockBase::Grow() +{ + #if defined(MEMORY_VERIFY) + Fail("MemoryBlockBase::Grow() not available!\n"); + #endif + // + //--------------------------------------------------------------------- + // If we have freeRecord space left in the firstHeaderRecord record block, allocate the + // new record from here, updating the next freeRecord record pointer + //--------------------------------------------------------------------- + // + Check(this); + if (freeRecord - firstHeaderRecord <= blockSize - recordSize) + { + void *result = freeRecord; + freeRecord += recordSize; + return result; + } + + // + //----------------------------------------------------------------------- + // Allocate a new block of records using the growth blockSize, and make the + // link field of the firstHeaderRecord block point to the new block. Then make the + // new block the firstHeaderRecord block, and make its next link NULL, as it is the + // end of the chain + //----------------------------------------------------------------------- + // + blockSize = deltaSize; + firstHeaderRecord -= sizeof(MemoryBlockHeader); + Byte *new_block = new Byte[blockSize + sizeof(MemoryBlockHeader)]; + Verify(new_block); + + MemoryBlockHeader *header = (MemoryBlockHeader*)firstHeaderRecord; + header->nextBlock = (MemoryBlockHeader*)new_block; + + firstHeaderRecord = new_block; + header = (MemoryBlockHeader*)firstHeaderRecord; + header->nextBlock = NULL; + header->blockSize = deltaSize; + + // + //--------------------------------------------------------------------- + // Make firstHeaderRecord point to the first available address in the new block + // (having skipped the first field allocated to the link pointer), and + // allocate this first block to the caller. Update the freeRecord pointer to + // reflect this allocation + //--------------------------------------------------------------------- + // + firstHeaderRecord += sizeof(MemoryBlockHeader); + freeRecord = firstHeaderRecord + recordSize; + return (void*)firstHeaderRecord; +} + +// +//############################################################################# +//############################################################################# +// +void + MemoryBlockBase::UsageReport() +{ +#if !defined(MEMORY_VERIFY) + DEBUG_STREAM << "#Bytes #Rcds #Dels #Free Use% Name\n"; + DEBUG_STREAM << "------ ----- ----- ----- ---- -------------------------------\n"; + MemoryBlockBase *block = firstBlock; + do + { + Check(block); + MemoryBlockHeader *header = block->blockMemory; + size_t byte_count = 0; + size_t record_count = 0; + size_t deletion_count = 0; + size_t unused_count = + block->blockSize - (block->freeRecord - block->firstHeaderRecord); + unused_count /= block->recordSize; + while (header) + { + Check(header); + record_count += header->blockSize / block->recordSize; + byte_count += header->blockSize + sizeof(MemoryBlockHeader); + header = header->nextBlock; + } + Byte *deletion = block->deletedRecord; + while (deletion) + { + ++deletion_count; + deletion = *(Byte**)deletion; + } + Scalar usage = 1.0f - (deletion_count+unused_count)/(float)record_count; + record_count -= deletion_count + unused_count; + DEBUG_STREAM << setw(6) << byte_count << setw(6) << record_count + << setw(6) << deletion_count << setw(6) << unused_count << setw(4) + << ((int)(usage*100.0f)) << '%'; + if (block->blockName) + { + DEBUG_STREAM << ' ' << block->blockName; + } + DEBUG_STREAM << endl; + block = block->nextBlock; + } + while (block != firstBlock); + DEBUG_STREAM << endl; +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// +// This function allocates a fixed blockSize record from the record blocks +// +//############################################################################# +// +void* + MemoryBlock::New() +{ + void *result; + #if defined(MEMORY_VERIFY) + result = new char[recordSize]; + #else + // + //---------------------------------------------------------------------- + // If we have a deletedRecord record, go ahead and reuse it, updating the next + // deletedRecord record value from the firstHeaderRecord one. This chain is independant + // of the firstHeaderRecord record block. If not, grow the blockMemory block by one + // record + //---------------------------------------------------------------------- + // + Check(this); + if (deletedRecord) + { + result = (void*)deletedRecord; + deletedRecord = *(Byte**)deletedRecord; + } + else + { + result = Grow(); + } + #endif + + // + //---------------------------------------------------------------------- + // If we are checking for unassigned variables, initialize the allocated + // memory with NANs + //---------------------------------------------------------------------- + // + #if defined(DEBUG_NEW_ON) + #define SNAN_POSITIVE_LONG 0x7fb07fb0 + long *filler = (long *)result; + for (int i = recordSize >> 2; i; --i) + { + *filler++ = SNAN_POSITIVE_LONG; + } + #endif + + // + //------------------------------------- + // Return the address of the new record + //------------------------------------- + // + return result; +} + +// +//############################################################################# +// +// This function deallocates a record, making it available for re-use +// +//############################################################################# +// +void + MemoryBlock::Delete( + void* where + ) +{ + #if defined(MEMORY_VERIFY) + delete where; + #else + // + //-------------------------------------------------------------------- + // If we are in debug2 mode, check to see if the deletedRecord region really + // belongs to us + //-------------------------------------------------------------------- + // + Check(this); + + #if DEBUG_LEVEL>1 + + // + //-------------------------------------------------------------------- + // Make sure the address of this record is not already in the deletion + // chain + //-------------------------------------------------------------------- + // + void *record; + for ( + record = (void*)deletedRecord; + record; + record = *(Byte**)record + ) + { + if (record == where) + { + break; + } + } + Verify(!record); + + // + //------------------------------------------------------------------ + // Find the address of the first record block, then check each block + // until we come to the end of the chain + //------------------------------------------------------------------ + // + unsigned + offset; + MemoryBlockHeader* + block = blockMemory; + + while (block) + { + + // + //--------------------------------------------------------------- + // If the record is in this block and is positioned correctly, go + // ahead and break as we have found a legal place within a block + //--------------------------------------------------------------- + // + Check(block); + offset = (unsigned)((Byte*)where - (Byte*)(block + 1)); + if (offset < block->blockSize) + { + Verify(!(offset % recordSize)); + break; + } + + // + //--------------------- + // Go to the next block + //--------------------- + // + block = block->nextBlock; + } + Verify(block); + + // + //----------------------------------------------------------- + // Now make sure that the address is not in our future region + //----------------------------------------------------------- + // + Verify(block->nextBlock || offset < freeRecord-firstHeaderRecord); + + #endif + + // + //---------------------------------------------------------------------- + // Make the first few bytes of the record act as the link pointer to the + // beginning of the firstHeaderRecord deletedRecord chain, then make the first record + // available for reuse this one + //---------------------------------------------------------------------- + // + *(Byte**)where = deletedRecord; + deletedRecord = (Byte*)where; + #endif +} + +// +//############################################################################# +//############################################################################# +// +void* + MemoryBlock::operator[](size_t index) +{ + #if defined(MEMORY_VERIFY) + Fail("MemoryBlock::operator[] not available!\n"); + #endif + + // + //------------------------------------------------------------------ + // Find the address of the first record block, then check each block + // until we come to the end of the chain + //------------------------------------------------------------------ + // + Check(this); + MemoryBlockHeader + *block = blockMemory; + + while (block) + { + // + //--------------------------------------------------------------- + // If the index is in this block, go ahead and return its address + //--------------------------------------------------------------- + // + Check(block); + Verify(recordSize); + int + records = block->blockSize / recordSize; + if (index < records) + { + return (Byte*)(block + 1) + index * recordSize; + } + + // + //-------------------------------------------------------------------- + // Save the address of the next blockMemory block, then delete this one and + // get ready to delete the next one + //-------------------------------------------------------------------- + // + index -= records; + block = block->nextBlock; + } + + // + //----------------------------------------- + // The record doesn't exist, so return NULL + //----------------------------------------- + // + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +void* + MemoryStack::Push(const void* what) +{ + Check(this); + Check_Pointer(what); + + Byte *block = firstHeaderRecord; + topOfStack = freeRecord; + Mem_Copy(Grow(), what, recordSize, blockSize - (freeRecord - firstHeaderRecord)); + if (firstHeaderRecord != block) + { + topOfStack = firstHeaderRecord; + } + return topOfStack; +} + +// +//############################################################################# +//############################################################################# +// +void* + MemoryStack::Push() +{ + Check(this); + Byte *block = firstHeaderRecord; + topOfStack = freeRecord; + Grow(); + + if (firstHeaderRecord != block) + { + topOfStack = firstHeaderRecord; + } + return topOfStack; +} + +// +//########################################################################### +//########################################################################### +// +void + MemoryStack::Pop() +{ + MemoryBlockHeader + *block, + *new_block; + + // + //----------------------------------------- + // Make sure that something is in the stack + //----------------------------------------- + // + Check(this); + if (topOfStack) + { + // + //-------------------------------------------------------------------- + // If the topOfStack of the stack is not at the bottom of a blockMemory block, the + // freeRecord and topOfStack pointers can move normally + //-------------------------------------------------------------------- + // + if (topOfStack != firstHeaderRecord) + { + // + //------------------------------------------------------------------- + // If the freeRecord pointer is at the bottom of a block, we have to delete + // the block and update the variables to the previous block + //------------------------------------------------------------------- + // + if (freeRecord == firstHeaderRecord) + { + new_block = (MemoryBlockHeader*)firstHeaderRecord - 1; + Check(new_block); + for ( + block = blockMemory; + block->nextBlock != new_block; + block = block->nextBlock + ) + { + Check(block); + } + + delete new_block; + block->nextBlock = NULL; + firstHeaderRecord = (Byte*)(block + 1); + blockSize = block->blockSize; + } + + // + //----------------------------------------------- + // Move the topOfStack and freeRecord pointers back one record + //----------------------------------------------- + // + freeRecord = topOfStack; + topOfStack -= recordSize; + } + + // + //-------------------------------------------------------------------- + // Otherwise, we have to wrap the top of the stack pointer back to the + // previous block. If there is only one allocated block, then the + // stack is empty + //-------------------------------------------------------------------- + // + else if (!blockMemory->nextBlock) + { + topOfStack = NULL; + } + + // + //-------------------------------------------------------------------- + // Point the top of the stack to the last record of the previous block + //-------------------------------------------------------------------- + // + else + { + new_block = (MemoryBlockHeader*)firstHeaderRecord - 1; + Check(new_block); + for ( + block = blockMemory; + block->nextBlock != new_block; + block = block->nextBlock + ) + { + Check(block); + } + topOfStack = (Byte*)(block + 1) + block->blockSize - recordSize; + } + } +} + +#if defined(TEST_CLASS) +# include "memblock.tcp" +#endif + diff --git a/CODE/RP/MUNGA/MEMBLOCK.HPP b/CODE/RP/MUNGA/MEMBLOCK.HPP new file mode 100644 index 0000000..9f5d1f3 --- /dev/null +++ b/CODE/RP/MUNGA/MEMBLOCK.HPP @@ -0,0 +1,205 @@ +//===========================================================================// +// File: memblock.hh // +// Project: MUNGA Brick: Memory Manager // +// Contents: Interface specification of the memory block class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/20/94 JMA Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(MEMBLOCK_HPP) +# define MEMBLOCK_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlockHeader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class MemoryBlockHeader + { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile MemoryBlockHeader *p); + #endif + + MemoryBlockHeader + *nextBlock; + size_t + blockSize; + + Logical + TestInstance(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlockBase ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class MemoryBlockBase SIGNATURED + { + public: + Logical + TestInstance() + {return blockMemory != NULL;} + + static void + UsageReport(); + static void + Collapse(); + + protected: + const char + *blockName; + + MemoryBlockHeader + *blockMemory; // the first record block allocated + + size_t + blockSize, // size in bytes of the current record block + recordSize, // size in bytes of the individual record + deltaSize; // size in bytes of the growth blocks + + Byte + *firstHeaderRecord, // the beginning of useful free space + *freeRecord, // the next address to allocate from the block + *deletedRecord; // the next record to reuse + + MemoryBlockBase( + size_t rec_size, + size_t start, + size_t delta, + const char* name = NULL + ); + ~MemoryBlockBase(); + + void* + Grow(); + + private: + static MemoryBlockBase + *firstBlock; + MemoryBlockBase + *nextBlock, + *previousBlock; + + static void + SortDeletions(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class MemoryBlock: + public MemoryBlockBase + { + public: + static Logical + TestClass(); + + MemoryBlock( + size_t rec_size, + size_t start, + size_t delta, + const char* name = NULL + ): + MemoryBlockBase(rec_size, start, delta, name) + {} + + void* + New(); + void + Delete(void *Where); + + void* + operator[](size_t Index); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlockOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class MemoryBlockOf: + public MemoryBlock + { + public: + MemoryBlockOf( + size_t start, + size_t delta, + const char* name=NULL + ): + MemoryBlock(sizeof(T), start, delta, name) + {} + + T* + New() + {return (T*)MemoryBlock::New();} + void + Delete(void *where) + {MemoryBlock::Delete(where);} + + T* + operator[](size_t index) + {return (T*)MemoryBlock::operator[](index);} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class MemoryStack: + public MemoryBlockBase + { + public: + static Logical + TestClass(); + + protected: + Byte + *topOfStack; + + MemoryStack( + size_t rec_size, + size_t start, + size_t delta, + const char* name = NULL + ): + MemoryBlockBase(rec_size, start, delta, name) + {topOfStack = NULL;} + + void* + Push(const void *What); + void* + Push(); + void* + Peek() + {return (void*)topOfStack;} + void + Pop(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStackOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class MemoryStackOf: + public MemoryStack + { + public: + MemoryStackOf( + size_t start, + size_t delta, + const char *name + ): + MemoryStack(sizeof(T), start, delta, name) + {} + + T* + Push(const T *what) + {return (T*)MemoryStack::Push(what);} + T* + Peek() + {return (T*)MemoryStack::Peek();} + void + Pop() + {MemoryStack::Pop();} + }; + +#endif diff --git a/CODE/RP/MUNGA/MEMBLOCK.TCP b/CODE/RP/MUNGA/MEMBLOCK.TCP new file mode 100644 index 0000000..fbaaea4 --- /dev/null +++ b/CODE/RP/MUNGA/MEMBLOCK.TCP @@ -0,0 +1,43 @@ +//===========================================================================// +// File: memblock.tst // +// Project: MUNGA Brick: Memory Manager // +// Contents: Test functions for memoryblock classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/23/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + MemoryBlock::TestClass() +{ + DEBUG_STREAM << "Starting MemoryBlock test...\n"; + + Tell(" MemoryBlock::TestClass() is stubbed out!\n"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +Logical + MemoryStack::TestClass() +{ + DEBUG_STREAM << "Starting MemoryStack test...\n"; + + Tell(" MemoryStack::TestClass() is stubbed out!\n"); + return False; +} + diff --git a/CODE/RP/MUNGA/MEMREG.HPP b/CODE/RP/MUNGA/MEMREG.HPP new file mode 100644 index 0000000..0126b39 --- /dev/null +++ b/CODE/RP/MUNGA/MEMREG.HPP @@ -0,0 +1,121 @@ +//======================================================================= +// File: MEMREG.HPP +// +// Created: Sunday, October 2, 1994, 6:33 PM +// Author: Eric Huffman +// Project: Node.Û +// Compiler: 7.0, Û Symantec Corporation 1994 +//----------------------------------------------------------------------- +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved +// PROPRIETARY AND CONFIDENTIAL +//======================================================================= + +#if !defined(MEMREG_HPP) +# define MEMREG_HPP + + typedef enum + { + PointerMRStatsAddressType, + ObjectMRStatsAddressType + } MRStatsAddressType; + +# undef Start_Registering +# undef Stop_Registering +# undef Register_Object +# undef Register_Pointer +# undef Unregister_Object +# undef Unregister_Pointer +# undef Object_Registration +# undef Check_All_Signatures + +# if !defined(MEMORY_REGISTER) + +# define Start_Registering() +# define Stop_Registering() +# define Register_Object(address) Check(address) +# define Register_Pointer(address) Check_Pointer(address) +# define Unregister_Object(address) Check(address) +# define Unregister_Pointer(address) Check_Pointer(address) +# define Object_Registration(address) +# define Check_All_Signatures() + +# else + + extern void + Start_Registering_Function(); + extern void + Stop_Registering_Function(); + + extern void + Register_Pointer_Function( + void *address, + MRStatsAddressType address_type, + char *file_name, + int line_num + ); + extern void + Unregister_Pointer_Function( + void *address, + char *file_name, + int line_num + ); + + extern void + Object_Registration_Function( + void *address, + char *file_name, + int line_num + ); + + extern void + Check_All_Signatures_Function( + char *file_name, + int line_num + ); + +# define Start_Registering() Start_Registering_Function() +# define Stop_Registering() Stop_Registering_Function() + +# define Check_All_Signatures()\ + Check_All_Signatures_Function(__FILE__, __LINE__) + +# if defined(MEMORY_VERIFY) +# undef Check +# define Check(p) {\ + Check_Signature(p);\ + Verify((p)->TestInstance());\ + Check_All_Signatures();\ + } +# endif + +# define Register_Object(address)\ + {\ + Check(address);\ + Register_Pointer_Function(\ + address,\ + Is_Signature_Bad((Signature*)address) ?\ + PointerMRStatsAddressType : ObjectMRStatsAddressType,\ + __FILE__, __LINE__\ + );\ + } + +# define Register_Pointer(address)\ + Register_Pointer_Function(\ + address, PointerMRStatsAddressType, __FILE__, __LINE__\ + ) + +# define Unregister_Object(address)\ + {\ + Check(address);\ + Unregister_Pointer_Function(address, __FILE__, __LINE__);\ + } +# define Unregister_Pointer(address)\ + Unregister_Pointer_Function(address, __FILE__, __LINE__) + +# define Object_Registration(address)\ + Object_Registration_Function(address, __FILE__, __LINE__) + +# endif + +#endif + diff --git a/CODE/RP/MUNGA/MEMSTRM.CPP b/CODE/RP/MUNGA/MEMSTRM.CPP new file mode 100644 index 0000000..8d58206 --- /dev/null +++ b/CODE/RP/MUNGA/MEMSTRM.CPP @@ -0,0 +1,269 @@ +//===========================================================================// +// File: memstrm.cpp // +// Project: MUNGA Brick: Resource Manager // +// Contents: Implementation Details of resource management // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(MEMSTRM_HPP) + #include +#endif + +//############################################################################# +//########################## MemoryStream ############################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream::MemoryStream( + void *stream_start, + size_t stream_size, + size_t initial_offset +) +{ + Check_Pointer(this); + + streamStart = (char*)stream_start; + streamSize = stream_size; + Verify(initial_offset <= stream_size); + currentPosition = streamStart + initial_offset; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + MemoryStream::ReadBytes( + void *ptr, + size_t number_of_bytes + ) +{ + Check(this); + Check_Pointer(ptr); + Verify(number_of_bytes > 0); + Verify(GetBytesRemaining() >= number_of_bytes); + + Mem_Copy(ptr, GetPointer(), number_of_bytes, number_of_bytes); + AdvancePointer(number_of_bytes); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + MemoryStream::WriteBytes( + const void *ptr, + size_t number_of_bytes + ) +{ + Check(this); + Check_Pointer(ptr); + Verify(number_of_bytes > 0) + + Mem_Copy(GetPointer(), ptr, number_of_bytes, GetBytesRemaining()); + AdvancePointer(number_of_bytes); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + istream *input + ) +{ + Check(stream); + Check_Pointer(input); + + Verify(!input->bad()); + input->clear(); + + // + //-------------------------------------------------------- + // If we are reading a binary stream, read it in one chunk + //-------------------------------------------------------- + // + #if defined(LBE4) + if (input->flags() & ios::binary) + { + #endif + input->seekg(0, ios::end); + int len=input->tellg(); + input->clear(); + input->seekg(0); + + if (!stream->AllocateBytes(len)) + { + Fail("Not enough memory remaining in stream!"); + } + input->read((char*)stream->GetPointer(), len); + stream->AdvancePointer(len); + #if defined(LBE4) + } + + // + //---------------------------------------------------------------- + // Read a text file character by character if we are a DOS machine + //---------------------------------------------------------------- + // + else + { + input->clear(); + input->seekg(0); + unsigned char byte; + + while (input->get(byte)) + { + *stream << byte; + } + } + #endif + return *stream; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const MemoryStream *input_stream + ) +{ + Check(stream); + Check(input_stream); + + return + stream->WriteBytes( + input_stream->GetPointer(), + input_stream->GetBytesRemaining() + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + MemoryStream::TestInstance() const +{ + return size_t(currentPosition - streamStart) <= streamSize; +} + +//############################################################################# +//###################### DynamicMemoryStream ############################ +//############################################################################# + +// +// calculate the allocation size for stream +// +inline size_t + Calculate_Buffer_Size(size_t needed) +{ + return (needed+0x80)&~0x7F; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DynamicMemoryStream::DynamicMemoryStream(size_t stream_size): + MemoryStream(NULL, stream_size) +{ + Check_Pointer(this); + + streamSize = Calculate_Buffer_Size(stream_size); + streamStart = new char[streamSize]; + Register_Pointer(streamStart); + + currentPosition = streamStart; + streamLength = 0L; + ownsStream = True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DynamicMemoryStream::DynamicMemoryStream( + void *stream_start, + size_t stream_size, + size_t initial_offset +): + MemoryStream(stream_start, stream_size, initial_offset) +{ + Check_Pointer(this); + ownsStream = False; + streamLength = stream_size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DynamicMemoryStream::~DynamicMemoryStream() +{ + Check(this); + if (ownsStream) + { + Unregister_Pointer(streamStart); + delete[] streamStart; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DynamicMemoryStream::AllocateBytes(size_t count) +{ + Check(this); + + if (ownsStream && MemoryStream::GetBytesRemaining() < count) + { + size_t current_offset = currentPosition - streamStart; + size_t new_stream_size = + streamSize + count - MemoryStream::GetBytesRemaining() + 1; + new_stream_size = Calculate_Buffer_Size(new_stream_size); + char *new_stream_start = new char[new_stream_size]; + Register_Pointer(new_stream_start); + + Mem_Copy(new_stream_start, streamStart, streamSize, new_stream_size); + Unregister_Pointer(streamStart); + delete[] streamStart; + streamStart = new_stream_start; + streamSize = new_stream_size; + currentPosition = streamStart + current_offset; + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + DynamicMemoryStream::WriteBytes( + const void *ptr, + size_t number_of_bytes + ) +{ + Check(this); + Check_Pointer(ptr); + Verify(number_of_bytes > 0) + + // + //-------------------------------------------------------------------- + // If we own the stream, and we don't have enough memory to accept the + // write, copy the buffer and make a new stream that is bigger + //-------------------------------------------------------------------- + // + AllocateBytes(number_of_bytes); + Mem_Copy( + GetPointer(), + ptr, + number_of_bytes, + MemoryStream::GetBytesRemaining() + ); + AdvancePointer(number_of_bytes); + + streamLength = Max(streamLength, GetBytesUsed()); + return *this; +} + diff --git a/CODE/RP/MUNGA/MEMSTRM.HPP b/CODE/RP/MUNGA/MEMSTRM.HPP new file mode 100644 index 0000000..d6de7d2 --- /dev/null +++ b/CODE/RP/MUNGA/MEMSTRM.HPP @@ -0,0 +1,346 @@ +//===========================================================================// +// File: memstrm.hpp // +// Project: MUNGA Brick: Resource Manager // +// Contents: Implementation Details of resource management // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(MEMSTRM_HPP) +# define MEMSTRM_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + class MemoryStream; + class DynamicMemoryStream; + + //########################################################################## + //####################### MemoryStream ############################### + //########################################################################## + + class MemoryStream SIGNATURED + { + friend MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const MemoryStream *input_stream + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructors + // + public: + MemoryStream( + void *stream_start, + size_t stream_size, + size_t initial_offset=0 + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Status functions + // + public: + virtual void* + GetPointer() const + {Check(this); return currentPosition;} + size_t + GetIndex() const + {Check(this); return currentPosition - streamStart;} + size_t + GetSize() const + {Check(this); return streamSize;} + + size_t + GetBytesUsed() const + {Check(this); return currentPosition - streamStart;} + virtual size_t + GetBytesRemaining() const + {Check(this); return streamSize - GetBytesUsed();} + + virtual void + SetPointer(void *new_pointer) + { + Check_Pointer(this); + currentPosition = (char*)new_pointer; + Check(this); + } + void + operator=(void *new_pointer) + {SetPointer(new_pointer);} + + virtual void + SetPointer(size_t index) + { + Check_Pointer(this); + currentPosition = streamStart + index; + Check(this); + } + void + operator=(size_t index) + {SetPointer(index);} + + void + Rewind() + {SetPointer(0U);} + + virtual Logical + AllocateBytes(size_t count) + {return GetBytesRemaining() <= count;} + virtual MemoryStream& + AdvancePointer(size_t count) + { + Check(this); + currentPosition += count; + Check(this); + return *this; + } + MemoryStream& + operator+=(size_t count) + {return AdvancePointer(count);} + + virtual MemoryStream& + RewindPointer(size_t count) + { + Check(this); + currentPosition -= count; + Check(this); + return *this; + } + MemoryStream& + operator-=(size_t count) + {return RewindPointer(count);} + + virtual MemoryStream& + ReadBytes( + void *ptr, + size_t number_of_bytes + ); + virtual MemoryStream& + WriteBytes( + const void *ptr, + size_t number_of_bytes + ); + + Logical + TestInstance() const; + + protected: + char + *streamStart, + *currentPosition; + size_t + streamSize; + }; + + //-------------------------------------------------------------------------- + // Extraction operators + // + template inline MemoryStream& + operator>>( + MemoryStream &stream, + T &output + ) + {return MemoryStream_Read(&stream, &output);} + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + char *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + Byte *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + short *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + Word *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + int *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + unsigned *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + long *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + LWord *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + + //-------------------------------------------------------------------------- + // Insertion operators + // + template inline MemoryStream& + operator<<( + MemoryStream &stream, + const T &input + ) + {return MemoryStream_Write(&stream, &input);} + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const char *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const Byte *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const short *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const Word *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const int *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const unsigned *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const long *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const LWord *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + istream *input + ); + MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const MemoryStream* input_stream + ); + + #define MEM_STRM_WRITE_ENTRY(stream, name_list, type, name)\ + {\ + type name;\ + Check(name_list);\ + const char* data = (const char*)(name_list)->FindData(#name);\ + if (!data)\ + {\ + DEBUG_STREAM << "DYN_MEM_STRM_WRITE_ENTRY - #name == ";\ + DEBUG_STREAM << #name << "\n";\ + Fail("DYN_MEM_STRM_WRITE_ENTRY - (name_list)->FindData(#name) == NULL");\ + }\ + Check_Pointer(data);\ + Convert_From_Ascii(data, &name);\ + stream << name;\ + } + + //########################################################################## + //################### DynamicMemoryStream ############################ + //########################################################################## + + class DynamicMemoryStream: + public MemoryStream + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + DynamicMemoryStream(size_t stream_size=0); + DynamicMemoryStream( + void *stream_start, + size_t stream_size, + size_t initial_offset=0 + ); + ~DynamicMemoryStream(); + + Logical + TestInstance() const + { + return + (size_t)(currentPosition - streamStart) <= streamSize + && streamLength <= streamSize; + } + + size_t + GetBytesRemaining() const + { + Check(this); + return streamLength - GetBytesUsed(); + } + + Logical + AllocateBytes(size_t count); + + MemoryStream& + WriteBytes( + const void *ptr, + size_t number_of_bytes + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + size_t + streamLength; + Logical + ownsStream; + }; + +#endif + diff --git a/CODE/RP/MUNGA/MISSION.CPP b/CODE/RP/MUNGA/MISSION.CPP new file mode 100644 index 0000000..be374b6 --- /dev/null +++ b/CODE/RP/MUNGA/MISSION.CPP @@ -0,0 +1,649 @@ +//===========================================================================// +// File: mission.cc // +// Project: MUNGA Brick: Application // +// Contents: Implementation Details for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/19/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +#if !defined(GRAPH2D_HPP) +# include +#endif + +//############################################################################# +//####################### MissionHostData ############################### +//############################################################################# + +MissionHostData::MissionHostData( + const CString &address_string, + HostType host_type +): + addressString(address_string), + hostType(host_type) +{ +} + +MissionHostData::~MissionHostData() +{ +} + +//############################################################################# +//########################### Mission ################################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadOrdinalBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load ordinal bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the bitmap names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *ord_namelist = notation_file->MakeEntryList("ordinals", "bitmap"); + if (!ord_namelist) + { + Warn("No Ordinal Bitmaps in Egg \n"); + return; + } + Register_Object(ord_namelist); + NameList::Entry *ord_entry = ord_namelist->GetFirstEntry(); + BitMap *new_bitmap; + int index(0); + while(ord_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the bitmap pageName + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + ++index; + CString ord_bitmap_name = ord_entry->GetChar(); + new_bitmap = new BitMap(notation_file, ord_bitmap_name); + + Register_Object(new_bitmap); + ordinalBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~ + // Increment the index + //~~~~~~~~~~~~~~~~~~~~ + // + ord_entry = ord_entry->GetNextEntry(); + } + + Unregister_Object(ord_namelist); + delete ord_namelist; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadTeamBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load team bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the team names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *team_namelist = notation_file->MakeEntryList("teams", "team"); + if (!team_namelist) + { + return; + } + Register_Object(team_namelist); + NameList::Entry *team_entry = team_namelist->GetFirstEntry(); + BitMap *new_bitmap; + int index(0); + while(team_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the team pageName + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString team_name = team_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Team Bitmap Page Name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char *team_bitmap_name; + notation_file->GetEntry( + team_name, + "bitmap", + &team_bitmap_name + ); + // + //~~~~~~~~~~~~~~~~~~ + // Create the bitMap + //~~~~~~~~~~~~~~~~~~ + // + new_bitmap = new BitMap(notation_file, team_bitmap_name); + Register_Object(new_bitmap); + teamBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~ + // Increment the index + //~~~~~~~~~~~~~~~~~~~~ + // + ++index; + team_entry = team_entry->GetNextEntry(); + } + Unregister_Object(team_namelist); + delete team_namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadNameBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load name bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the large bitmap names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *large_namelist = notation_file->MakeEntryList("largebitmap", "bitmap"); + if (!large_namelist) + { + Warn("No Large NameBitmaps in Egg \n"); + return; + } + Register_Object(large_namelist); + NameList::Entry *large_entry = large_namelist->GetFirstEntry(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the small bitmap names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *small_namelist = notation_file->MakeEntryList("smallbitmap", "bitmap"); + if (!small_namelist) + { + Warn("No Small NameBitmaps in Egg \n"); + return; + } + Register_Object(small_namelist); + NameList::Entry *small_entry = small_namelist->GetFirstEntry(); + + BitMap *new_bitmap; + CString large_bitmap_name, small_bitmap_name; + int index(0); + while(large_entry && small_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the large Name bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ++index; + large_bitmap_name = large_entry->GetChar(); + new_bitmap = new BitMap(notation_file, large_bitmap_name); + Register_Object(new_bitmap); + largeNameBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the small Name bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + small_bitmap_name = small_entry->GetChar(); + new_bitmap = new BitMap(notation_file, small_bitmap_name); + Register_Object(new_bitmap); + smallNameBitmapChain.AddValue(new_bitmap, index); + + small_entry = small_entry->GetNextEntry(); + large_entry = large_entry->GetNextEntry(); + } + + Unregister_Object(large_namelist); + delete large_namelist; + + Unregister_Object(small_namelist); + delete small_namelist; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadLandmarkBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load Landmark bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the landmark names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *landmark_namelist = notation_file->MakeEntryList("landmarks", "landmark"); + if (!landmark_namelist) + { + return; + } + Register_Object(landmark_namelist); + NameList::Entry *landmark_entry = landmark_namelist->GetFirstEntry(); + BitMap *new_bitmap; + int index(0); + while(landmark_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the landmark pageName + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString landmark_name = landmark_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the landmark Bitmap Page Name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char *landmark_bitmap_name; + notation_file->GetEntry( + landmark_name, + "bitmap", + &landmark_bitmap_name + ); + // + //~~~~~~~~~~~~~~~~~~ + // Create the bitMap + //~~~~~~~~~~~~~~~~~~ + // + new_bitmap = new BitMap(notation_file, landmark_bitmap_name); + Register_Object(new_bitmap); + landmarkBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~ + // Increment the index + //~~~~~~~~~~~~~~~~~~~~ + // + ++index; + landmark_entry = landmark_entry->GetNextEntry(); + } + Unregister_Object(landmark_namelist); + delete landmark_namelist; +} + + +// +//############################################################################# +//############################################################################# +// +Mission::Mission( + NotationFile *notation_file, + ResourceFile *resources +): + missionHostSocket(NULL), + largeNameBitmapChain(NULL, True), + smallNameBitmapChain(NULL, True), + ordinalBitmapChain(NULL, True), + teamBitmapChain(NULL, True), + landmarkBitmapChain(NULL, True), + scenarioRoleChain(NULL, True) +{ + Check(notation_file); + Check(resources); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // NULL out All allocated variables + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + colorName = NULL; + badgeName = NULL; + dropZoneName = NULL; + gameModel = NULL; + missionTime = NULL; + missionWeather = NULL; + scenarioName = NULL; + positionName = NULL; + // + //----------------- + // Get the map name + //----------------- + // + Logical ret; + const char *map_name; + + ret = notation_file->GetEntry("mission", "map", &map_name); + if (!ret) + { + DEBUG_STREAM << "ERROR: no map in egg!\n"; + Exit(AbortExitCodeID); + } + + // + //----------------------- + // Get the mission length + //----------------------- + // + gameLength = 0.0; + notation_file->GetEntry("mission", "length", &gameLength); + + // + //------------------------ + // Get the map resource id + //------------------------ + // + ResourceDescription *map = + resources->FindResourceDescription( + map_name, + ResourceDescription::MakeMessageStreamResourceType + ); + if (!map) + { + DEBUG_STREAM << "ERROR: Couldn't find map in resource file!\n"; + Exit(AbortExitCodeID); + } + Check(map); + mapID = map->resourceID; + + // + //---------------------------------- + // Get the existance map resource id + //---------------------------------- + // + map = + resources->FindResourceDescription( + map_name, + ResourceDescription::ExistanceBoxStreamResourceType + ); + if (!map) + { + DEBUG_STREAM << "ERROR: Couldn't find existance map in resource file!\n"; + Exit(AbortExitCodeID); + } + Check(map); + existanceMapID = map->resourceID; + + // + //--------------------------------------------- + // Get the mission time, weather, and scenario + //-------------------------------------------- + // + const char *mission_time; + const char *mission_weather; + const char *mission_scenario; + + ret = notation_file->GetEntry("mission", "time", &mission_time); + if (!ret) + { + DEBUG_STREAM << "ERROR: no time in egg!\n"; + Exit(AbortExitCodeID); + } + + ret = notation_file->GetEntry("mission", "weather", &mission_weather); + if (!ret) + { + DEBUG_STREAM << "ERROR: no weather in egg!\n"; + Exit(AbortExitCodeID); + } + + ret = notation_file->GetEntry("mission", "scenario", &mission_scenario); + if (!ret) + { + DEBUG_STREAM << "ERROR: no scenario in egg!\n"; + Exit(AbortExitCodeID); + } + + int length; + + length = strlen(mission_time) + 1; + missionTime = new char[length]; + Register_Pointer(missionTime); // safer to register BEFORE using + Str_Copy(missionTime, mission_time, length); + + length = strlen(mission_weather) + 1; + missionWeather = new char[length]; + Register_Pointer(missionWeather); // safer to register BEFORE using + Str_Copy(missionWeather, mission_weather, length); + + length = strlen(mission_scenario) + 1; + scenarioName = new char[length]; + Register_Pointer(scenarioName); // safer to register BEFORE using + Str_Copy(scenarioName, mission_scenario, length); + + // + //-------------------------- + // Get the mission host data + //-------------------------- + // + NameList *entry_list; + NameList::Entry *entry; + + playerCount = 0; + entry_list = notation_file->MakeEntryList("pilots", "pilot"); + Register_Object(entry_list); + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + + // + // Get the host address character string + // + char *host_address_pointer = entry->GetChar(); + Check_Pointer(host_address_pointer); + + // + // Create the host address string + // + CString host_address_string(host_address_pointer); + Check(&host_address_string); + + // + // Get the host type + // + int host_type; + + ret = notation_file->GetEntry( + host_address_pointer, + "hostType", + &host_type + ); + if (!ret) + { + DEBUG_STREAM << "ERROR: no host type in egg!\n"; + Exit(AbortExitCodeID); + } + + // + // Create the mission host data + // + MissionHostData *mission_host_data; + + mission_host_data = + new MissionHostData( + host_address_string, + (HostType)host_type + ); + Register_Object(mission_host_data); + + // + // Add to the host socket + // + missionHostSocket.Add(mission_host_data); + ++playerCount; + + entry = entry->GetNextEntry(); + } + #if DEBUG_LEVEL>0 + SChainIteratorOf iterator(&missionHostSocket); + Check(&iterator); + Verify(iterator.GetSize() > 0); + #endif + Unregister_Object(entry_list); + delete entry_list; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Load all the Bitmaps from the Notation File + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + LoadOrdinalBitmaps(notation_file); + LoadNameBitmaps(notation_file); + //LoadTeamBitmaps(notation_file); + //LoadLandmarkBitmaps(notation_file); + + positionName = NULL; +} + +// +//############################################################################# +//############################################################################# +// +Mission::~Mission() +{ + Check(this); + + // + // Delete mission host data + // + SChainIteratorOf iterator(&missionHostSocket); + Check(&iterator); + iterator.DeletePlugs(); + + // + // Delete the text fields + // + if (gameModel) + { + Unregister_Pointer(gameModel); + delete[] gameModel; + } + if (dropZoneName) + { + Unregister_Pointer(dropZoneName); + delete[] dropZoneName; + } + if (colorName) + { + Unregister_Pointer(colorName); + delete[] colorName; + } + if (badgeName) + { + Unregister_Pointer(badgeName); + delete[] badgeName; + } + if (positionName) + { + Unregister_Pointer(positionName); + delete[] positionName; + } + if (missionTime) + { + Unregister_Pointer(missionTime); + delete[] missionTime; + } + if (missionWeather) + { + Unregister_Pointer(missionWeather); + delete[] missionWeather; + } + if (scenarioName) + { + Unregister_Pointer(scenarioName); + delete[] scenarioName; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // delete all the bitmaps + //~~~~~~~~~~~~~~~~~~~~~~~ + // + VChainIteratorOf small_iterator(smallNameBitmapChain); + small_iterator.DeletePlugs(); + + VChainIteratorOf large_iterator(largeNameBitmapChain); + large_iterator.DeletePlugs(); + + VChainIteratorOf ordinal_iterator(ordinalBitmapChain); + ordinal_iterator.DeletePlugs(); + + VChainIteratorOf team_iterator(teamBitmapChain); + team_iterator.DeletePlugs(); + + VChainIteratorOf landmark_iterator(landmarkBitmapChain); + landmark_iterator.DeletePlugs(); + + + VChainIteratorOf role_iterator(scenarioRoleChain); + role_iterator.DeletePlugs(); +} + +// +//############################################################################# +//############################################################################# +// +void + Mission::SetPlayerData( + NotationFile * //notation_file + ) +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Mission::TestInstance() const +{ + Check(&missionHostSocket); + return True; +} + +//############################################################################# +//###################### Mission_HostIterator ########################### +//############################################################################# + +Mission_HostIterator::Mission_HostIterator(Mission *mission): + SChainIteratorOf(&mission->missionHostSocket) +{ +} + +Mission_HostIterator::~Mission_HostIterator() +{ +} + diff --git a/CODE/RP/MUNGA/MISSION.HPP b/CODE/RP/MUNGA/MISSION.HPP new file mode 100644 index 0000000..805e302 --- /dev/null +++ b/CODE/RP/MUNGA/MISSION.HPP @@ -0,0 +1,316 @@ +//===========================================================================// +// File: mission.hh // +// Project: MUNGA Brick: Application // +// Contents: Interface specification for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/19/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MISSION_HPP) +# define MISSION_HPP + +# if !defined(CSTR_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(VCHAIN_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(HOST_HPP) +# include +# endif + +# if !defined(SCNROLE_HPP) +# include +# endif + + class BitMap; + + //########################################################################## + //####################### MissionHostData ############################ + //########################################################################## + + class MissionHostData: + public Plug + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction + // + public: + MissionHostData( + const CString &address_string, + HostType host_type + ); + virtual ~MissionHostData(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessors + // + public: + CString + GetAddressString() + {return addressString;} + HostType + GetHostType() + {return hostType;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + CString addressString; + HostType hostType; + }; + + //########################################################################## + //########################### Mission ################################ + //########################################################################## + + class Mission SIGNATURED + { + friend class Mission_HostIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + typedef Mission_HostIterator HostIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + Mission( + NotationFile *notation_file, + ResourceFile *resources + ); + virtual ~Mission(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Set the player data + // + public: + virtual void + SetPlayerData(NotationFile *notation_file); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessors + // + public: + ResourceDescription::ResourceID + GetMapID(); + ResourceDescription::ResourceID + GetExistanceMapID(); + const char* + GetDropZoneName() + {Check(this); return dropZoneName;} + const char* + GetGameModel() + {Check(this); return gameModel;} + Logical + IsDropZoneHost() + {Check(this); return dropZoneHost;} + const char* + GetColorName() + {Check(this); return colorName;} + const char* + GetBadgeName() + {Check(this); return badgeName;} + const char* + GetMissionTime() + {Check(this); return missionTime;} + const char* + GetMissionWeather() + {Check(this); return missionWeather;} + const char* + GetScenarioName() + {Check(this); return scenarioName;} + + int + GetTeamID() + { Check(this); return teamID; } + int + GetPlayerCount() + {Check(this); return playerCount;} + + const char* + GetPositionName() + { Check(this); return positionName; } + + Scalar + GetGameLength() + { Check(this); return gameLength; } + + BitMap* + GetLargeNameBitmap(int index) + { + Check(this); + return largeNameBitmapChain.Find(index); + } + + BitMap* + GetSmallNameBitmap(int index) + { + Check(this); + return smallNameBitmapChain.Find(index); + } + + BitMap* + GetOrdinalBitmap(int index) + { + Check(this); + return ordinalBitmapChain.Find(index); + } + + BitMap* + GetTeamBitmap(int team_index) + { + Check(this); + return teamBitmapChain.Find(team_index); + } + + BitMap* + GetLandmarkBitmap(int landmark_index) + { + Check(this); + return landmarkBitmapChain.Find(landmark_index); + } + + int + GetPlayerBitmapIndex() const + {Check(this); return playerBitmapIndex;} + + ScenarioRole* + GetScenarioRole(const CString &role_name) + { + Check(this); + VChainIteratorOf iterator(scenarioRoleChain); + return iterator.Find(role_name); + } + + void + AddScenarioRole(ScenarioRole *scenario_role) + { + Check(this); + Check(scenario_role); + if (!GetScenarioRole(scenario_role->GetRoleName())) + { + scenarioRoleChain.AddValue(scenario_role, scenario_role->GetRoleName()); + } + #if DEBUG_LEVEL > 0 + else + { + Tell(scenario_role->GetRoleName()); + Warn(" already exists not adding to Mission \n"); + } + #endif + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected data + // + protected: + + ResourceDescription::ResourceID + mapID, + existanceMapID; + SChainOf + missionHostSocket; + char + *colorName, + *badgeName, + *dropZoneName, + *gameModel, + *missionTime, + *missionWeather, + *scenarioName; + + Logical + dropZoneHost; + char + *positionName; + + int + teamID, + playerCount; + + int + playerBitmapIndex; + + VChainOf + scenarioRoleChain; + + VChainOf + largeNameBitmapChain, + smallNameBitmapChain; + + VChainOf + ordinalBitmapChain; + + VChainOf + teamBitmapChain; + + VChainOf + landmarkBitmapChain; + + void + LoadOrdinalBitmaps(NotationFile *notation_file); + + void + LoadNameBitmaps(NotationFile *notation_file); + + void + LoadTeamBitmaps(NotationFile *notation_file); + + void + LoadLandmarkBitmaps(NotationFile *notation_file); + + Scalar + gameLength; + }; + + inline ResourceDescription::ResourceID + Mission::GetMapID() + { + Check(this); + return mapID; + } + + inline ResourceDescription::ResourceID + Mission::GetExistanceMapID() + { + Check(this); + return existanceMapID; + } + + //########################################################################## + //##################### Mission_HostIterator ######################### + //########################################################################## + + class Mission_HostIterator: + public SChainIteratorOf + { + public: + Mission_HostIterator(Mission *mission); + ~Mission_HostIterator(); + }; + +#endif diff --git a/CODE/RP/MUNGA/MODE.CPP b/CODE/RP/MUNGA/MODE.CPP new file mode 100644 index 0000000..ce8cc31 --- /dev/null +++ b/CODE/RP/MUNGA/MODE.CPP @@ -0,0 +1,75 @@ +//==========================================================================// +// File: mode.cpp // +// Project: MUNGA Brick: Controls Manager // +// Contents: Interface specification for Controls/Gauges // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 02/13/96 CPB First created // +//--------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include +#pragma hdrstop + +#if !defined(MODE_HPP) +# include +#endif + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//############################################################################ +//############################ ModeManager ############################# +//############################################################################ +ModeManager::ModeManager(ModeMask initial_mask) +{ + Check_Pointer(this); + + modeMask = initial_mask; + + Check_Fpu(); +} + +ModeManager::~ModeManager() +{ + Check(this); + Check_Fpu(); +} + +Logical + ModeManager::TestInstance() const +{ + Check_Fpu(); + return True; +} + +Logical + ModeManager::ModeStringLookup( + const char *name, + ModeMask *returned_value + ) +{ + Check(this); + + // There's only one mode value available at this level. + + if (stricmp(name, "ModeAlwaysActive") == 0) + { + *returned_value = ModeManager::ModeAlwaysActive; + Check_Fpu(); + return True; + } + else + { + *returned_value = (ModeMask) 0; + } + Check_Fpu(); + return False; +} diff --git a/CODE/RP/MUNGA/MODE.HPP b/CODE/RP/MUNGA/MODE.HPP new file mode 100644 index 0000000..7a98121 --- /dev/null +++ b/CODE/RP/MUNGA/MODE.HPP @@ -0,0 +1,107 @@ +//===========================================================================// +// File: mode.hpp // +// Project: MUNGA Brick: Controls Module // +// Contents: Interface specification for Controls/Gauges modules // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 2/13/96 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MODE_HPP) +# define MODE_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + //######################################################################## + //############################ Basic typedefs ############################ + //######################################################################## + typedef unsigned long ModeMask; + + //######################################################################### + //############################## ModeManager ############################## + //######################################################################### + class ModeManager SIGNATURED + { + public: + enum + { + nextModeBit=0 + }; + enum + { + ModeAlwaysActive = -1L // WARNING! Assumed to be 32 bits!!! + }; + + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- + public: + ModeManager(ModeMask initial_mask); + ~ModeManager(); + + Logical + TestInstance() const; + + //------------------------------------------------------------------- + // Mode mask accessor + //------------------------------------------------------------------- + public: + void + AddModeMask(ModeMask mode_mask) + { + Check(this); + previousModeMask = modeMask; + modeMask |= mode_mask; + Check_Fpu(); + } + void + RemoveModeMask(ModeMask mode_mask) + { + Check(this); + previousModeMask = modeMask; + modeMask &= ~mode_mask; + Check_Fpu(); + } + void + ReplaceModeMask(ModeMask mode_mask) + { + Check(this); + previousModeMask = modeMask; + modeMask = mode_mask; + Check_Fpu(); + } + ModeMask + GetModeMask() + { + Check(this); + Check_Fpu(); + return modeMask; + } + + ModeMask + GetPreviousModeMask() + { + Check(this); + Check_Fpu(); + return previousModeMask; + } + //------------------------------------------------------------------- + // String-to-Mode lookup + //------------------------------------------------------------------- + public: + virtual Logical + ModeStringLookup(const char *name, ModeMask *returned_value); + + protected: + ModeMask + modeMask, previousModeMask; + }; + +#endif + diff --git a/CODE/RP/MUNGA/MOTION.CPP b/CODE/RP/MUNGA/MOTION.CPP new file mode 100644 index 0000000..9289148 --- /dev/null +++ b/CODE/RP/MUNGA/MOTION.CPP @@ -0,0 +1,110 @@ +//===========================================================================// +// File: motion.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the position class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/19/95 JMA Initial coding. // +// 01/29/95 JMA Added origin concatenation // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(MOTION_HPP) + #include +#endif + +const Motion + Motion::Identity(Vector3D::Identity, Vector3D::Identity); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Motion *) + { + return False; + } +#endif + +Motion::Motion(const Motion& motion) +{ + Check_Pointer(this); + Check(&motion); + + angularMotion = motion.angularMotion; + linearMotion = motion.linearMotion; +} + +// +//########################################################################### +//########################################################################### +// +Motion& + Motion::operator=(const Motion &motion) +{ + Check_Pointer(this); + Check(&motion); + + angularMotion = motion.angularMotion; + linearMotion = motion.linearMotion; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Motion::operator==(const Motion &motion) const +{ + Check(this); + return (memcmp(this, &motion, sizeof(Motion)) == 0); +} + +// +//########################################################################### +//########################################################################### +// +Motion& + Motion::AddScaled( + const Motion& source, + const Motion& delta, + Scalar t + ) +{ + Check_Pointer(this); + Check(&source); + Check(&delta); + Verify(t >= 0.0f); + + linearMotion.AddScaled(source.linearMotion, delta.linearMotion, t); + angularMotion.AddScaled(source.angularMotion, delta.angularMotion, t); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator<<( + ostream& stream, + const Motion& p + ) +{ + return stream << '{' << p.linearMotion << ',' << p.angularMotion << '}'; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Motion::TestInstance() const +{ + return angularMotion.TestInstance(); +} + diff --git a/CODE/RP/MUNGA/MOTION.HPP b/CODE/RP/MUNGA/MOTION.HPP new file mode 100644 index 0000000..d4ee506 --- /dev/null +++ b/CODE/RP/MUNGA/MOTION.HPP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: motion.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the position class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MOTION_HPP) +# define MOTION_HPP + +# if !defined(VECTOR3D_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Motion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Motion + { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Motion *); + #endif + + Vector3D + linearMotion; + Vector3D + angularMotion; + + static const Motion + Identity; + + // + // Constructors + // + Motion() + {} + Motion(const Motion& motion); + Motion( + const Vector3D& t, + const Vector3D& q + ) + {Check(&t); Check(&q); linearMotion = t; angularMotion = q;} + + // + // Assignment operators + // + Motion& + operator=(const Motion& p); + + // + // Equality operator + // + Logical + operator==(const Motion&) const; + + // + // Origin motion + // + Motion& + AddScaled( + const Motion& source, + const Motion& delta, + Scalar t + ); + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const Motion& p + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + +#endif diff --git a/CODE/RP/MUNGA/MOVER.CPP b/CODE/RP/MUNGA/MOVER.CPP new file mode 100644 index 0000000..328b72b --- /dev/null +++ b/CODE/RP/MUNGA/MOVER.CPP @@ -0,0 +1,2126 @@ +//===========================================================================// +// File: mover.cc // +// Project: MUNGA Brick: Model Manager // +// Contents: Implementation details of moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(MOVER_HPP) + #include +#endif + +#if !defined(PLAYER_HPP) + #include +#endif + +#if !defined(BOXSOLID_HPP) + #include +#endif + +#if !defined(INTEREST_HPP) + #include +#endif + +#if !defined(COLLASST_HPP) + #include +#endif + +#if !defined(DOORFRAM_HPP) + #include +#endif + +#if !defined(DOOR_HPP) + #include +#endif + +#if !defined(LINE_HPP) + #include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(NOTATION_HPP) + #include +#endif + +//############################################################################# +//############################### Mover ################################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation + Mover::ClassDerivations( + Entity::ClassDerivations, + "Mover" + ); + +Mover::SharedData + Mover::DefaultData( + Mover::ClassDerivations, + Mover::MessageHandlers, + Mover::AttributeIndex, + Mover::StateCount, + (Entity::MakeHandler)Mover::Make + ); + +//############################################################################# +// Message Support +// +#if 0 +const Receiver::HandlerEntry + Mover::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Mover, Update) +}; + +Entity::MessageHandlerSet + Mover::MessageHandlers( + ELEMENTS(Mover::MessageHandlerEntries), + Mover::MessageHandlerEntries, + Entity::MessageHandlers + ); +#endif + +//############################################################################# +// Attribute Support +// +const Mover::IndexEntry + Mover::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Mover, LocalVelocity, localVelocity), + ATTRIBUTE_ENTRY(Mover, LocalAcceleration, localAcceleration), + ATTRIBUTE_ENTRY(Mover, WorldLinearVelocity, worldLinearVelocity), + ATTRIBUTE_ENTRY(Mover, WorldLinearAcceleration, worldLinearAcceleration), + ATTRIBUTE_ENTRY(Mover, MoverMass, moverMass), + ATTRIBUTE_ENTRY(Mover, MomentOfInertia, momentOfInertia), + ATTRIBUTE_ENTRY( + Mover, + PositiveLinearDragCoefficients, + positiveLinearDragCoefficients + ), + ATTRIBUTE_ENTRY( + Mover, + NegativeLinearDragCoefficients, + negativeLinearDragCoefficients + ), + ATTRIBUTE_ENTRY(Mover, AngularDragCoefficients, angularDragCoefficients), + ATTRIBUTE_ENTRY(Mover, FrictionCoefficient, frictionCoefficient), + ATTRIBUTE_ENTRY(Mover, ElasticityCoefficient, elasticityCoefficient), + ATTRIBUTE_ENTRY(Mover, MinimumBounceSpeed, minimumBounceSpeed) +}; + +Mover::AttributeIndexSet + Mover::AttributeIndex( + ELEMENTS(Mover::AttributePointers), + Mover::AttributePointers, + Entity::AttributeIndex + ); + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::UpdateWorldMotion() +{ + Check(this); + + // + //--------------------------------------------------- + // Move the accelerations back into world coordinates + //--------------------------------------------------- + // + worldLinearAcceleration.Multiply( + localAcceleration.linearMotion, + localToWorld + ); + worldLinearVelocity.Multiply( + localVelocity.linearMotion, + localToWorld + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::UpdateLocalMotion() +{ + Check(this); + localVelocity.linearMotion.MultiplyByInverse( + worldLinearVelocity, + localToWorld + ); + localAcceleration.linearMotion.MultiplyByInverse( + worldLinearAcceleration, + localToWorld + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyWorldAccelerations(Scalar time_slice) +{ + Check(this); + Verify(time_slice > 0.0f); + + // + //-------------------------------------------------- + // Calculate the new position as p += v*t + a*.5*t*t + //-------------------------------------------------- + // + Scalar + half_t_squared = 0.5f * time_slice * time_slice; + Vector3D + position_delta; + position_delta.Multiply(worldLinearAcceleration, half_t_squared); + Check_Fpu(); + + position_delta.AddScaled( + position_delta, + worldLinearVelocity, + time_slice + ); + Check_Fpu(); + + localOrigin.linearPosition.Add(localOrigin.linearPosition, position_delta); + Check_Fpu(); + + position_delta.Multiply(localAcceleration.angularMotion, half_t_squared); + Check_Fpu(); + + position_delta.AddScaled( + position_delta, + localVelocity.angularMotion, + time_slice + ); + Check_Fpu(); + + Quaternion + old_position = localOrigin.angularPosition; + localOrigin.angularPosition.Add(old_position, position_delta); + Check_Fpu(); + // + //----------------------------------- + // Calculate our velocity as v += a*t + //----------------------------------- + // + worldLinearVelocity.AddScaled( + worldLinearVelocity, + worldLinearAcceleration, + time_slice + ); + Check_Fpu(); + localVelocity.angularMotion.AddScaled( + localVelocity.angularMotion, + localAcceleration.angularMotion, + time_slice + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::CalculateDrag( + Vector3D *drag, + const Vector3D &velocity, + const Vector3D &positive_CODs, + const Vector3D &negative_CODs, + Scalar power + ) +{ + Environment *air = GetEnvironment(); + Check(air); + Vector3D temp,temp2; + temp.MultiplyByInverse(air->GetWindVelocity(), localToWorld); + temp += velocity; + + if (temp.x < 0.0f) + { + drag->x = negative_CODs.x; + temp2.x = Power(-temp.x, power); + Check_Fpu(); + } + else + { + drag->x = -positive_CODs.x; + temp2.x = Power(temp.x, power); + Check_Fpu(); + } + + if (temp.y < 0.0f) + { + drag->y = negative_CODs.y; + temp2.y = Power(-temp.y, power); + Check_Fpu(); + } + else + { + drag->y = -positive_CODs.y; + temp2.y = Power(temp.y, power); + Check_Fpu(); + } + + if (temp.z < 0.0f) + { + drag->z = negative_CODs.z; + temp2.z = Power(-temp.z, power); + Check_Fpu(); + } + else + { + drag->z = -positive_CODs.z; + temp2.z = Power(temp.z, power); + Check_Fpu(); + } + + *drag *= air->airDensity; + drag->Multiply(*drag, temp2); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyAirResistanceAndGravity(Scalar power) +{ + Check(this); + + // + //------------------------------------------------------------------------- + // Apply drag to the system, allowing for different drag numbers based upon + // the direction of motion along the axis + //------------------------------------------------------------------------- + // + Vector3D acceleration; + CalculateDrag( + &acceleration, + localVelocity.linearMotion, + positiveLinearDragCoefficients, + negativeLinearDragCoefficients, + power + ); + localAcceleration.linearMotion += acceleration; + + acceleration.Multiply(angularDragCoefficients, localVelocity.angularMotion); + localAcceleration.angularMotion -= acceleration; + + // + //--------------------------- + // Apply gravity to the craft + //--------------------------- + // + UpdateWorldMotion(); + worldLinearAcceleration.y -= GetEnvironment()->gravityConstant; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyLocalForce( + const Vector3D &force, + const Vector3D &moment + ) +{ + Check(this); + Check(&force); + Check(&moment); + + Vector3D acceleration; + Verify(!Small_Enough(moverMass)); + acceleration.Divide(force, moverMass); + ApplyLocalAcceleration(acceleration, moment); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyLocalAcceleration( + const Vector3D &acceleration, + const Vector3D &moment + ) +{ + Check(this); + Check(&acceleration); + Check(&moment); + + localAcceleration.linearMotion += acceleration; + Vector3D torque; + torque.Cross(moment, acceleration); + torque *= momentOfInertia; + localAcceleration.angularMotion += torque; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::NoDeadReckoner() +{ + Check(this); + + // + //------------------------------------------------------------------------- + // If we are the replicant instance and we are not yet past the anticipated + // time for the next event, project out to the next event + //------------------------------------------------------------------------- + // + projectedOrigin = updateOrigin; + Check_Fpu(); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::LinearDeadReckoner() +{ + Check(this); + Logical lerp_mode; + Scalar time_slice; + + // + //------------------------------------------------------------------------- + // If we are the replicant instance and we are not yet past the anticipated + // time for the next event, project out to the next event + //------------------------------------------------------------------------- + // + if (GetInstance() == ReplicantInstance && lastPerformance < nextUpdate) + { + time_slice = nextUpdate - lastUpdate; + lerp_mode = True; + } + else + { + time_slice = lastPerformance - lastUpdate; + lerp_mode = False; + } + + // + //--------------------------------------- + // Calculate the new position as p += v*t + //--------------------------------------- + // + Vector3D position_delta; + position_delta.Multiply(updateVelocity.linearMotion, time_slice); + projectedOrigin.linearPosition.Add( + updateOrigin.linearPosition, + position_delta + ); + + // + //------------------------------- + // Handle projecting the rotation + //------------------------------- + // + position_delta.Multiply(updateVelocity.angularMotion, time_slice); + projectedOrigin.angularPosition.Add( + updateOrigin.angularPosition, + position_delta + ); + projectedVelocity = updateVelocity; + + Check_Fpu(); + return lerp_mode; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::AcceleratedDeadReckoner() +{ + Check(this); + Logical lerp_mode; + Scalar time_slice; + + // + //------------------------------------------------------------------------- + // If we are the replicant instance and we are not yet past the anticipated + // time for the next event, project out to the next event + //------------------------------------------------------------------------- + // + if (GetInstance() == ReplicantInstance && lastPerformance < nextUpdate) + { + time_slice = nextUpdate - lastUpdate; + lerp_mode = True; + } + else + { + time_slice = lastPerformance - lastUpdate; + lerp_mode = False; + } + + // + //-------------------------------------------------- + // Calculate the new position as p += v*t + a*.5*t*t + //-------------------------------------------------- + // + Scalar half_t_squared = 0.5f * time_slice * time_slice; + Vector3D position_delta; + position_delta.Multiply(updateAcceleration.linearMotion, half_t_squared); + position_delta.AddScaled( + position_delta, + updateVelocity.linearMotion, + time_slice + ); + projectedOrigin.linearPosition.Add( + updateOrigin.linearPosition, + position_delta + ); + + // + //------------------------------- + // Handle projecting the rotation + //------------------------------- + // + position_delta.Multiply(updateAcceleration.angularMotion, half_t_squared); + position_delta.AddScaled( + position_delta, + updateVelocity.angularMotion, + time_slice + ); + projectedOrigin.angularPosition.Add( + updateOrigin.angularPosition, + position_delta + ); + + // + //----------------------------------- + // Calculate our velocity as v += a*t + //----------------------------------- + // + if (GetInstance() == ReplicantInstance) + { + projectedVelocity.linearMotion.AddScaled( + updateVelocity.linearMotion, + worldLinearAcceleration, + time_slice + ); + projectedVelocity.angularMotion.AddScaled( + updateVelocity.angularMotion, + localAcceleration.angularMotion, + time_slice + ); + } + Check_Fpu(); + return lerp_mode; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::DeadReckon(Scalar time_slice) +{ + Check(this); + + // + //------------------------------ + // Run the chosen dead reckoning + //------------------------------ + // + Verify(GetInstance() == ReplicantInstance); + if (deadReckoner) + { + // + //--------------------------------------------------------------------- + // Merge the projected origin with the current origin if we are in lerp + // mode. If not, just copy the projected origin into the local origin + //--------------------------------------------------------------------- + // + if ((this->*deadReckoner)()) + { + Scalar percent = + time_slice / ((nextUpdate - lastPerformance) + time_slice); + + // + //------------------------------------------ + // Do a spherical lerp on the angular motion + //------------------------------------------ + // + localOrigin.angularPosition.Lerp( + localOrigin.angularPosition, + projectedOrigin.angularPosition, + percent + ); + localVelocity.angularMotion.Lerp( + localVelocity.angularMotion, + projectedVelocity.angularMotion, + percent + ); + + // + //------------------------- + // Spline the linear motion + //------------------------- + // + #if 0 + CubicCurve + spline( + localOrigin.linearPosition, + worldLinearVelocity, + projectedOrigin.linearPosition, + projectedVelocity.linearMotion + ); + spline.Evaluate( + percent, + &localOrigin.linearPosition, + &worldLinearVelocity + ); + #else + localOrigin.linearPosition.Lerp( + localOrigin.linearPosition, + projectedOrigin.linearPosition, + percent + ); + worldLinearVelocity.Lerp( + worldLinearVelocity, + projectedVelocity.linearMotion, + percent + ); + #endif + } + else + { + localOrigin = projectedOrigin; + worldLinearVelocity = projectedVelocity.linearMotion; + localVelocity.angularMotion = projectedVelocity.angularMotion; + } + + // + //---------------------------------------------------- + // Update the collision volume and the local variables + //---------------------------------------------------- + // + if (IsCollisionVolume()) + { + MoveCollisionVolume(); + } + else + { + localToWorld = localOrigin; + } + UpdateLocalMotion(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::PerformAndWatch( + const Time &till, + MemoryStream *update_stream + ) +{ + Check(this); + Check(&till); + + int i; + + // + //-------------------------------------------------------------------------- + // Make sure that the time into the simulations is stable. If a half-second + // delay occurs, or we are in stasis, just bring everything up to date + //-------------------------------------------------------------------------- + // + Scalar time_slice = till - lastPerformance; + if (time_slice < SMALL) + { + Tell("No time!\n"); +Bye_Bye: + WriteSimulationUpdate(update_stream); + return; + } + + if (GetSimulationState() == StasisState || time_slice > 0.5f) + { + lastPerformance = till; + if (GetSimulationState() == StasisState) + { + lastUpdate = till; + } + if (subsystemArray) + { + Check_Pointer(subsystemArray); + for (i=0; iSetLastPerformance(till); + } + } + } + //SetSimulationState(DefaultState); + goto Bye_Bye; + } + + // + //------------------------------------ + // Set up for local motion calculation + //------------------------------------ + // + localVelocity.linearMotion.MultiplyByInverse( + worldLinearVelocity, + localToWorld + ); + localAcceleration = Motion::Identity; + previousOrigin = localOrigin; + + // + //----------------------- + // Process the subsystems + //----------------------- + // + Entity::PerformAndWatch(till, update_stream); + + // + //----------------------------------------------- + // Make sure the position quaternion stays stable + //----------------------------------------------- + // + if (++normalizeCount == 20) + { + localOrigin.angularPosition.Normalize(); + normalizeCount = 0; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ReadUpdateRecord(Simulation::UpdateRecord *record) +{ + Check(this); + Check_Pointer(record); + switch (record->recordID) + { + case DefaultUpdateModelBit: + { + + // + //------------------------------------------- + // HACK - precalculation for next update time + //------------------------------------------- + // + nextUpdate = Now(); + Scalar diff = nextUpdate - lastUpdate; + if (diff < 10.0f) + { + nextUpdate.ticks += nextUpdate.ticks - lastUpdate.ticks; + } + + // + //--------------------------------------- + // Handle updating the entity information + //--------------------------------------- + // + Entity::ReadUpdateRecord(record); + + // + //----------------------- + // Update the motion data + //----------------------- + // + UpdateRecord *update = (UpdateRecord*)record; + + localAcceleration = update->localAcceleration; + worldLinearAcceleration = update->worldLinearAcceleration; + + updateVelocity.linearMotion = update->worldLinearVelocity; + updateVelocity.angularMotion = update->localVelocity.angularMotion; + + updateAcceleration.linearMotion = update->worldLinearAcceleration; + updateAcceleration.angularMotion = update->localAcceleration.angularMotion; + + // + //----------------------------------------- + // Update the collision volume if necessary + //----------------------------------------- + // + if (IsCollisionVolume()) + { + MoveCollisionVolume(); + } + } + break; + + default: + Entity::ReadUpdateRecord(record); + break; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::WriteUpdateRecord( + Simulation::UpdateRecord *record, + int update_model + ) +{ + Check(this); + Check_Pointer(record); + switch (update_model) + { + case DefaultUpdateModelBit: + { + Entity::WriteUpdateRecord(record, update_model); + + UpdateRecord *update = (UpdateRecord*)record; + + update->recordLength = sizeof(*update); + update->localVelocity = localVelocity; + update->localAcceleration = localAcceleration; + + update->worldLinearVelocity = worldLinearVelocity; + update->worldLinearAcceleration = worldLinearAcceleration; + + updateVelocity.linearMotion = worldLinearVelocity; + updateVelocity.angularMotion = localVelocity.angularMotion; + + updateAcceleration.linearMotion = worldLinearAcceleration; + updateAcceleration.angularMotion = localAcceleration.angularMotion; + } + break; + default: + Entity::WriteUpdateRecord(record, update_model); + break; + } + Check_Fpu(); +} + +//############################################################################# +// Collision support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::MoveCollisionVolume() +{ + // + //--------------------------------------------------- + // Make sure that there is a collision volume to move + //--------------------------------------------------- + // + Check(this); + if (!collisionVolumeCount) + { + Check_Fpu(); + return; + } + + // + //------------------------------------------------------------------------ + // Set up the extents of the collision volume from the template and the + // current position. We must find the center point of the template volume + // and rotate it about the y axis + //------------------------------------------------------------------------ + // + Check(collisionTemplate); + Check(collisionVolume); + Verify(collisionVolumeCount == 1); + Verify(collisionTemplate->solidType == BoxedSolid::YAxisCylinderType); + + localToWorld = localOrigin; + Point3D centerPoint; + centerPoint.x = (collisionTemplate->minX + collisionTemplate->maxX) * 0.5f; + centerPoint.y = (collisionTemplate->minY + collisionTemplate->maxY) * 0.5f; + centerPoint.z = (collisionTemplate->minZ + collisionTemplate->maxZ) * 0.5f; + Vector3D radius; + radius.x = collisionTemplate->maxX - centerPoint.x; + radius.y = collisionTemplate->maxY - centerPoint.y; + radius.z = collisionTemplate->maxZ - centerPoint.z; + Point3D rotated; + rotated.Multiply(centerPoint, localToWorld); + + collisionVolume->minX = rotated.x - radius.x; + collisionVolume->maxX = rotated.x + radius.x; + collisionVolume->minY = rotated.y - radius.y; + collisionVolume->maxY = rotated.y + radius.y; + collisionVolume->minZ = rotated.z - radius.z; + collisionVolume->maxZ = rotated.z + radius.z; + + // + //------------------------------------------------------------ + // Now, Find the smallest node containing our collision column + //------------------------------------------------------------ + // + if (GetInstance() != ReplicantInstance) + { + InterestManager *interest_mgr = + application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = + interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + containedByNode = + tree->FindSmallestNodeContainingColumn(*collisionVolume); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolidCollisionList* + Mover::AllocateCollisionList() +{ + Check(this); + + // + //----------------------------------------------------------- + // Find the correct collision list to use, and reset to empty + //----------------------------------------------------------- + // + BoxedSolidCollisionList *collision_list; + if (lastCollisionList == collisionLists) + { + collision_list = &collisionLists[1]; + } + else + { + collision_list = collisionLists; + } + Check(collision_list); + collision_list->Reset(); + return collision_list; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolidCollisionList* + Mover::GetCurrentCollisions(BoxedSolidCollisionList *collision_list) +{ + Check(this); + + if (!collision_list) + { + collision_list = AllocateCollisionList(); + } + Check(collision_list); + + // + //--------------------------------- + // Test against the tangible movers + //--------------------------------- + // + Check(collisionAssistant); + CollisionAssistant::MovingEntityIterator iterator(collisionAssistant); + Entity *entity; + Check(collisionVolume); + while ((entity = iterator.ReadAndNext()) != NULL) + { + // + //------------------------------------------------------------------ + // If we are checking against ourselves, or something more than 50m + // away, skip it + //------------------------------------------------------------------ + // + Check(entity); + if (entity == this) + { + continue; + } + Vector3D delta; + delta.Subtract( + entity->localOrigin.linearPosition, + localOrigin.linearPosition + ); + if (delta.LengthSquared() > 2500.0f) + { + continue; + } + + // + //-------------------------------------------------- + // If we have a mover class object, check against it + //-------------------------------------------------- + // + if (entity->IsDerivedFrom(Mover::ClassDerivations)) + { + Mover *mover = (Mover*)entity; + Check(mover); + Check(mover->collisionVolume); + CheckAgainstBoxedSolidChain(collision_list, mover->collisionVolume); + } + + // + //----------------------------------------------------------------------- + // If we have a door, check against its subsystems if we are close enough + // for it to matter + //----------------------------------------------------------------------- + // + else if (entity->IsDerivedFrom(DoorFrame::ClassDerivations)) + { + DoorFrame *door_frame = (DoorFrame*)entity; + Check(door_frame); + for (int i=0; iGetSubsystemCount(); ++i) + { + Door *door = (Door*)door_frame->GetSubsystem(i); + CheckAgainstBoxedSolidChain( + collision_list, + door->GetFirstBoxedSolid() + ); + } + } + } + + // + //------------------------------ + // Test against the static world + //------------------------------ + // + containedByNode->FindBoundingBoxesContaining( + collisionVolume, + *collisionVolume, + *collision_list + ); + + Check_Fpu(); + return collision_list; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid* + Mover::FindBoxedSolidHitBy( + Line *line, + Entity *except + ) +{ + Check(this); + Check(line); + + // + //------------------------------------------------------------------------- + // Calculate the midpoint of the line, and sweep a sphere out around the + // line from that point, including an extra 50 meters. This extra distance + // takes into account the doors... + //------------------------------------------------------------------------- + // + Point3D center; + Scalar radius = line->length * 0.5f; + line->Project(radius, ¢er); + + // + //--------------------------------- + // Test against the tangible movers + //--------------------------------- + // + Check(collisionAssistant); + CollisionAssistant::MovingEntityIterator iterator(collisionAssistant); + Entity *entity; + BoxedSolid + *solid = NULL, + *result; + + while ((entity = iterator.ReadAndNext()) != NULL) + { + // + //--------------------------------------------------------------- + // If we are checking against ourselves or the exception, skip it + //--------------------------------------------------------------- + // + Check(entity); + if (entity == this || except && except == entity) + { + continue; + } + + // + //------------------------------------------------------------------- + // If we have a mover class object, check against it. If we have no + // collision volume, we are just using a line, so just run it against + // the collision volume chain + //------------------------------------------------------------------- + // + if (entity->IsDerivedFrom(Mover::ClassDerivations)) + { + Mover *mover = (Mover*)entity; + Check(mover); + Check(mover->collisionVolume); + + // + //----------------------------------------------------------------- + // If the mover is close enough to the radius of the line, check it + //----------------------------------------------------------------- + // + Vector3D delta; + delta.Subtract(entity->localOrigin.linearPosition, center); + Scalar r2 = + mover->collisionVolume->maxX - mover->collisionVolume->minX; + r2 += mover->collisionVolume->maxY - mover->collisionVolume->minY; + r2 *= 0.5f; + r2 += radius; + if (delta.LengthSquared() > r2*r2) + { + continue; + } + + result = + CheckLineAgainstBoxedSolidChain(line, mover->collisionVolume); + if (result) + { + Check(result); + solid = result; + } + } + + // + //----------------------------------------------------------------------- + // If we have a door, check against its subsystems if we are close enough + // for it to matter + //----------------------------------------------------------------------- + // + else if (entity->IsDerivedFrom(DoorFrame::ClassDerivations)) + { + // + //----------------------------------------------------------------- + // If the mover is close enough to the radius of the line, check it + //----------------------------------------------------------------- + // + Vector3D delta; + delta.Subtract(entity->localOrigin.linearPosition, center); + Scalar r2 = radius + 50.0f; + if (delta.LengthSquared() > r2*r2) + { + continue; + } + + DoorFrame *door_frame = (DoorFrame*)entity; + Check(door_frame); + for (int i=0; iGetSubsystemCount(); ++i) + { + Door *door = (Door*)door_frame->GetSubsystem(i); + result = + CheckLineAgainstBoxedSolidChain( + line, + door->GetFirstBoxedSolid() + ); + if (result) + { + Check(result); + solid = result; + } + } + } + } + + // + //------------------------------ + // Test against the static world + //------------------------------ + // + InterestManager *interest_mgr = application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + result = (BoxedSolid*)tree->FindBoundingBoxHitBy(line); + if (result) + { + Check(result); + solid = result; + } + Check_Fpu(); + return solid; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolidCollisionList* + Mover::CollideCenterOfMotion( + Line *line, + BoxedSolidCollisionList *list + ) +{ + Check(this); + Check(line); + + // + //----------------------------------------------------------- + // Find the correct collision list to use, and reset to empty + //----------------------------------------------------------- + // + if (!list) + { + list = AllocateCollisionList(); + } + Check(list); + + // + //------------------------------------------------------------------------ + // If the length of the line has changed, we must reposition the collision + // volume appropriately + //------------------------------------------------------------------------ + // + BoxedSolid *solid = FindBoxedSolidHitBy(line, NULL); + if (solid && IsCollisionVolume()) + { + line->FindEnd(&localOrigin.linearPosition); + MoveCollisionVolume(); + ExtentBox slice; + slice.Intersect(*collisionVolume, *solid); + Verify(list->GetCollisionsLeft()); + list->AddCollisionToList(solid, slice); + } + + Check_Fpu(); + return list; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ProcessCollisionList( + BoxedSolidCollisionList *collisions, + Scalar time_slice, + const Point3D &old_position, + Damage *damage + ) +{ + Check(this); + Check(collisions); + Verify(time_slice > 0.0f); + Check(&old_position); + Check_Pointer(damage); + + damage->damageAmount = 0.0f; + damage->damageType = Damage::CollisionDamageType; + damage->impactPoint = Point3D::Identity; + + if (collisions->GetCollisionCount()) + { + // + //------------------------------------------------------------------ + // Reduce the number of collisions we have to play with based on our + // velocity + //------------------------------------------------------------------ + // + collisions->ReduceCollisionList(worldLinearVelocity); + + // + //----------------------------------------------------------------- + // Setup up the totaling variables to handle averaging out multiple + // collisions + //----------------------------------------------------------------- + // + int total_collisions = 0; + Vector3D resultant_velocity = Vector3D::Identity; + Point3D resultant_position = Point3D::Identity; + Vector3D resultant_normal = Vector3D::Identity; + Vector3D initial_velocity = worldLinearVelocity; + Vector3D initial_position = localOrigin.linearPosition; + Scalar total_damage = 0.0f; + + // + //--------------------------------------------------------------------- + // For each hit in the list, process it, and if the collision is + // determined to be valid, bounce it and add the result into the others + //--------------------------------------------------------------------- + // + for (int i=0; iGetRealCollisions(); ++i) + { + // + //---------------------------------------------------------- + // Make sure to bounce the vehicle from the correct location + //---------------------------------------------------------- + // + worldLinearVelocity = initial_velocity; + localOrigin.linearPosition = initial_position; + damage->damageAmount = 0.0f; + ProcessCollision( + time_slice, + (*collisions)[i], + old_position, + damage + ); + if (damage->damageAmount > 0.0f) + { + ++total_collisions; + resultant_velocity += worldLinearVelocity; + resultant_position += localOrigin.linearPosition; + resultant_normal += damage->surfaceNormal; + total_damage += damage->damageAmount; + ExtentBox *box = &(*collisions)[i].collisionSlice; + damage->impactPoint.x += 0.5 * + ( + box->minX + box->maxX + - (collisionVolume->minX - collisionVolume->maxX) + ); + damage->impactPoint.y += 0.5 * + ( + box->minY + box->maxY + - (collisionVolume->minY - collisionVolume->maxY) + ); + damage->impactPoint.z += 0.5 * + ( + box->minZ + box->maxZ + - (collisionVolume->minZ - collisionVolume->maxZ) + ); + } + } + + // + //----------------------------------------------------------------- + // If we collided with more than one thing, average out the results + //----------------------------------------------------------------- + // + if (total_collisions > 1) + { + worldLinearVelocity.Divide(resultant_velocity, total_collisions); + localOrigin.linearPosition.Divide( + resultant_position, + total_collisions + ); + damage->surfaceNormal.Vector3D::Divide( + resultant_normal, + total_collisions + ); + goto Figure_Normal; + } + + // + //------------------------------------------------------ + // Otherwise, just set up the positions from the results + //------------------------------------------------------ + // + else if (total_collisions == 1) + { + worldLinearVelocity = resultant_velocity; + localOrigin.linearPosition = resultant_position; + damage->surfaceNormal.operator=(resultant_normal); + + // + //--------------------------------------------------------- + // Figure out the normal, and calculate the collision force + //--------------------------------------------------------- + // +Figure_Normal: + if (Small_Enough(damage->surfaceNormal.LengthSquared())) + { + damage->surfaceNormal.x = 0.0f; + damage->surfaceNormal.y = 1.0f; + damage->surfaceNormal.z = 0.0f; + } + else + { + damage->surfaceNormal.Normalize(damage->surfaceNormal); + } + MoveCollisionVolume(); + damage->damageAmount = total_damage; + damage->damageForce.Subtract(worldLinearVelocity, initial_velocity); + } + lastCollisionList = collisions; + } + else + { + lastCollisionList = NULL; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ) +{ + Check(this); + Verify(time_slice > 0.0f); + Check(&collision); + Check(&old_position); + Check_Pointer(damage); + + Scalar penetration; + + // + //------------------------------------------------------------------------ + // If we really have a collision, do a static bounce off of the normal + // generated. This is default behavior, and any derived class should make + // sure to handle any handshaking that needs to be done + //------------------------------------------------------------------------ + // + if ( + collisionVolume->ProcessCollision( + collision, + worldLinearVelocity, + lastCollisionList, + &damage->surfaceNormal, + &penetration + ) + ) + { + Max_Clamp(penetration, time_slice); + Scalar r = penetration / time_slice; + Scalar elasticity = elasticityCoefficient; + Scalar friction = frictionCoefficient; + + damage->damageAmount = + StaticBounce( + old_position, + time_slice, + r, + damage->surfaceNormal, + &elasticity, + minimumBounceSpeed, + &friction + ); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::StartCollisionAssistant() +{ + Check(this); + Verify(collisionAssistant == NULL); + + collisionAssistant = CollisionAssistant::Make(this); + Register_Object(collisionAssistant); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + Mover::StaticBounce( + const Point3D &, //old_position, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity, + Scalar bounce_min, + Scalar *friction + ) +{ + Check(this); + Check(&normal); + Check_Pointer(elasticity); + Check_Pointer(friction); + + Verify(penetration >= 0.0f && penetration <= 1.0f); + Verify(*elasticity >= 0.0f && *elasticity <= 1.0f); + Verify(*friction >= 0.0f); + Verify(delta_t > SMALL); + +// penetration = 1.0f; // HACK - should keep stuff from going through the floor + + // + //----------------------------------------------------------------------- + // Calculate the impact speed and vectors. If we didn't hit fast enough, + // don't do any bounce + //----------------------------------------------------------------------- + // + Scalar impact = worldLinearVelocity * normal; + Vector3D vn,vp; + vn.Multiply(normal, impact); + vp.Subtract(worldLinearVelocity, vn); + if (impact > 0.0f) + { + Check_Fpu(); + return 0.0f; + } + if (-impact <= bounce_min * delta_t) + { + *elasticity = 0.0f; + } + + // + //-------------------------------------- + // Calculate the energy lost to friction + //-------------------------------------- + // + Scalar resistance = vp.Length(); + if (Small_Enough(resistance)) + { + *friction = resistance = 0.0f; + } + else + { + resistance = + 1.0f + *friction * (1.0f + *elasticity) * impact / resistance; + if (resistance < 0.0f) + { + *friction = resistance = 0.0f; + } + } + + // + //---------------------------------------------------- + // Compute the velocity delta created by the collision + //---------------------------------------------------- + // + Scalar temp = resistance - 1.0f; + Vector3D delta_v; + delta_v.Multiply(worldLinearVelocity, temp); + temp = resistance + *elasticity; + delta_v.AddScaled(delta_v, vn, -temp); + + // + //------------------------------------ + // Figure out the kinetic energy stuff + //------------------------------------ + // + temp = -1.0f - *elasticity; + vn *= temp; + vp.AddScaled(vn, worldLinearVelocity, 2.0f); + + // + // Reflect the velocity vector + // + worldLinearVelocity += delta_v; + temp = penetration * delta_t; + delta_v *= temp; + localOrigin.linearPosition += delta_v; + + // + // Compute the kinetic energy loss + // + Check_Fpu(); + return -0.0005 * (vn * vp) * moverMass; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + Mover::DynamicBounce( + Mover *other, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity + ) +{ + Check(this); + Check(other); + Check(&normal); + Check_Pointer(elasticity); + + Verify(penetration >= 0.0f && penetration <= 1.0f); + Verify(*elasticity >= 0.0f && *elasticity <= 1.0f); + Verify(delta_t > SMALL); + + // + //------------------------------------------------------------------------ + // Get the relative velocity of the other guy, and figure out the velocity + // delta along the normal + //------------------------------------------------------------------------ + // + Scalar k1 = worldLinearVelocity.LengthSquared(); + Scalar k2 = other->worldLinearVelocity.LengthSquared(); + + Scalar mass_ratio = other->moverMass / (moverMass + other->moverMass); + Check_Fpu(); + Vector3D v; + v.Subtract(other->worldLinearVelocity, worldLinearVelocity); + Scalar temp = (1.0f + *elasticity) * (v*normal); + Vector3D delta_v; + delta_v.Multiply(normal, temp); + + // + //------------------------------------------------------------------------- + // Figure out the kinetic energy loss in kilojoules, and bounce the primary + // mover + // + // There was an additional multiplication by mass ratio in system 3 code... + // we should make sure it is really needed... + //------------------------------------------------------------------------- + // + v.AddScaled(delta_v, v, -2.0f); + worldLinearVelocity.AddScaled( + worldLinearVelocity, + delta_v, + mass_ratio + ); + localOrigin.linearPosition.AddScaled( + localOrigin.linearPosition, + delta_v, + delta_t * penetration + ); + + // + //---------------------------------------------------------- + // Bounce the second object, and reset it's update values... + //---------------------------------------------------------- + // + other->worldLinearVelocity.AddScaled( + other->worldLinearVelocity, + delta_v, + mass_ratio - 1.0f + ); + other->localOrigin.linearPosition.AddScaled( + other->localOrigin.linearPosition, + delta_v, + delta_t + ); + other->updateVelocity.linearMotion = other->worldLinearVelocity; + other->updateOrigin.linearPosition = other->localOrigin.linearPosition; + other->lastUpdate = Now(); + + // + //-------------------------------- + // Return the result in kilojoules + //-------------------------------- + // + k1 -= worldLinearVelocity.LengthSquared(); + k2 -= other->worldLinearVelocity.LengthSquared(); + Check_Fpu(); + return 0.0005f * mass_ratio * (moverMass * k1 + other->moverMass * k2); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::CheckAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ) +{ + Check(this); + Check(collisions); + + // + //---------------------------------------------------------------------- + // If the two movers collided against with each other, add the result to + // the collision list + //---------------------------------------------------------------------- + // + while (chain) + { + Check(chain); + ExtentBox slice; + if (chain->Intersects(*collisionVolume, &slice)) + { + Verify(collisions->GetCollisionsLeft()); + collisions->AddCollisionToList(chain, slice); + if (!collisions->GetCollisionsLeft()) + { + return; + } + } + chain = chain->GetNextSolid(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::CheckVolumeAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ) +{ + Check(this); + Check(collisions); + + // + //---------------------------------------------------------------------- + // If the two movers collided against with each other, add the result to + // the collision list + //---------------------------------------------------------------------- + // + while (chain) + { + Check(chain); + ExtentBox slice; + if (chain->Intersects(*collisionVolume, &slice)) + { + Verify(collisions->GetCollisionsLeft()); + collisions->AddCollisionToList(collisionVolume, slice); + if (!collisions->GetCollisionsLeft()) + { + return; + } + } + chain = chain->GetNextSolid(); + } + Check_Fpu(); +} + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid* + Mover::CheckLineAgainstBoxedSolidChain( + Line *line, + BoxedSolid *chain + ) +{ + Check(this); + Check(line); + + // + //---------------------------------------------------------------------- + // If the two movers collided against with each other, add the result to + // the collision list + //---------------------------------------------------------------------- + // + BoxedSolid *result = NULL; + while (chain) + { + Check(chain); + if (chain->HitBy(line)) + { + result = chain; + } + chain = chain->GetNextSolid(); + } + Check_Fpu(); + return result; +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Mover::Mover( + Mover::MakeMessage *creation_message, + Mover::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + Check_Pointer(this); + Check(creation_message); + + Check(application); + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + + // + //------------------------------ + // Initialize the motion vectors + //------------------------------ + // + localVelocity = creation_message->localVelocity; + localAcceleration = creation_message->localAcceleration; + worldLinearAcceleration.Multiply( + localAcceleration.linearMotion, + localToWorld + ); + worldLinearVelocity.Multiply( + localVelocity.linearMotion, + localToWorld + ); + + updateVelocity.linearMotion = worldLinearVelocity; + updateVelocity.angularMotion = localVelocity.linearMotion; + + updateAcceleration.linearMotion = worldLinearAcceleration; + updateAcceleration.angularMotion = localAcceleration.linearMotion; + nextUpdate = lastUpdate; + + normalizeCount = 0; + if (IsInitialStasis()) + { + SetSimulationState(StasisState); + } + + collisionVolume = NULL; + collisionTemplate = NULL; + containedByNode = NULL; + collisionLists = NULL; + lastCollisionList = NULL; + collisionAssistant = NULL; + deadReckoner = NULL; + collisionVolumeCount = 0; + + ResourceDescription *res = + res_file->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + ModelResource* model = (ModelResource*)res->resourceAddress; + Check_Pointer(model); + + moverMass = model->moverMass; + Verify(!Small_Enough(model->momentOfInertia.x)); + momentOfInertia.x = 1.0f/model->momentOfInertia.x; + Verify(!Small_Enough(model->momentOfInertia.y)); + momentOfInertia.y = 1.0f/model->momentOfInertia.y; + Verify(!Small_Enough(model->momentOfInertia.z)); + momentOfInertia.z = 1.0f/model->momentOfInertia.z; + positiveLinearDragCoefficients = model->positiveLinearDragCoefficients; + negativeLinearDragCoefficients = model->negativeLinearDragCoefficients; + angularDragCoefficients = model->angularDragCoefficients; + frictionCoefficient = model->frictionCoefficient; + elasticityCoefficient = model->elasticityCoefficient; + minimumBounceSpeed = model->minimumBounceSpeed; + + // + //-------------------------------------------------------------------- + // Read the collision information from the resource file, but for now, + // assume a VTV + //-------------------------------------------------------------------- + // + collisionLists = new BoxedSolidCollisionList[2]; + Register_Pointer(collisionLists); + res->Unlock(); + if (IsCollisionVolume()) + { + res = + res_file->SearchList( + resourceID, + ResourceDescription::BoxedSolidStreamResourceType + ); + Check(res); + res->Lock(); + + BoxedSolidResource* box = (BoxedSolidResource*)res->resourceAddress; + Check_Pointer(box); + collisionVolumeCount = res->resourceSize / sizeof(BoxedSolidResource); + + for (int i=0; iUnlock(); + MoveCollisionVolume(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->messageLength = sizeof(Mover::MakeMessage); + creation_message->classToCreate = RegisteredClass::TrivialMoverClassID; +// creation_message->instanceFlags = DefaultFlags; + creation_message->localVelocity = Motion::Identity; + creation_message->localAcceleration = Motion::Identity; + Check_Fpu(); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + Mover::CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *model_file, + const ResourceDirectories *,//directories, + ModelResource *model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + // + //----------------------------------------------------------------------- + // If we were not provided a buffer to write the model data into, we must + // create it ourselves + //----------------------------------------------------------------------- + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + // + //----------------- + // Read in the mass + //----------------- + // + if (!model_file->GetEntry("gamedata", "MoverMass", &local_model->moverMass)) + { + cerr << model_name << " missing MoverMass!\n"; +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + Check_Fpu(); + return -1; + } + + // + //------------------------------ + // Read in the moment of inertia + //------------------------------ + // + const char* entry; + if ( + !model_file->GetEntry( + "gamedata", + "MomentOfInertia", + &entry + ) + ) + { + cerr << model_name << " missing MomentOfInertia!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->momentOfInertia.x, + &local_model->momentOfInertia.y, + &local_model->momentOfInertia.z + ); + + // + //------------------------------ + // Read in the drag coefficients + //------------------------------ + // + if ( + !model_file->GetEntry( + "gamedata", + "PositiveLinearDragCoefficients", + &entry + ) + ) + { + cerr << model_name << " missing PositiveLinearDragCoefficients!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->positiveLinearDragCoefficients.x, + &local_model->positiveLinearDragCoefficients.y, + &local_model->positiveLinearDragCoefficients.z + ); + + if ( + !model_file->GetEntry( + "gamedata", + "NegativeLinearDragCoefficients", + &entry + ) + ) + { + cerr << model_name << " missing NegativeLinearDragCoefficients!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->negativeLinearDragCoefficients.x, + &local_model->negativeLinearDragCoefficients.y, + &local_model->negativeLinearDragCoefficients.z + ); + + // + //------------------------- + // Read in the angular drag + //------------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "AngularDragCoefficients", + &entry + ) + ) + { + cerr << model_name << " missing AngularDragCoefficients!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->angularDragCoefficients.x, + &local_model->angularDragCoefficients.y, + &local_model->angularDragCoefficients.z + ); + + // + //--------------------- + // Read in the friction + //--------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "FrictionCoefficient", + &local_model->frictionCoefficient + ) + ) + { + cerr << model_name << " missing FrictionCoefficient!\n"; + goto Dump_And_Die; + } + + // + //----------------------- + // Read in the elasticity + //----------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "ElasticityCoefficient", + &local_model->elasticityCoefficient + ) + ) + { + cerr << model_name << " missing ElasticityCoefficient!\n"; + goto Dump_And_Die; + } + + // + //--------------------------------- + // Read in the minimum bounce speed + //--------------------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "MinimumBounceSpeed", + &local_model->minimumBounceSpeed + ) + ) + { + cerr << model_name << " missing MinimumBounceSpeed!\n"; + goto Dump_And_Die; + } + + // + //------------------------------------------------------------------------- + // If we created the model buffer, then we have the responsibility to write + // it out to the resource file + //------------------------------------------------------------------------- + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Mover* + Mover::Make(Mover::MakeMessage *creation_message) +{ + return new Mover(creation_message, DefaultData); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Mover::~Mover() +{ + Unregister_Pointer(collisionLists); + delete[] collisionLists; + + if (IsCollisionVolume()) + { + BoxedSolid *box = collisionTemplate; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } + box = collisionVolume; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } + } + + if (collisionAssistant) + { + Unregister_Object(collisionAssistant); + delete collisionAssistant; + } + Check_Fpu(); +} + +Logical + Mover::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/MOVER.HPP b/CODE/RP/MUNGA/MOVER.HPP new file mode 100644 index 0000000..f198fba --- /dev/null +++ b/CODE/RP/MUNGA/MOVER.HPP @@ -0,0 +1,484 @@ +//===========================================================================// +// File: mover.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MOVER_HPP) +# define MOVER_HPP + +# if !defined(ENTITY_HPP) +# include +# endif + +# if !defined(MOTION_HPP) +# include +# endif + + class Mover__SharedData; + class Mover; + class CollisionAssistant; + class BoundingBoxTreeNode; + class BoxedSolid; + class BoxedSolidCollision; + class BoxedSolidCollisionList; + class Normal; + class Line; + class Environment; + + //########################################################################## + //#################### Mover::UpdateMessage ########################## + //########################################################################## + + struct Mover__UpdateRecord: + public Entity::UpdateRecord + { + public: + Motion + localVelocity, + localAcceleration; + Vector3D + worldLinearVelocity, + worldLinearAcceleration; + }; + + //########################################################################## + //##################### Mover::MakeMessage ########################## + //########################################################################## + + class Mover__MakeMessage: + public Entity::MakeMessage + { + public: + Motion + localVelocity, + localAcceleration; + + Mover__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration + ): + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + localVelocity(velocity), + localAcceleration(acceleration) + {} + Mover__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration + ): + Entity::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + localVelocity(velocity), + localAcceleration(acceleration) + {} + }; + + //########################################################################## + //##################### Mover::ModelResource ######################### + //########################################################################## + + struct Mover__ModelResource + { + Scalar moverMass; + Vector3D + momentOfInertia, + positiveLinearDragCoefficients, + negativeLinearDragCoefficients, + angularDragCoefficients; + Scalar + frictionCoefficient, + elasticityCoefficient, + minimumBounceSpeed; + }; + + //########################################################################## + //############################ Mover ################################# + //########################################################################## + + class Mover: + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + LocalVelocityAttributeID = Entity::NextAttributeID, + LocalAccelerationAttributeID, + WorldLinearVelocityAttributeID, + WorldLinearAccelerationAttributeID, + MoverMassAttributeID, + MomentOfInertiaAttributeID, + PositiveLinearDragCoefficientsAttributeID, + NegativeLinearDragCoefficientsAttributeID, + AngularDragCoefficientsAttributeID, + FrictionCoefficientAttributeID, + ElasticityCoefficientAttributeID, + MinimumBounceSpeedAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Motion + localVelocity, + localAcceleration; + Vector3D + worldLinearVelocity, + worldLinearAcceleration; + Scalar moverMass; + Vector3D + momentOfInertia, + positiveLinearDragCoefficients, + negativeLinearDragCoefficients, + angularDragCoefficients; + Scalar + frictionCoefficient, + elasticityCoefficient, + minimumBounceSpeed; + + // + // virtual access + // + public: + virtual Vector3D + GetWorldLinearVelocity() + {return worldLinearVelocity;} + virtual Vector3D + GetWorldLinearAcceleration() + {return worldLinearAcceleration;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + enum { + StasisState = Entity::StateCount, + StateCount + }; + + typedef Mover__UpdateRecord UpdateRecord; + typedef Mover__MakeMessage MakeMessage; + typedef void + (Mover::*Performance)(Scalar time_slice); + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + UpdateWorldMotion(); + void + UpdateLocalMotion(); + void + ApplyWorldAccelerations(Scalar time_slice); + void + ApplyAirResistanceAndGravity(Scalar power=1.0f); + void + CalculateDrag( + Vector3D *drag, + const Vector3D &velocity, + const Vector3D &positive_CODs, + const Vector3D &negative_CODs, + Scalar power + ); + + void + ApplyLocalForce( + const Vector3D &force, + const Vector3D &moment + ); + void + ApplyLocalAcceleration( + const Vector3D &acceleration, + const Vector3D &moment + ); + + Environment* + GetEnvironment() + {Check(this); return localEnvironment;} + + typedef Logical (Mover::*DeadReckoner)(); + void + SetDeadReckoner(DeadReckoner reckoner) + {Check(this); deadReckoner = reckoner;} + + Logical + NoDeadReckoner(); + Logical + LinearDeadReckoner(); + Logical + AcceleratedDeadReckoner(); + void + DeadReckon(Scalar time_slice); + + protected: + void + WriteUpdateRecord( + Simulation::UpdateRecord *message, + int update_model + ); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + void + PerformAndWatch( + const Time& till, + MemoryStream *update_stream + ); + + int + normalizeCount; + Environment + *localEnvironment; + DeadReckoner + deadReckoner; + Origin + projectedOrigin, + previousOrigin; + Motion + projectedVelocity, + updateAcceleration, + updateVelocity; + Time + nextUpdate; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Collision support + // + public: + virtual void + MoveCollisionVolume(); + BoundingBoxTreeNode* + GetMoverCollisionRoot() + {Check(this); return containedByNode;} + + BoxedSolidCollisionList* + AllocateCollisionList(); + BoxedSolidCollisionList* + GetCurrentCollisions(BoxedSolidCollisionList *list=NULL); + BoxedSolid* + FindBoxedSolidHitBy( + Line *line, + Entity *except_by + ); + BoxedSolidCollisionList* + CollideCenterOfMotion( + Line *line, + BoxedSolidCollisionList *list + ); + void + ProcessCollisionList( + BoxedSolidCollisionList *collisions, + Scalar time_slice, + const Point3D &old_position, + Damage *damage + ); + + Scalar + StaticBounce( + const Point3D &old_position, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity, + Scalar bounce_min, + Scalar *friction + ); + Scalar + DynamicBounce( + Mover *other, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity + ); + + BoxedSolid* + GetCollisionVolume() + {Check(this); return collisionVolume;} + BoxedSolid* + GetCollisionTemplate() + {Check(this); return collisionTemplate;} + int + GetCollisionVolumeCount() + {Check(this); return collisionVolumeCount;} + + virtual void + StartCollisionAssistant(); + + protected: + int collisionVolumeCount; + BoxedSolid + *collisionVolume, + *collisionTemplate; + BoundingBoxTreeNode *containedByNode; + BoxedSolidCollisionList + *collisionLists, + *lastCollisionList; + CollisionAssistant *collisionAssistant; + + virtual void + ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ); + + void + CheckAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ); + + public: + void + CheckVolumeAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ); + + protected: + BoxedSolid* + CheckLineAgainstBoxedSolidChain( + Line *line, + BoxedSolid *chain + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Flag Support + // + public: + enum { + NoCollisionVolumeBit = Entity::NextBit, + NoCollisionTestBit, + InitialStasisBit, + NextBit + }; + + enum { + NoCollisionVolumeFlag = 1< + +#if !defined(MTRXSTK_HPP) +# include +#endif + +AffineMatrixStack& + AffineMatrixStack::Concatenate(const AffineMatrix& matrix) +{ + AffineMatrix *old_top = Cast_Object(AffineMatrix*,Peek()); + AffineMatrix *new_top = (AffineMatrix*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +LinearMatrixStack& + LinearMatrixStack::Concatenate(const LinearMatrix& matrix) +{ + LinearMatrix *old_top = Cast_Object(LinearMatrix*,Peek()); + LinearMatrix *new_top = (LinearMatrix*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4Stack& + Matrix4x4Stack::Concatenate(const Matrix4x4& matrix) +{ + Matrix4x4 *old_top = Cast_Object(Matrix4x4*,Peek()); + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4Stack& + Matrix4x4Stack::Concatenate(const AffineMatrix& matrix) +{ + Matrix4x4 *old_top = Cast_Object(Matrix4x4*,Peek()); + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4& + Matrix4x4Stack::Push(const AffineMatrix& matrix) +{ + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + return *new_top = matrix; +} + diff --git a/CODE/RP/MUNGA/MTRXSTK.HPP b/CODE/RP/MUNGA/MTRXSTK.HPP new file mode 100644 index 0000000..5d3f647 --- /dev/null +++ b/CODE/RP/MUNGA/MTRXSTK.HPP @@ -0,0 +1,150 @@ +//===========================================================================// +// File: mtrxstk.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for the matrix class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 JMA Initial coding. // +// 12/01/94 JMA Changed Matrix to Matrix4x4, based both matrix classes on // +// Matrix44Base // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(MTRXSTK_HPP) +# define MTRXSTK_HPP + +# if !defined(MEMBLOCK_HPP) +# include +# endif + +# if !defined(MATRIX_HPP) +# include +# endif + +# if !defined(LINMTRX_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~ AffineMatrixStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AffineMatrixStack: + public MemoryStack + { + public: + AffineMatrixStack( + size_t start, + size_t delta + ): + MemoryStack(sizeof(AffineMatrix),start,delta) + {} + + AffineMatrix* + Peek() + { + Check(this); + return Cast_Object(AffineMatrix*,MemoryStack::Peek()); + } + + AffineMatrixStack& + Concatenate(const AffineMatrix& matrix); + AffineMatrixStack& + operator*=(const AffineMatrix& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + + AffineMatrix& + Push(const AffineMatrix& matrix) + { + Check(this); Check(&matrix); + return *Cast_Object(AffineMatrix*,MemoryStack::Push(&matrix)); + } + + operator AffineMatrix&() + {Check(this); return *Peek();} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~ LinearMatrixStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class LinearMatrixStack: + public MemoryStack + { + public: + LinearMatrixStack( + size_t start, + size_t delta + ): + MemoryStack(sizeof(LinearMatrix),start,delta) + {} + + LinearMatrix* + Peek() + { + Check(this); + return Cast_Object(LinearMatrix*,MemoryStack::Peek()); + } + + LinearMatrixStack& + Concatenate(const LinearMatrix& matrix); + LinearMatrixStack& + operator*=(const LinearMatrix& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + + LinearMatrix& + Push(const LinearMatrix& matrix) + { + Check(this); Check(&matrix); + return *Cast_Object(LinearMatrix*,MemoryStack::Push(&matrix)); + } + + operator LinearMatrix&() + {Check(this); return *Peek();} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ Matrix4x4Stack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Matrix4x4Stack: + public MemoryStack + { + public: + Matrix4x4Stack( + size_t start, + size_t delta + ): + MemoryStack(sizeof(Matrix4x4),start,delta) + {} + + Matrix4x4* + Peek() + { + Check(this); + return Cast_Object(Matrix4x4*,MemoryStack::Peek()); + } + + Matrix4x4Stack& + Concatenate(const Matrix4x4& matrix); + Matrix4x4Stack& + Concatenate(const AffineMatrix& matrix); + Matrix4x4Stack& + operator*=(const Matrix4x4& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + Matrix4x4Stack& + operator*=(const AffineMatrix& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + + Matrix4x4& + Push(const Matrix4x4& matrix) + { + Check(this); Check(&matrix); + return *Cast_Object(Matrix4x4*,MemoryStack::Push(&matrix)); + } + Matrix4x4& + Push(const AffineMatrix& matrix); + + operator Matrix4x4&() + {Check(this); return *Peek();} + }; + +#endif diff --git a/CODE/RP/MUNGA/MUNGA.HPP b/CODE/RP/MUNGA/MUNGA.HPP new file mode 100644 index 0000000..961d4e8 --- /dev/null +++ b/CODE/RP/MUNGA/MUNGA.HPP @@ -0,0 +1,83 @@ +#if !defined(MUNGA_HPP) +# define MUNGA_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# if defined(__BCPLUSPLUS__) +# include +# endif + +# if defined(LBE4) +# include +# else +# include +# endif + + enum { + NullExitCodeID = 0, + AbortExitCodeID + }; + +# if !defined(TRACE_HPP) +# include +# endif + +# if !defined(NO_PRECOMPILED_HEADERS) +# if !defined(CSTR_HPP) +# include +# endif + +# if !defined(NAMELIST_HPP) +# include +# endif + +# if !defined(NOTATION_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(VCHAIN_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + +# if !defined(TREE_HPP) +# include +# endif + +# if !defined(HASH_HPP) +# include +# endif + +# if !defined(ORIGIN_HPP) +# include +# endif + +# endif + +#endif diff --git a/CODE/RP/MUNGA/MUNGA.MAK b/CODE/RP/MUNGA/MUNGA.MAK new file mode 100644 index 0000000..9974bd1 --- /dev/null +++ b/CODE/RP/MUNGA/MUNGA.MAK @@ -0,0 +1,255 @@ +.autodepend +.cacheautodepend +.suffixes: .asm .cpp .c + +!ifndef BTYPE +!error BTYPE macro not supplied +!endif + +!ifndef BPATH +!error BPATH macro not supplied +!endif + +!include make.cfg +!include $(BPATH) + +!ifndef MUNGA_ROOT +!error MUNGA_ROOT macro is not defined +!endif + +TARGET_DIR = $(MUNGA_ROOT)\$(BTYPE) +TARGET_PATH = $(TARGET_DIR)\\ +.path.obj = $(TARGET_DIR) +.path.lib = $(LIBRARY_PATH) + +LIB_PREFIX = -+$(TARGET_DIR)\\ + +CFG_FILE = $(TARGET_DIR)\$(BTYPE).cfg +HEADER_FILE = munga$(BTYPE).csm + +#------------------------------------------------------------------------------ +# targets +# +all: $(CFG_FILE) $(TARGET_DIR)\testall.exe + +clean: + del $(TARGET_DIR)\*.obj + del $(TARGET_DIR)\*.lib + del $(TARGET_DIR)\*.exe + del $(TARGET_DIR)\*.bak + del $(TARGET_DIR)\*.cfg + +assemble: + @echo No assembly targets + +#------------------------------------------------------------------------------ +# Implicit rules +# +!include $(BTYPE).mak + +!ifndef STARTUP_OBJ +!error STARTUP_OBJ macro is not defined +!endif + +!ifndef STARTUP_LIBS +!error STARTUP_LIBS macro is not defined +!endif + +{$(INCLUDE_PATH)}.cpp{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(INCLUDE_PATH)}.c{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(MUNGA_ROOT)}.asm{$(TARGET_DIR)}.obj: + tasm32 -ml $(TASM_OPTIONS) -i$(MUNGA_ROOT) $<,$@ >>error.log + +#------------------------------------------------------------------------------ +# Test program +# +$(TARGET_DIR)\testall.exe:\ + $(MUNGA_ROOT)\munga.mak $(TARGET_DIR)\stub.lib $(TARGET_DIR)\munga.lib\ + testall.obj $(BTYPE).mak + tlink32 @&&| +$(LINK_OPTIONS) + +$(STARTUP_OBJ)+ +$(TARGET_DIR)\testall.obj +$<,$* +$(TARGET_DIR)\stub.lib+ +$(TARGET_DIR)\munga.lib+ +$(STARTUP_LIBS) +| >>error.log + +testall.obj: $(CFG_FILE) + +#------------------------------------------------------------------------------ +# Stub library +# +STUB_OBJS = \ + ?tracstub.obj \ + ?filestub.obj \ + ?timestub.obj + +$(STUB_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\stub.lib: $(STUB_OBJS:?=) $(MUNGA_ROOT)\munga.mak + tlib $@ $(LIB_OPTIONS) @&&| +$(STUB_OBJS:?=$(LIB_PREFIX)) +| >>error.log + +#------------------------------------------------------------------------------ +# MUNGA library +# +MUNGA_OBJS = \ + ?heap.obj \ + ?cstr.obj \ + ?memblock.obj \ + ?memreg.obj \ + ?memstrm.obj \ + ?filestrm.obj \ + ?verify.obj \ + ?namelist.obj \ + ?notation.obj \ + ?fileutil.obj \ + ?color.obj \ + ?resource.obj \ + ?scalar.obj \ + ?rect2d.obj \ + ?random.obj \ + ?angle.obj \ + ?vector3d.obj \ + ?vector4d.obj \ + ?point3d.obj \ + ?unitvec.obj \ + ?rotation.obj \ + ?motion.obj \ + ?origin.obj \ + ?affnmtrx.obj \ + ?linmtrx.obj \ + ?matrix.obj \ + ?mtrxstk.obj \ + ?spline.obj \ + ?ray.obj \ + ?line.obj \ + ?sphere.obj \ + ?normal.obj \ + ?plane.obj \ + ?extntbox.obj \ + ?bndgbox.obj \ + ?boxtree.obj \ + ?boxlist.obj \ + ?boxsolid.obj \ + ?boxsort.obj \ + ?boxsphr.obj \ + ?boxcone.obj \ + ?boxramp.obj \ + ?boxiramp.obj \ + ?boxwedge.obj \ + ?boxdisks.obj \ + ?boxtile.obj \ + ?time.obj \ + ?vdata.obj \ + ?iterator.obj \ + ?link.obj \ + ?plug.obj \ + ?objstrm.obj \ + ?socket.obj \ + ?node.obj \ + ?slot.obj \ + ?chain.obj \ + ?sfeskt.obj \ + ?srtskt.obj \ + ?schain.obj \ + ?vchain.obj \ + ?tree.obj \ + ?table.obj \ + ?hash.obj \ + ?trace.obj \ + ?receiver.obj \ + ?event.obj \ + ?evtstat.obj \ + ?cmpnnt.obj \ + ?simulate.obj \ + ?subsystm.obj \ + ?joint.obj \ + ?network.obj \ + ?damage.obj \ + ?entity.obj \ + ?entityid.obj \ + ?nttmgr.obj \ + ?entity2.obj \ + ?envirnmt.obj \ + ?mover.obj \ + ?segment.obj \ + ?jmover.obj \ + ?watcher.obj \ + ?host.obj \ + ?hostmgr.obj \ + ?console.obj \ + ?scnrole.obj \ + ?team.obj \ + ?exptbl.obj \ + ?caminst.obj \ + ?cammgr.obj \ + ?camship.obj \ + ?cammppr.obj \ + ?eyecandy.obj \ + ?player.obj \ + ?director.obj \ + ?dropzone.obj \ + ?explode.obj \ + ?terrain.obj \ + ?cultural.obj \ + ?doorfram.obj \ + ?door.obj \ + ?registry.obj \ + ?lattice.obj \ + ?intorgn.obj \ + ?collorgn.obj \ + ?interest.obj \ + ?collasst.obj \ + ?update.obj \ + ?reticle.obj \ + ?rndorgn.obj \ + ?renderer.obj \ + ?vidrend.obj \ + ?audio.obj \ + ?audent.obj \ + ?audtime.obj \ + ?audwgt.obj \ + ?audlvl.obj \ + ?audloc.obj \ + ?audcmp.obj \ + ?audsrc.obj \ + ?audmidi.obj \ + ?audseq.obj \ + ?audwthr.obj \ + ?audrend.obj \ + ?wrhous.obj \ + ?gaugmap.obj \ + ?gauge.obj \ + ?lamp.obj \ + ?gaugrend.obj \ + ?gaugalrm.obj \ + ?graph2d.obj \ + ?mode.obj \ + ?controls.obj \ + ?mission.obj \ + ?apptask.obj \ + ?app.obj \ + ?appmgr.obj \ + ?appmsg.obj \ + ?spooler.obj \ + ?icom.obj \ + ?maptool.obj \ + ?modtool.obj \ + ?animtool.obj \ + ?audtools.obj \ + ?tool.obj + +$(MUNGA_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\munga.lib: $(MUNGA_ROOT)\munga.mak $(MUNGA_OBJS:?=) + tlib $@ $(LIB_OPTIONS) @&&| +$(MUNGA_OBJS:?=$(LIB_PREFIX)) +| >>error.log diff --git a/CODE/RP/MUNGA/NAMELIST.CPP b/CODE/RP/MUNGA/NAMELIST.CPP new file mode 100644 index 0000000..4267fa6 --- /dev/null +++ b/CODE/RP/MUNGA/NAMELIST.CPP @@ -0,0 +1,475 @@ +//===========================================================================// +// File: namelist.cpp // +// Title: Definition of NameList classes. // +// Project: Munga // +// Author: Ken Olsen (based on work by J.M. Albertson) // +// Purpose: Maintains an unsorted list of strings with (void *) to // +// anything the client needs to associate with the string. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/07/94 KEO convert from Tool Architecture I. // +// 01/07/95 KEO Add ObjectNameList class. // +//---------------------------------------------------------------------------// +// Copyright (c) 1994-1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(NAMELIST_HPP) + #include +#endif + +//############################################################################# +//############## ObjectNameList ######################################### +//############################################################################# + +ObjectNameList::ObjectNameList() +{ + Check_Pointer(this); + firstEntry = lastEntry = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ObjectNameList::~ObjectNameList() +{ + Check(this); + + Entry + *next; + + while (firstEntry) + { + Check_Pointer(firstEntry); + next = firstEntry->nextEntry; + Unregister_Pointer(firstEntry); + delete firstEntry; + firstEntry = next; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + ObjectNameList::AddEntry( + const char *name, + void *data + ) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry; + + entry = (Entry *)new char[ sizeof(Entry) + strlen(name) + 1 ]; + Register_Pointer(entry); + + entry->dataReference = data; + entry->nextEntry = NULL; + + if (firstEntry) + { + Check_Pointer(lastEntry); + lastEntry->nextEntry = entry; + } + else + { + firstEntry = entry; + } + lastEntry = entry; + + entry->SetName(name); + + return entry->GetName(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void* + ObjectNameList::FindObject(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (!strcmp(entry->GetName(), name)) + { + break; + } + } + return (entry)?entry->dataReference:NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ObjectNameList::DeleteEntry(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *cur, + *prev, + *entry; + + //---------------------------------------------------- + // ***** DANGEROUS!!! see notice in namelist.hh ***** + //---------------------------------------------------- + entry = (Entry *)(name - sizeof(Entry)); + Check_Pointer(entry); + prev = NULL; + for (cur=firstEntry; cur && cur != entry; cur = cur->nextEntry) + { + Check_Pointer(cur); + prev = cur; + } + Verify(cur == entry); + if (!prev) + { + firstEntry = entry->nextEntry; + } + else + { + prev->nextEntry = entry->nextEntry; + } + if (entry == lastEntry) + { + lastEntry = prev; + } + Unregister_Pointer(entry); + delete entry; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + ObjectNameList::EntryCount() const +{ + Check(this); + + Entry + *entry = firstEntry; + int + count = 0; + + while (entry) + { + Check_Pointer(entry); + count++; + entry = entry->nextEntry; + } + return count; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + ObjectNameList::BuildSubList( + const ObjectNameList &source_list, + const char *prefix + ) +{ + Check(this); + Check(&source_list); + Check_Pointer(prefix); + + const int + length = strlen(prefix); + Entry + *entry = source_list.firstEntry; + const char + *name; + int + count = 0; + + //------------------------------------------------------ + // add entries to SubList whose name begins with prefix + //------------------------------------------------------ + while (entry) + { + Check_Pointer(entry); + name = entry->GetName(); + Check_Pointer(name); + if (!strncmp(name, prefix, length)) + { + count++; + AddEntry(name, entry->dataReference); + } + entry = entry->nextEntry; + } + //------------------------------------------- + // return number of entries added to SubList + //------------------------------------------- + return count; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ObjectNameList::TestInstance() const +{ + // nothing to check + return True; +} + +//############################################################################# +//############## ObjectNameList::Entry ################################## +//############################################################################# + +void + ObjectNameList::Entry::SetName(const char *name) +{ + Check_Pointer(this); + Check_Pointer(name); + strcpy((char *)this + sizeof(ObjectNameList::Entry), name); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile ObjectNameList__Entry *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ObjectNameList::Entry::IsName(const char *name) const +{ + Check(this); + //do not check name here + + if (name) + { + Check_Pointer(name); + return strcmp(GetName(), name) == 0; + } + else + { + return GetName() == name; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ObjectNameList::Entry::TestInstance() const +{ + // nothing to check + //do not check dataReference even if it is not NULL! + return True; +} + +//############################################################################# +//############## NameList ############################################### +//############################################################################# + +NameList::NameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList::~NameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + NameList::FindName(void *data) +{ + Check(this); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (entry->dataReference == data) + { + break; + } + } + return (entry)?entry->GetName():NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList::Entry* + NameList::FindEntry(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (!strcmp(entry->GetName(), name)) + { + break; + } + } + return entry; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList::Entry + *NameList::FindEntry(void *data) +{ + Check(this); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (entry->dataReference == data) + { + break; + } + } + return entry; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NameList::DeleteEntry(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *prev = NULL, + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (!strcmp(entry->GetName(), name)) + { + break; + } + prev = entry; + } + if (entry) + { + if (!prev) + { + firstEntry = entry->nextEntry; + } + else + { + prev->nextEntry = entry->nextEntry; + } + if (entry == lastEntry) + { + lastEntry = prev; + } + Unregister_Pointer(entry); + delete entry; + } + return; +} + +//############################################################################# +//############## AlphaNameList ########################################## +//############################################################################# + +AlphaNameList::AlphaNameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList::~AlphaNameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + AlphaNameList::AddEntry( + const char *name, + void *data + ) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry, + *next = firstEntry, + *prev = NULL; + + entry = (Entry *)new char[ sizeof(Entry) + strlen(name) + 1 ]; + Verify(entry); + Register_Pointer(entry); + + //----------------------------------- + // find location to insert new entry + //----------------------------------- + while (next) + { + Check_Pointer(next); + if (strcmp(name, next->GetName()) < 0) + { + break; + } + prev = next; + next = next->nextEntry; + } + //--------------------------------------------- + // insert new entry after prev and before next + //--------------------------------------------- + if (!next) + { + lastEntry = entry; + } + if (!prev) + { + firstEntry = entry; + } + else + { + prev->nextEntry = entry; + } + entry->dataReference = data; + entry->nextEntry = next; + entry->SetName(name); + + return entry->GetName(); +} + +//############################################################################# +//############## TestClass() ############################################ +//############################################################################# + +#if defined(TEST_CLASS) + #include "namelist.tcp" +#endif + +//############################################################################# +//############################################################################# diff --git a/CODE/RP/MUNGA/NAMELIST.HPP b/CODE/RP/MUNGA/NAMELIST.HPP new file mode 100644 index 0000000..393230b --- /dev/null +++ b/CODE/RP/MUNGA/NAMELIST.HPP @@ -0,0 +1,230 @@ +//===========================================================================// +// File: namelist.hpp // +// Title: Declaration of NameList classes. // +// Project: Munga // +// Author: Ken Olsen (based on work by J.M. Albertson) // +// Purpose: Maintains an unsorted list of strings with (void *) to // +// anything the client needs to associate with the string. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/07/94 KEO Convert from Tool Architecture I. // +// 01/07/95 KEO Add ObjectNameList class. // +// 01/25/95 KEO Move BuildSubList from NameList to ObjectNameList. // +// 02/12/95 KEO Add isempty method. // +// 02/17/95 KEO Add more get methods for entries. // +// 03/11/95 KEO Add IsName and yet more get methods for entries. // +//---------------------------------------------------------------------------// +// Copyright (c) 1994-1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(NAMELIST_HPP) + #define NAMELIST_HPP + + #if !defined(STYLE_HPP) + #include + #endif + + class ObjectNameList; + class ObjectNameList__Entry; + class NameList; + class AlphaNameList; + + //======================================================================= + // Notice: + // In using ObjectNameList class, think of AddEntry sort of like a New + // in the sense that you MUST store the (char *) it returns in the name + // field of the class you are bonding ObjectNameList to so that when you + // DeleteEntry you can pass that exact same pointer back. DeleteEntry + // does not do a find on the name you pass it. It expects to receive the + // pointer that AddEntry gave to you. + // This restriction does not exist for NameList and AlphaNameList. + //----------------------------------------------------------------------- + // Another Notice: + // NameList::Entry objects are never _constructed_ and therefore + // Check_Pointer(this) is used instead of Check(this). Also Register_ + // Pointer and Unregister_Pointer are used instead of Register_Object + // and Unregister_Object. + //======================================================================= + + //########################################################################## + //############## ObjectNameList ###################################### + //########################################################################## + + class ObjectNameList SIGNATURED + { + public: + typedef ObjectNameList__Entry Entry; + + protected: + Entry + *firstEntry, + *lastEntry; + + public: + ObjectNameList(); + virtual + ~ObjectNameList(); + + virtual const char* + AddEntry( + const char *name, + void *data + ); + void* + FindObject(const char *name); + void + DeleteEntry(const char *name); // ** DANGEROUS!! see notice above ** + int + EntryCount() const; // (implementation assumes infrequent use) + Logical + IsEmpty() const + { Check(this); return firstEntry == NULL && lastEntry == NULL; } + Entry* + GetFirstEntry() + { Check(this); return firstEntry; } + const Entry* + GetFirstEntry() const + { Check(this); return firstEntry; } + Entry* + GetLastEntry() + { Check(this); return lastEntry; } + const Entry* + GetLastEntry() const + { Check(this); return lastEntry; } + int + BuildSubList( + const ObjectNameList &source_list, + const char *prefix + ); + + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + //########################################################################## + //############## ObjectNameList::Entry ############################### + //########################################################################## + + class ObjectNameList__Entry + { + friend class ObjectNameList; + friend class NameList; + friend class AlphaNameList; + + private: + ObjectNameList::Entry + *nextEntry; + + public: + void + *dataReference; + + protected: + void + SetName(const char *name); + + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile ObjectNameList__Entry *); + #endif + + const char* + GetName() const + { + Check(this); + return &((const char *)this)[sizeof(ObjectNameList::Entry)]; + } + Logical + IsName(const char *name) const; + void* + GetObject() + { Check(this); return dataReference; } + void* + GetData() + { Check(this); return dataReference; } + const void* + GetData() const + { Check(this); return dataReference; } + char* + GetChar() + { Check(this); return (char *)dataReference; } + const char* + GetChar() const + { Check(this); return (const char *)dataReference; } + int + GetAtoi() const + { Check(this); Check_Pointer(dataReference); + return atoi((const char *)dataReference); } + long + GetAtol() const + { Check(this); Check_Pointer(dataReference); + return atol((const char *)dataReference); } + double + GetAtof() const + { Check(this); Check_Pointer(dataReference); + return atof((const char *)dataReference); } + ObjectNameList::Entry* + GetNextEntry() + { Check(this); return nextEntry; } + const ObjectNameList::Entry* + GetNextEntry() const + { Check(this); return nextEntry; } + Logical + TestInstance() const; + }; + + //########################################################################## + //############## NameList ############################################ + //########################################################################## + + class NameList: + public ObjectNameList + { + public: + NameList(); + ~NameList(); + + void* + FindData(const char *name) + { return FindObject(name); } + const char* + FindName(void *data); + Entry* + FindEntry(const char *name); + Entry* + FindEntry(void *data); + void + DeleteEntry(const char *name); // this one is searches for name + static Logical + TestClass(); + }; + + //########################################################################## + //############## AlphaNameList ####################################### + //########################################################################## + + class AlphaNameList: + public NameList + { + public: + AlphaNameList(); + ~AlphaNameList(); + + const char* + AddEntry( + const char *name, + void *data + ); + static Logical + TestClass(); + }; + + //########################################################################## + //########################################################################## +#endif diff --git a/CODE/RP/MUNGA/NAMELIST.TCP b/CODE/RP/MUNGA/NAMELIST.TCP new file mode 100644 index 0000000..963e742 --- /dev/null +++ b/CODE/RP/MUNGA/NAMELIST.TCP @@ -0,0 +1,305 @@ +//===========================================================================// +// File: namelist.tst // +// Title: Definition of NameList TestClass methods. // +// Project: Munga // +// Author: Ken Olsen // +// Purpose: Maintains an unsorted list of strings with (void *) to // +// anything the client needs to associate with the string. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 KEO Stub-out TestClass methods. // +// 02/12/95 KEO Test IsEmpty method. // +//---------------------------------------------------------------------------// +// Copyright (c) 1994, 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +//############################################################################# +//############## TestHost ############################################### +//############################################################################# + +class TestHost SIGNATURED +{ +public: + //-------------------------------------------------------------------- + // ObjectNameList is designed to bond with another class to provide + // dymanic naming of the objects represented by that class. TestHost + // provides a means of testing the functionality of ObjectNameList. + //-------------------------------------------------------------------- + const char + *name; + TestHost + *next; + static ObjectNameList + names; + + TestHost(const char *a_name); + ~TestHost(); + + Logical + TestInstance() const; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ObjectNameList + TestHost::names; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestHost::TestHost(const char *a_name) +{ + Check_Pointer(this); + Check_Pointer(a_name); + name = names.AddEntry(a_name, (void *)this); + next = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestHost::~TestHost() +{ + Check(this); + names.DeleteEntry(name); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + TestHost::TestInstance() const +{ + return True; +} + +//############################################################################# +//############## ObjectNameList::TestClass ############################## +//############################################################################# + +Logical + ObjectNameList::TestClass() +{ + DEBUG_STREAM << "Starting ObjectNameList test..." << endl; + + TestHost + *host, + *save_host; + ObjectNameList::Entry + *next_entry, + *entry, + *save_entry; + NameList + sub_list; + int + freq, + count, + i; + div_t + mod; + char + name[20], + save_name[20]; + ostrstream + stream(name, sizeof(name)); + + //---------------------- + // initialize variables + //---------------------- + save_host = NULL; + freq = TEST_CLASS / 10; + Test( freq > 1 ); + count = 0; + + //-------------------------------- + // add objects to test and delete + // a few in the process + //-------------------------------- + Test( TestHost::names.IsEmpty() ); + for (i=0; iGetObject(); + Check(host); + Check_Pointer(host->name); + Check_Pointer(entry->GetName()); + Test( host->name == entry->GetName() ); + if (!(--i)) + { + save_entry = entry; + } + entry = entry->GetNextEntry(); + } + + //-------------------------------------- + // delete middle, first and last object + //-------------------------------------- + entry = save_entry; + if (entry) + { + Check_Pointer(entry); // special case (entry is not constructed) + host = (TestHost *)entry->GetObject(); + Check(host); + Unregister_Object(host); + delete host; + count--; + } + + entry = TestHost::names.GetFirstEntry(); + if (entry) + { + Check_Pointer(entry); // special case (entry is not constructed) + host = (TestHost *)entry->GetObject(); + Check(host); + Unregister_Object(host); + delete host; + count--; + } + + entry = TestHost::names.GetLastEntry(); + if (entry) + { + Check_Pointer(entry); // special case (entry is not constructed) + host = (TestHost *)entry->GetObject(); + Check(host); + Unregister_Object(host); + delete host; + count--; + } + + //------------------------ + // add a few more objects + //------------------------ + for (i=TEST_CLASS; i0 + host = + #endif + new TestHost(name); + Register_Object(host); + count++; + } + + //----------------- + // create sub list + //----------------- + i = sub_list.BuildSubList(TestHost::names, "TEST"); + Test( i == freq ); + Test( i == sub_list.EntryCount() ); + + //----------------------------- + // check count and names again + // and delete as we go + //----------------------------- + Test( count == TestHost::names.EntryCount() ); + + entry = TestHost::names.GetFirstEntry(); + while (entry) + { + Check_Pointer(entry); // special case (entry is not constructed) + host = (TestHost *)entry->GetObject(); + Check(host); + Check_Pointer(host->name); + Check_Pointer(entry->GetName()); + Test( host->name == entry->GetName() ); + + next_entry = entry->GetNextEntry(); + if (!next_entry) + { + Test( entry == TestHost::names.GetLastEntry() ); + Test( entry == TestHost::names.GetFirstEntry() ); + } + Unregister_Object(host); + delete host; + count--; + entry = next_entry; + } + + Test( count == 0 ); + +// Tell(" ObjectNameList::TestClass() is stubbed out!\n"); + return True; +} + +//############################################################################# +//############## NameList::TestClass #################################### +//############################################################################# + +Logical + NameList::TestClass() +{ + DEBUG_STREAM << "Starting NameList test..." << endl; + + Tell(" NameList::TestClass() is stubbed out!\n"); + return False; +} + +//############################################################################# +//############## AlphaNameList::TestClass ############################### +//############################################################################# + +Logical + AlphaNameList::TestClass() +{ + DEBUG_STREAM << "Starting AlphaNameList test..." << endl; + + Tell(" AlphaNameList::TestClass() is stubbed out!\n"); + return False; +} + +//############################################################################# +//############################################################################# diff --git a/CODE/RP/MUNGA/NETWORK.HPP b/CODE/RP/MUNGA/NETWORK.HPP new file mode 100644 index 0000000..9f5a0ed --- /dev/null +++ b/CODE/RP/MUNGA/NETWORK.HPP @@ -0,0 +1,289 @@ +//===========================================================================// +// File: network.hh // +// Project: MUNGA Brick: Network Manager // +// Contents: Interface specification for network brick // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/01/94 JMA Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/03/94 ECH Changed NetworkClient to inherit from Node // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(NETWORK_HPP) +# define NETWORK_HPP + +# if !defined(RECEIVER_HPP) +# include +# endif + +# if !defined(TIME_HPP) +# include +# endif + +# if !defined(HOSTID_HPP) +# include +# endif + + class Mission; + class NetworkManager; + class NotationFile; + + // + //--------------------------------------------------- + // Support types for interest manager + //--------------------------------------------------- + // + typedef Enumeration InterestZoneID; + const InterestZoneID NullInterestZoneID = 0; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkAddress ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef LWord NetworkAddress; + + extern const NetworkAddress NullNetworkAddress; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkClient ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class NetworkPacket; + + class NetworkClient: + public Receiver + { + friend class NetworkManager; + + //########################################################################## + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //########################################################################## + // Construction and destruction support + // + public: + enum ClientID { + NetworkManagerClientID = 0, + EntityManagerClientID = 1, + HostManagerClientID = 2, + InterestManagerClientID = 3, + ApplicationClientID = 4, + ConsoleClientID = 5, + IcomManagerClientID = 6 + }; + + private: + ClientID + clientID; + + protected: + NetworkClient( + ClassID class_ID, + SharedData &virtual_data, + ClientID clientID + ); + + public: + ~NetworkClient(); + + Logical + TestInstance() const; + + //########################################################################## + // Message packet receiving + // + public: + virtual void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Network ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define NETWORKMANAGER_BUFFER_SIZE 1600 + + class NetworkManager__ReceiveEggFileMessage; + + class NetworkManager: + public NetworkClient + { + //########################################################################## + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + public: + typedef Enumeration GameID; + + const NetworkAddress& + GetAddress() + {return address;} + + NetworkManager(SharedData &shared_data); + ~NetworkManager(); + + void + SetGameID(GameID new_id) + {gameID = new_id;} + + virtual void + Send( + Message *what, + ClientID to, + HostID host_id + ); + void + Broadcast( + Message *what, + ClientID to + ); + virtual void + ExclusiveBroadcast( + Message *what, + ClientID to + ); + Logical + RoutePacket(); + virtual Logical + ExecuteBackground(); + + NetworkClient* + GetNetworkClientPointer(ClientID client_id); + + virtual void + StartConnecting(Mission *mission); + + virtual Logical + Shutdown(); + + virtual void + Marker(char *) {}; + + enum NetworkMode + { + ReliableMode, + UnreliableMode + }; + + virtual void + Mode(NetworkMode) {}; + +// protected: //GY for test only + virtual Logical + CheckBuffers(NetworkPacket*); + virtual void + RemovePacket(NetworkPacket *packet); + + GameID + gameID; + NetworkAddress + address; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + // + // Message IDs + // + enum + { + ReceiveEggFileMessageID = NetworkClient::NextMessageID, + NextMessageID + }; + + // + // Message types + // + typedef NetworkManager__ReceiveEggFileMessage + ReceiveEggFileMessage; + + // + // Message table + // + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void + ReceiveEggFileMessageHandler(ReceiveEggFileMessage* EggMessage); + + protected: + char + *eggTempBuffer; + NotationFile + *networkEggNotationFile; + long + eggTempNext; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManager messages ~~~~~~~~~~~~~~~~~~~~~~~~~ + // NetworkManager__ReceiveEggFileMessage + // NOTE: this message should be setup as variable length rather than fixing the + // size at 1000, I wasn't sure how to do this and there wasn't anyone around + // to ask at the time so I did it this way temporarily. + // + class NetworkManager__ReceiveEggFileMessage: + public Receiver__Message + { + public: + NetworkManager__ReceiveEggFileMessage( + int sequence_number, + int total_file_length, + char* notation_data, + int length + ): + Receiver__Message( + NetworkManager::ReceiveEggFileMessageID, + sizeof(NetworkManager__ReceiveEggFileMessage) + ), + sequenceNumber(sequence_number), + notationFileLength(total_file_length), + thisMessageLength(length) + {Mem_Copy(notationData,notation_data,length,sizeof(notationData));} + int + sequenceNumber; + int + notationFileLength; + int + thisMessageLength; + char + notationData[1000]; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ NetworkPacketHeader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class NetworkPacketHeader + { + public: + NetworkClient::ClientID + clientID; + NetworkManager::GameID + gameID; + HostID + fromHost; + Time + timeStamp; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkPacket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class NetworkPacket: + public NetworkPacketHeader + { + public: + Receiver::Message + messageData; + + }; + +#endif diff --git a/CODE/RP/MUNGA/NODE.CPP b/CODE/RP/MUNGA/NODE.CPP new file mode 100644 index 0000000..6c55e27 --- /dev/null +++ b/CODE/RP/MUNGA/NODE.CPP @@ -0,0 +1,52 @@ +//===========================================================================// +// File: node.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of Node class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++, moved ReleaseSocketLink into // +// the virtual data field // +// 11/08/94 ECH Made compatible with BC4.0 // +// 12/01/94 JMA Made compatible with SGI CC // +// 12/12/94 ECH Changed release handler // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(NODE_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Node ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Node::Node(ClassID class_id): + Plug(class_id) +{ +} + +Node::Node(PlugStream *stream): + Plug(stream) +{ +} + +Node::~Node() +{ +} + +void + Node::ReleaseLinkHandler(Socket*, Plug*) +{ +} + + diff --git a/CODE/RP/MUNGA/NODE.HPP b/CODE/RP/MUNGA/NODE.HPP new file mode 100644 index 0000000..9fb88a8 --- /dev/null +++ b/CODE/RP/MUNGA/NODE.HPP @@ -0,0 +1,76 @@ +//===========================================================================// +// File: node.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for base node class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff. // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/08/94 ECH Made compatible with BC4.0 // +// 11/30/94 JMA Adapted to new style conventions // +// 12/06/94 JMA Made virtual data publicly visible // +// 12/12/94 ECH Changed release handler // +// 02/16/95 ECH Removed plug commands, added node command // +// 02/16/95 ECH Removed plug commands, added node command // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(NODE_HPP) +# define NODE_HPP + +# if !defined(SOCKET_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Node ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Node: + public Plug + { + public: + // + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + // + ~Node(); + + // + //-------------------------------------------------------------------- + // ReceiveNodeCommand - Is called from plugs when sending a command + // to connected sockets + //-------------------------------------------------------------------- + // + virtual int + ReceiveNodeCommand( + NodeCommandID, // node_command + void * //info + ) + {return 0;} + + // + //-------------------------------------------------------------------- + // ReleaseLinkHandler + //-------------------------------------------------------------------- + // + virtual void + ReleaseLinkHandler(Socket*, Plug*); + + protected: + // + //-------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------- + // + Node(ClassID class_id = TrivialNodeClassID); + Node(PlugStream *stream); + }; + +#endif + diff --git a/CODE/RP/MUNGA/NORMAL.CPP b/CODE/RP/MUNGA/NORMAL.CPP new file mode 100644 index 0000000..dbc4bd3 --- /dev/null +++ b/CODE/RP/MUNGA/NORMAL.CPP @@ -0,0 +1,69 @@ +//===========================================================================// +// File: normal.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the normal class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(NORMAL_HPP) + #include +#endif + +#if !defined(AFFNMTRX_HPP) + #include +#endif + +// +//############################################################################# +//############################################################################# +// +Normal& + Normal::Multiply_Inverse( + const Normal &Source, + const AffineMatrix &M + ) +{ + Check(this); + Check(&Source); + Check(&M); + + x = Source.x*M(0,0) + Source.y*M(0,1) + Source.z*M(0,2); + y = Source.x*M(1,0) + Source.y*M(1,1) + Source.z*M(1,2); + z = Source.x*M(2,0) + Source.y*M(2,1) + Source.z*M(2,2); + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Normal& + Normal::Multiply( + const Normal &Source, + const AffineMatrix &M + ) +{ + Check(this); + Check(&Source); + Check(&M); + + AffineMatrix m; + m.Invert(M); + return Multiply_Inverse(Source,m); +} + +#if defined(TEST_CLASS) +# include "normal.tcp" +#endif + diff --git a/CODE/RP/MUNGA/NORMAL.HPP b/CODE/RP/MUNGA/NORMAL.HPP new file mode 100644 index 0000000..194a812 --- /dev/null +++ b/CODE/RP/MUNGA/NORMAL.HPP @@ -0,0 +1,116 @@ +//===========================================================================// +// File: normal.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the normal class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +// 12/01/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(NORMAL_HPP) +# define NORMAL_HPP + +# if !defined(UNITVEC_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Normal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Normal: + public UnitVector + { + public: + // + // Constructors + // + Normal() + {} + Normal( + Scalar x, + Scalar y, + Scalar z + ): + UnitVector(x,y,z) + {} + Normal(const UnitVector& v): + UnitVector(v) + {} + + // + // Assignment operators + // + Normal& + operator=(const UnitVector& v) + {UnitVector::operator=(v); return *this;} + Normal& + operator=(const Vector3D& v) + {Normalize(v); return *this;} + + // + // Math operators + // + Normal& + Negate(const Normal &v) + {Vector3D::Negate(v); return *this;} + + Scalar + operator*(const Vector3D& v) const + {return Vector3D::operator*(v);} + + Normal& Multiply( + const Normal &n, + const LinearMatrix &m + ) + {UnitVector::Multiply(n,m); return *this;} + Normal& + operator*=(const LinearMatrix &M) + {Normal src(*this); return Multiply(src,M);} + + // + // These functions will cause the vector to lose its unit length, thus + // cause any downstream verifies to fail. We have to be able to only + // normalize the normal once after all transformations if these are to + // be of any benefit, so don't use them for now + Normal& + Multiply_Inverse( + const Normal &Source, + const AffineMatrix &M + ); + Normal& + Multiply( + const Normal &Source, + const AffineMatrix &M + ); + + // + // Support functions + // + static Logical + TestClass(); + + private: + static const Normal identity; + Normal& Negate(const Vector3D &V); + Normal& Add(const Vector3D& V1,const Vector3D& V2); + Normal& operator+=(const Vector3D& V); + Normal& Subtract(const Vector3D& V1,const Vector3D& V2); + Normal& operator-=(const Vector3D& V); + Normal& Cross(const Vector3D& V1,const Vector3D& V2); + Normal& Multiply(const Vector3D& V,Scalar Scale); + Normal& operator*=(Scalar Value); + Normal& Multiply(const Vector3D& V1,const Vector3D& V2); + Normal& operator*=(const Vector3D &V); + Normal& Multiply(const Vector3D &Source, const AffineMatrix &M); + Normal& operator*=(const AffineMatrix &M); + Normal& Divide(const Vector3D& V,Scalar Scale); + Normal& operator/=(Scalar Value); + Normal& Combine(const Vector3D& V1,Scalar t1,const Vector3D& V2,Scalar t2); + }; + +#endif diff --git a/CODE/RP/MUNGA/NORMAL.TCP b/CODE/RP/MUNGA/NORMAL.TCP new file mode 100644 index 0000000..2d51150 --- /dev/null +++ b/CODE/RP/MUNGA/NORMAL.TCP @@ -0,0 +1,22 @@ +//===========================================================================// +// File: normal.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the normal class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + Normal::TestClass() +{ + DEBUG_STREAM << "Starting Normal Test...\n"; + Tell(" Normal::TestClass() is stubbed out!\n"); + return False; +} + diff --git a/CODE/RP/MUNGA/NOTATION.CPP b/CODE/RP/MUNGA/NOTATION.CPP new file mode 100644 index 0000000..328d67c --- /dev/null +++ b/CODE/RP/MUNGA/NOTATION.CPP @@ -0,0 +1,2151 @@ +//===========================================================================// +// File: notation.cpp // +// Title: Definition of NotationFile classes. // +// Project: Munga // +// Author: Ken Olsen // +// Purpose: Provide general purpose access to data stored in a formatted // +// text file. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/07/95 KEO Converted from Tool Architecture I. // +// 02/07/95 KEO Add AppendEntry methods. // +// 02/17/95 KEO Change page and entry lists to make nomenclature. // +// 03/11/95 KEO Remove all instances of strtok from class. // +// 03/24/95 KEO Add methods to read and write text in memory. // +// 03/31/95 KEO Add methods for lab only mark. // +// 05/23/95 KEO Add setpage and appendpage and allow setentry(,,null). // +// 11/11/95 KEO Add operation modes and correct small bugs. // +//---------------------------------------------------------------------------// +// Copyright (c) 1994-1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include + +#if !defined(NOTATION_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +//############################################################################# +//############## NotationFile ########################################### +//############################################################################# + +NotationFile::NotationFile( + const char *filename, + Enumeration operation_modes +) +{ + Check_Pointer(this); + //do not check filename here + + fileName = NULL; + firstNotePage = lastNotePage = NULL; + pageCount = cleanPageCount = 0; + dirtyFlag = False; + saveNotePage = NULL; + operationModes = operation_modes; + + if (filename && *filename) + { + Check_Pointer(filename); + ReadFile(filename); + } + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile::~NotationFile() +{ + Check(this); + + NotePage + *next = firstNotePage; + + if (dirtyFlag) + { + if (fileName && *fileName && !WriteFile()) + { + cerr << "NotationFile: Error writing file '" << fileName << + "' - changes lost!" << endl; + } + } + + while (next) + { + Check(next); + firstNotePage = next->nextNotePage; + Unregister_Object(next); + delete next; + next = firstNotePage; + } + if (fileName) + { + Unregister_Pointer(fileName); + delete fileName; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::PageExists(const char *pagename) +{ + // let FindNotePage() check this and pagename + + NotePage + *notepage; + + return FindNotePage(pagename, ¬epage); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::EntryCount(const char *pagename) +{ + // let FindNotePage() check this and pagename + + NotePage + *notepage; + + if (FindNotePage(pagename, ¬epage)) + { + Check(notepage); + return ((operationModes&CleanEntryListMode)?notepage->cleanNotationCount:notepage->notationCount); + } + return 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile::NotePage* + NotationFile::SetPage( + const char *pagename, + const char *comment + ) +{ + // let FindNotePage() check this and pagename + // let AppentPage() or SetComment() check comment + + NotePage + *notepage; + + SetDirty(); + if (!FindNotePage(pagename, ¬epage)) + { + notepage = AppendPage(pagename, comment); + } + else + { + notepage->SetComment(comment); + } + return notepage; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile::NotePage* + NotationFile::AppendPage( + const char *pagename, + const char *comment + ) +{ + Check(this); + Check_Pointer(pagename); + // let SetComment() check comment + + NotePage + *notepage; + + SetDirty(); + notepage = new NotePage(this); + Register_Object(notepage); + notepage->SetName(pagename, &cleanPageCount); + notepage->SetComment(comment); + AppendNotePage(notepage); + + return notepage; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + const char **contents + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(contents); + + NotePage + *notepage; + Notation + *notation; + + //--------------- + // return string + //--------------- + if (FindNotePage(pagename, ¬epage)) + { + Check(notepage); + if (notepage->FindNote(entryname, ¬ation)) + { + Check(notation); + *contents = notation->GetEntry(); + return True; + } + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + int *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //---------------- + // return integer + //---------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + *value = atoi(contents); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + Scalar *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //--------------- + // return scalar + //--------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + *value = atof(contents); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + double *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //--------------- + // return double + //--------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + *value = atof(contents); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetLogicalEntry( + const char *pagename, + const char *entryname, + Logical *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //---------------- + // return Logical + //---------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + //-------------------------------------------------------- + // these stricmp()'s must not affected by IgnoreCaseModes + //-------------------------------------------------------- + *value = (!stricmp(contents, "true") || !stricmp(contents, "yes") || atoi(contents) != 0); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + const char *contents + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + if (contents) { Check_Pointer(contents); } + + NotePage + *notepage; + Notation + *notation; + + SetDirty(); + //--------------- + // assign string + //--------------- + if (!FindNotePage(pagename, ¬epage)) + { + notepage = AppendPage(pagename); + } + notation = new Notation; + Register_Object(notation); + notation->SetName(entryname, &(notepage->cleanNotationCount)); + notation->SetEntry(contents); + notepage->UpdateNote(notation); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + int value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[12]; + ostrstream + stream(contents, sizeof(contents)); + + stream << value << ends; + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + Scalar value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[32]; + ostrstream + stream(contents, sizeof(contents)); + + stream << value << ends; + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + double value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[64]; + ostrstream + stream(contents, sizeof(contents)); + + stream << value << ends; + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetLogicalEntry( + const char *pagename, + const char *entryname, + Logical value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[6]; + ostrstream + stream(contents, sizeof(contents)); + + if (value) + { + stream << "True" << ends; + } + else + { + stream << "False" << ends; + } + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + const char *contents + ) +{ + Check(this); + Check_Pointer(pagename); + if (entryname) { Check_Pointer(entryname); } + if (contents) { Check_Pointer(contents); } + + NotePage + *notepage; + Notation + *notation; + + SetDirty(); + //--------------- + // assign string + //--------------- + if (!FindNotePage(pagename, ¬epage)) + { + notepage = AppendPage(pagename); + } + notation = new Notation; + Register_Object(notation); + notation->SetName(entryname, &(notepage->cleanNotationCount)); + notation->SetEntry(contents); + notepage->AppendNote(notation); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + int value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[12]; + ostrstream + stream(contents, sizeof(contents)); + + stream << value << ends; + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + Scalar value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[32]; + ostrstream + stream(contents, sizeof(contents)); + + stream << value << ends; + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + double value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[64]; + ostrstream + stream(contents, sizeof(contents)); + + stream << value << ends; + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendLogicalEntry( + const char *pagename, + const char *entryname, + Logical value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[6]; + ostrstream + stream(contents, sizeof(contents)); + + if (value) + { + stream << "True" << ends; + } + else + { + stream << "False" << ends; + } + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList* + NotationFile::MakeEntryList( + const char *pagename, + const char *entryname_prefix + ) +{ + Check(this); + Check_Pointer(pagename); + //do not check entryname_prefix here + + NotePage + *notepage; + + //-------------------------------------------------- + // return namelist of matching entries and contents + //-------------------------------------------------- + if (FindNotePage(pagename, ¬epage)) + { + return MakeEntryList(notepage, entryname_prefix); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList* + NotationFile::MakeEntryList( + NotePage *notepage, + const char *entryname_prefix + ) +{ + Check(this); + Check(notepage); + //do not check entryname_prefix here + + const char + *name_prefix = entryname_prefix?entryname_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + NameList + *namelist; + Notation + *notation; + const char + *name; + Logical + prefix_matches, + add_entry; + + //-------------------------------------------------- + // return namelist of matching entries and contents + //-------------------------------------------------- + namelist = new NameList; + //do not register namelist + notation = notepage->firstNotation; + while (notation) + { + Check(notation); + name = notation->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnoreEntryCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (entryname_prefix == NULL); + } + if (operationModes&CleanEntryListMode) + { + add_entry = (notation->cleanNotation && prefix_matches); + } + else if (name) + { + add_entry = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_entry = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_entry = False; + //add_entry = (prefix_matches); + } + if (add_entry) + { + if (notation->GetEntry()) + { Check_Pointer(notation->GetEntry()); } + namelist->AddEntry(name, (void *)notation->GetEntry()); + } + notation = notation->nextNotation; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList* + NotationFile::MakePageList(const char *pagename_prefix) +{ + Check(this); + //do not check pagename_prefix here + + const char + *name_prefix = pagename_prefix?pagename_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + NameList + *namelist; + NotePage + *notepage; + const char + *name; + Logical + prefix_matches, + add_page; + + //----------------------------------------------------- + // return namelist of matching pagenames and notepages + //----------------------------------------------------- + namelist = new NameList; + //do not register namelist + notepage = firstNotePage; + while (notepage) + { + Check(notepage); + name = notepage->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnorePageCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (pagename_prefix == NULL); + } + if (operationModes&CleanPageListMode) + { + add_page = (notepage->cleanPage && prefix_matches); + } + else if (name) + { + add_page = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_page = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_page = False; + //add_page = (pagename_prefix==NULL); + } + if (add_page) + { + namelist->AddEntry(name, (void *)notepage); + } + notepage = notepage->nextNotePage; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList* + NotationFile::MakeAlphaEntryList( + const char *pagename, + const char *entryname_prefix + ) +{ + Check(this); + Check_Pointer(pagename); + //do not check entryname_prefix here + + NotePage + *notepage; + + //------------------------------------------------------- + // return alphanamelist of matching entries and contents + //------------------------------------------------------- + if (FindNotePage(pagename, ¬epage)) + { + return MakeAlphaEntryList(notepage, entryname_prefix); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList* + NotationFile::MakeAlphaEntryList( + NotePage *notepage, + const char *entryname_prefix + ) +{ + Check(this); + Check(notepage); + //do not check entryname_prefix here + + const char + *name_prefix = entryname_prefix?entryname_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + AlphaNameList + *namelist; + Notation + *notation; + const char + *name; + Logical + prefix_matches, + add_entry; + + //------------------------------------------------------- + // return alphanamelist of matching entries and contents + //------------------------------------------------------- + namelist = new AlphaNameList; + //do not register namelist + notation = notepage->firstNotation; + while (notation) + { + Check(notation); + name = notation->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnoreEntryCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (entryname_prefix == NULL); + } + if (operationModes&CleanEntryListMode) + { + add_entry = (notation->cleanNotation && prefix_matches); + } + else if (name) + { + add_entry = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_entry = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_entry = False; + //add_entry = (entryname_prefix==NULL); + } + if (add_entry) + { + if (notation->GetEntry()) + { Check_Pointer(notation->GetEntry()); } + namelist->AddEntry(name, (void *)notation->GetEntry()); + } + notation = notation->nextNotation; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList* + NotationFile::MakeAlphaPageList(const char *pagename_prefix) +{ + Check(this); + //do not check pagename_prefix here + + const char + *name_prefix = pagename_prefix?pagename_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + AlphaNameList + *namelist; + NotePage + *notepage; + const char + *name; + Logical + prefix_matches, + add_page; + + //---------------------------------------------------------- + // return alphanamelist of matching pagenames and notepages + //---------------------------------------------------------- + namelist = new AlphaNameList; + //do not register namelist + notepage = firstNotePage; + while (notepage) + { + Check(notepage); + name = notepage->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnorePageCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (pagename_prefix == NULL); + } + if (operationModes&CleanPageListMode) + { + add_page = (notepage->cleanPage && prefix_matches); + } + else if (name) + { + add_page = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_page = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_page = False; + //add_page = (pagename_prefix==NULL); + } + if (add_page) + { + namelist->AddEntry(name, (void *)notepage); + } + notepage = notepage->nextNotePage; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeleteEntry( + const char *pagename, + const char *entryname + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + NotePage + *notepage; + + //--------------------------- + // if found, delete Notation + //--------------------------- + if (FindNotePage(pagename, ¬epage)) + { + Check(notepage); + SetDirty(); + notepage->DeleteNote(entryname); + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeletePage(const char *pagename) +{ + Check(this); + Check_Pointer(pagename); + + NotePage + *notepage, + *prev; + + //---------------------------- + // if found, delete Note_Page + //---------------------------- + if (FindNotePage(pagename, ¬epage, &prev)) + { + DeletePage(notepage, prev); + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::ReadFile(const char *filename) +{ + Check(this); + Check_Pointer(filename); + + ifstream + notefile(filename); + char + buffer[512]; + Logical + was_empty = IsEmpty(); + + //------------------------------- + // store first notation filename + //------------------------------- + if (!fileName) + { + fileName = new char[strlen(filename) + 1]; + Register_Pointer(fileName); + strcpy(fileName, filename); + } + + //-------------------- + // read notation file + //-------------------- + if (notefile) + { + //Dump( "--- read notation file ---" ); + + while (notefile.getline(buffer, sizeof(buffer))) + { + //------------------------------ + // process line of NotationFile + //------------------------------ + Read(buffer); + } + notefile.close(); + Read(NULL); // (reset static variable) + + //Dump( "--- end ---" ); + } + if (was_empty) + { + dirtyFlag = False; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::ReadText( + char *start, + long length + ) +{ + Check(this); + Check_Pointer(start); + + char + *stop, + *buffer; + Logical + was_empty = IsEmpty(); + + //-------------------------------- + // read notation file from memory + //-------------------------------- + stop = start + length; + while (start < stop) + { + //--------------------------------------------------------- + // this must preceed Read() which does not preserve buffer + //--------------------------------------------------------- + buffer = start; + start = strchr(buffer, '\0') + 1; + + //------------------------------ + // process line of NotationFile + //------------------------------ + Read(buffer); + } + Read(NULL); // (reset static variable) + if (was_empty) + { + dirtyFlag = False; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::WriteFile(const char *filename) +{ + Check(this); + //do not check filename + + ofstream output; + + if (filename && *filename) + { + Check_Pointer(filename); + output.open(filename); + } + else if (fileName && *fileName) + { + Check_Pointer(fileName); + output.open(fileName); + } + else + { + return False; // you tried to WriteFile with no default fileName! + } + + if (output) + { + Write(output); + output.close(); + if (filename && *filename) + { + if (fileName) + { + Unregister_Pointer(fileName); + delete fileName; + } + fileName = new char[strlen(filename) + 1]; + Register_Pointer(fileName); + strcpy(fileName, filename); + } + dirtyFlag = False; + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::SizeOfText() +{ + Check(this); + + ofstream + dummy; + + return Write(dummy, Size_Only); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::WriteText( + char *buffer, + long size + ) +{ + Check(this); + Check_Pointer(buffer); + Verify( size >= 0 ); + + ostrstream + output(buffer, size); + long + actual_size; + + if ((actual_size = Write(output, Text_Memory)) <= size) + { + dirtyFlag = False; + return actual_size; + } + + return -1L; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Abort() +{ + Check(this); + dirtyFlag = False; + this->~NotationFile(); + //this->NotationFile(); //does not compile! + *this = NotationFile(); + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeleteStandardPages() +{ + Check(this); + + NotePage + *prev = NULL, + *notepage = firstNotePage, + *next; + const char + *name; + + while (notepage) + { + Check(notepage); + next = notepage->nextNotePage; + name = notepage->pageName; + if (*name != '_' && strcmp(name, "LAB_ONLY") != 0) + { + DeletePage(notepage, prev); + } + else + { + prev = notepage; + } + notepage = next; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::MarkLabOnly() +{ + Check(this); + + if (!IsMarkedLabOnly()) + { + SetPage("LAB_ONLY","\t// this file has not been approved for release"); + AppendEntry("LAB_ONLY", NULL, (char *)NULL); // (blank line) + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendNotePage(NotePage *notepage) +{ + Check(this); + Check(notepage); + + //--------------------------------- + // append NotePage to NotationFile + //--------------------------------- + if (!lastNotePage) + { + firstNotePage = notepage; + } + else + { + Check(lastNotePage); + lastNotePage->nextNotePage = notepage; + } + lastNotePage = notepage; + lastNotePage->nextNotePage = NULL; + if (notepage->cleanPage) + { + ++cleanPageCount; + } + ++pageCount; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::FindNotePage( + const char *pagename, + NotePage **notepage + ) +{ + //----------------------------------------------------------------- + // HACK: This routine should be changed to support NULL pagename. + //----------------------------------------------------------------- + Check(this); + Check_Pointer(pagename); + Check_Pointer(notepage); + + //------------------------------------------- + // check to see if same as previous NotePage + //------------------------------------------- + if (saveNotePage && + saveNotePage->pageName && + ((operationModes&IgnorePageCaseMode && + !stricmp(saveNotePage->pageName, pagename)) || + (!(operationModes&IgnorePageCaseMode) && + !strcmp(saveNotePage->pageName, pagename)))) + { + Check(saveNotePage); + *notepage = saveNotePage; + return True; + } + else + { + //------------------------------ + // search for matching NotePage + //------------------------------ + NotePage + *notepg = firstNotePage; + + while (notepg) + { + Check(notepg); + if (notepg->pageName && + ((operationModes&IgnorePageCaseMode && + !stricmp(notepg->pageName, pagename)) || + (!(operationModes&IgnorePageCaseMode) && + !strcmp(notepg->pageName, pagename)))) + { + *notepage = saveNotePage = notepg; + return True; + } + notepg = notepg->nextNotePage; + } + } + //----------- + // not found + //----------- + *notepage = NULL; + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::FindNotePage( + const char *pagename, + NotePage **notepage, + NotePage **prevpage + ) +{ + //----------------------------------------------------------------- + // HACK: This routine should be changed to support NULL pagename. + //----------------------------------------------------------------- + Check(this); + Check_Pointer(pagename); + Check_Pointer(notepage); + Check_Pointer(prevpage); + + NotePage + *notepg = firstNotePage, + *prev = NULL; + + //------------------------------ + // search for matching NotePage + //------------------------------ + while (notepg) + { + Check(notepg); + if (notepg->pageName && + ((operationModes&IgnorePageCaseMode && + !stricmp(notepg->pageName, pagename)) || + (!(operationModes&IgnorePageCaseMode) && + !strcmp(notepg->pageName, pagename)))) + { + *notepage = notepg; + *prevpage = prev; + return True; + } + prev = notepg; + notepg = notepg->nextNotePage; + } + //----------- + // not found + //----------- + *notepage = *prevpage = NULL; + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeletePage( + NotePage *notepage, + NotePage *prev + ) +{ + Check(this); + Check(notepage); + //do not check prev here + + //--------------------------- + // remove & delete Note_Page + //--------------------------- + SetDirty(); + + if (prev) + { + Check(prev); + prev->nextNotePage = notepage->nextNotePage; + } + else + { + firstNotePage = notepage->nextNotePage; + } + if (lastNotePage == notepage) + { + lastNotePage = prev; + } + if (notepage == saveNotePage) + { + saveNotePage = NULL; + } + if (notepage->cleanPage) + { + --cleanPageCount; + } + --pageCount; + Unregister_Object(notepage); + delete notepage; + + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Read(char *buffer) +{ + Check(this); + //do not check buffer here + + static NotePage + *notepage = NULL; + Notation + *notation; + char + *token, + *entry, + *p; + Logical +// blank_line, + comment_line; + + if (!buffer) + { + //------------------------------ + // reset notepage for next read + //------------------------------ + notepage = NULL; + return; + } + Check_Pointer(buffer); + + //-------------------------------- + // find first non-blank character + //-------------------------------- + p = buffer; + while (*p == ' ' || *p == '\t') + { + ++p; + } + + //-------------------- + // begin new NotePage + //-------------------- + if (*p == '[') + { + token = p+1; + if ((p = strchr(token, ']')) != NULL) + { + *p = '\0'; + ++p; + } + notepage = AppendPage(token, p); +// cerr << "[" << notepage->GetName() << "]" << endl; // TESTING! +// notepage->Write( cerr ); // TESTING! + return; + } + + //--------------------------------- + // detect blank lines and comments + //--------------------------------- +// blank_line = (*p == '\0'); + comment_line = Comment_Line(p); + + //--------------- + // read Notation + //--------------- + token = p; + if ((p = strchr(token, '=')) != NULL) + { + *p = '\0'; + entry = ++p; +// if (*entry == '\0') +// { +// entry = NULL; +// } + } + else + { + entry = NULL; + } + if (*token == '\0') + { + token = NULL; + } + + //------------------------ + // remove trailing blanks + //------------------------ + if (token && !comment_line) + { + p = strchr(token, '\0') - 1; + while (*p == ' ' || *p == '\t') + { + *p = '\0'; + if (--p < token) + { + break; + } + } + } + + if (!notepage) + { + notepage = new NotePage(this); + Register_Object(notepage); + AppendNotePage(notepage); + } + notation = new Notation; + Register_Object(notation); + notation->SetName(token, &(notepage->cleanNotationCount)); + notation->SetEntry(entry); + notepage->AppendNote(notation); +// cerr << token << "=" << entry << endl; // TESTING! +// notation->Write( cerr ); // TESTING! +// notepage->Write( cerr ); // TESTING! + + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::Write( + ostream &stream, + WriteMode mode + ) +{ + Check(this); + + NotePage + *notepg = firstNotePage; + long + size = 0; + + while (notepg) + { + Check(notepg); + size += notepg->WriteNote(stream, mode); + notepg = notepg->nextNotePage; + } + return size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::TestInstance() const +{ + //do not Check(this); + if (fileName) { Check_Pointer(fileName); } + if (firstNotePage) { Check_Signature(firstNotePage); } + if (lastNotePage) { Check_Signature(lastNotePage); } + if (saveNotePage) { Check_Signature(saveNotePage); } + return True; +} + +//############################################################################# +//############## NotationFile::Notation ################################# +//############################################################################# + +NotationFile__Notation::~NotationFile__Notation() +{ + Check(this); + + if (notationName) + { + Check_Pointer(notationName); + Unregister_Pointer(notationName); + delete notationName; + } + if (notationEntry) + { + Check_Pointer(notationEntry); + Unregister_Pointer(notationEntry); + delete notationEntry; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Notation::SetName( + const char *entryname, + long *clean_notation_count + ) +{ + Check(this); + //do not check entryname here + Check_Pointer(clean_notation_count); + + if (notationName) + { + if (cleanNotation) + { + cleanNotation = False; + --(*clean_notation_count); + } + Check_Pointer(notationName); + Unregister_Pointer(notationName); + delete notationName; + } + if (entryname) // (do not add "&& *entryname") + { + Check_Pointer(entryname); + notationName = new char[strlen(entryname) + 1]; + Register_Pointer(notationName); + strcpy(notationName, entryname); + cleanNotation = (*notationName && !Comment_Line(notationName)); + } + else + { + notationName = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Notation::SetEntry(const char *contents) +{ + Check(this); + //do not check contents here + + if (notationEntry) + { + Check_Pointer(notationEntry); + Unregister_Pointer(notationEntry); + delete notationEntry; + } + if (contents) // (do not add "&& *contents") + { + Check_Pointer(contents); + notationEntry = new char[strlen(contents) + 1]; + Register_Pointer(notationEntry); + strcpy(notationEntry, contents); + } + else + { + notationEntry = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::Notation::WriteNotation( + ostream &stream, + NotationFile::WriteMode mode + ) const +{ + Check(this); + +// Logical +// comment_line = True; + long + size = 0; + + if (notationName) + { + Check_Pointer(notationName); + if (mode) + { + stream << notationName; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(notationName); + } +// comment_line = Comment_Line(notationName); +// if (!comment_line) +// { +// stream << "="; +// } + } + if (notationEntry) + { + Check_Pointer(notationEntry); +// if (comment_line) +// { +// stream << "="; +// } + if (mode) + { + stream << "=" << notationEntry; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(notationEntry) + 1; + } + } + if (mode == NotationFile::Disk_File) + { + stream << endl; + } + else if (mode) + { + stream << ends; + } + if (mode != NotationFile::Disk_File) + { + size += 1; + } + + return size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::Notation::TestInstance() const +{ + //do not Check(this); + if (nextNotation) { Check_Signature(nextNotation); } + if (notationName) { Check_Pointer(notationName); } + if (notationEntry) { Check_Pointer(notationEntry); } + return True; +} + +//############################################################################# +//############## NotationFile::NotePage ################################# +//############################################################################# + +NotationFile__NotePage::NotationFile__NotePage(NotationFile *notation_file) +{ + Check_Pointer(this); + Check(notation_file); + + notationFile = notation_file; + nextNotePage = NULL; + firstNotation = lastNotation = NULL; + notationCount = cleanNotationCount = 0; + pageName = pageComment = NULL; + cleanPage = False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile__NotePage::~NotationFile__NotePage() +{ + Check(this); + + NotationFile::Notation + *notation = firstNotation; + + while (notation) + { + Check(notation); + firstNotation = notation->nextNotation; + Unregister_Object(notation); + delete notation; + notation = firstNotation; + } + if (pageName) + { + Check_Pointer(pageName); + Unregister_Pointer(pageName); + delete pageName; + } + if (pageComment) + { + Check_Pointer(pageComment); + Unregister_Pointer(pageComment); + delete pageComment; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::SetName( + const char *pagename, + long *clean_page_count + ) +{ + Check(this); + //do not check pagename here + Check_Pointer(clean_page_count); + + if (pageName) + { + if (cleanPage) + { + cleanPage = False; + --(*clean_page_count); + } + Check_Pointer(pageName); + Unregister_Pointer(pageName); + delete pageName; + } + if (pagename) // (do not add "&& *pagename") + { + Check_Pointer(pagename); + pageName = new char[strlen(pagename) + 1]; + Register_Pointer(pageName); + strcpy(pageName, pagename); + cleanPage = (*pageName && (*pageName != '!') && strcmp(pageName, "LAB_ONLY")); + } + else + { + pageName = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::SetComment(const char *comment) +{ + Check(this); + //do not check comment here + + if (pageComment) + { + Check_Pointer(pageComment); + Unregister_Pointer(pageComment); + delete pageComment; + } + if (comment && *comment) + { + Check_Pointer(comment); + pageComment = new char[strlen(comment) + 1]; + Register_Pointer(pageComment); + strcpy(pageComment, comment); + } + else + { + pageComment = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::AppendNote(NotationFile::Notation *note) +{ + Check(this); + Check(note); + + //----------------------------- + // append Notation to NotePage + //----------------------------- + if (!lastNotation) + { + firstNotation = note; + } + else + { + Check(lastNotation); + lastNotation->nextNotation = note; + } + lastNotation = note; + lastNotation->nextNotation = NULL; + if (note->cleanNotation) + { + ++cleanNotationCount; + } + ++notationCount; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::NotePage::FindNote( + const char *entryname, + NotationFile::Notation **note + ) +{ + NotationFile::Notation + *prev; + + return FindNote(entryname, note, &prev); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::NotePage::FindNote( + const char *entryname, + NotationFile::Notation **note, + NotationFile::Notation **prev + ) +{ + //------------------------------------------------------------------ + // HACK: This routine should be changed to support NULL entryname. + //------------------------------------------------------------------ + Check(this); + Check_Pointer(entryname); + Check_Pointer(note); + Check_Pointer(prev); + + NotationFile::Notation + *notation = firstNotation, + *previous = NULL; + + //------------------------------ + // search for matching Notation + //------------------------------ + while (notation) + { + Check(notation); + if (notation->notationName && + ((notationFile->operationModes&NotationFile::IgnoreEntryCaseMode && + !stricmp(notation->notationName, entryname)) || + (!(notationFile->operationModes&NotationFile::IgnoreEntryCaseMode) && + !strcmp(notation->notationName, entryname)))) + { + *note = notation; + *prev = previous; + return True; + } + previous = notation; + notation = notation->nextNotation; + } + //----------- + // not found + //----------- + *note = *prev = NULL; + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::UpdateNote(NotationFile::Notation *note) +{ + Check(this); + Check(note); + + NotationFile::Notation + *notation, + *prev; + + //------------------------------ + // search for matching Notation + //------------------------------ + if (FindNote(note->notationName, ¬ation, &prev)) + { + Check(notation); + + //------------------ + // replace Notation + //------------------ + if (prev) + { + Check(prev); + prev->nextNotation = note; + } + else + { + firstNotation = note; + } + if ((note->nextNotation = notation->nextNotation) == NULL) + { + lastNotation = note; + } + Unregister_Object(notation); + delete notation; + } + else + { + //----------------- + // append Notation + //----------------- + AppendNote(note); + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::DeleteNote(const char *entryname) +{ + Check(this); + Check_Pointer(entryname); + + NotationFile::Notation + *notation, + *prev; + + //------------------------------ + // search for matching Notation + //------------------------------ + if (FindNote(entryname, ¬ation, &prev)) + { + Check(notation); + + //-------------------------- + // remove & delete Notation + //-------------------------- + if (prev) + { + Check(prev); + prev->nextNotation = notation->nextNotation; + } + else + { + firstNotation = notation->nextNotation; + } + if (lastNotation == notation) + { + lastNotation = prev; + } + if (notation->cleanNotation) + { + --cleanNotationCount; + } + --notationCount; + Unregister_Object(notation); + delete notation; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::NotePage::WriteNote( + ostream &stream, + NotationFile::WriteMode mode + ) const +{ + Check(this); + + NotationFile::Notation + *notation = firstNotation; + long + size = 0; + + if (pageName) + { + Check_Pointer(pageName); + if (mode) + { + stream << "[" << pageName << "]"; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(pageName) + 2; + } + } + if (pageComment) + { + Check_Pointer(pageComment); + if (mode) + { + stream << pageComment; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(pageComment); + } + } + if (pageName || pageComment) + { + if (mode == NotationFile::Disk_File) + { + stream << endl; + } + else if (mode) + { + stream << ends; + } + if (mode != NotationFile::Disk_File) + { + size += 1; + } + } + while (notation) + { + Check(notation); + size += notation->WriteNotation(stream, mode); + notation = notation->nextNotation; + } + return size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::NotePage::TestInstance() const +{ + //do not Check(this); + if (nextNotePage) { Check_Signature(nextNotePage); } + if (firstNotation) { Check_Signature(firstNotation); } + if (lastNotation) { Check_Signature(lastNotation); } + if (pageName) { Check_Pointer(pageName); } + return True; +} + +//############################################################################# +//############## TestClass() ############################################ +//############################################################################# + +#if defined(TEST_CLASS) + #include "notation.tcp" +#endif + +//===========================================================================// diff --git a/CODE/RP/MUNGA/NOTATION.HPP b/CODE/RP/MUNGA/NOTATION.HPP new file mode 100644 index 0000000..08a518c --- /dev/null +++ b/CODE/RP/MUNGA/NOTATION.HPP @@ -0,0 +1,511 @@ +//===========================================================================// +// File: notation.hpp // +// Title: Declaration of NotationFile classes. // +// Project: Munga // +// Author: Ken Olsen // +// Purpose: Provide general purpose access to data stored in a formatted // +// text file. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 KEO Converted from Tool Architecture I. // +// 02/07/95 KEO Add AppendEntry methods. // +// 02/17/95 KEO Change page and entry lists to make nomenclature. // +// 03/24/95 KEO Add methods to read and write text in memory. // +// 03/31/95 KEO Add methods for lab only mark. // +// 05/23/95 KEO Add getfilename, setpage and appendpage. // +// 11/11/95 KEO Add operation modes and correct small bugs. // +//---------------------------------------------------------------------------// +// Copyright (c) 1994-1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(NOTATION_HPP) + #define NOTATION_HPP + + #if !defined(NAMELIST_HPP) && 0 + #include + #endif + + #if !defined(SCALAR_HPP) + #include + #endif + + class NotationFile; + class NotationFile__Notation; + class NotationFile__NotePage; + class NameList; + class AlphaNameList; + + //======================================================================= + // Format of notation file: + // + // ; comment (preserved) + // + // [RecordName] // comment + // FieldName=FieldData + // Field2Name=Field2Data + // + // [Record2Name] + // FieldName=FieldData + // Field3Name=Field2Data + // + // ... + // + //======================================================================= + + //########################################################################## + //############## Miscellaneous Functions ############################# + //########################################################################## + + inline Logical + Comment_Line(const char *p) + {return ((*p == ';') || (*p == '#') || (*p == '/' && *(p+1) == '/'));} + + //########################################################################## + //############## NotationFile ######################################## + //########################################################################## + + class NotationFile SIGNATURED + { + friend class NotationFile__NotePage; + friend class NotationFile__Notation; + + public: + typedef NotationFile__Notation Notation; + typedef NotationFile__NotePage NotePage; + + private: + //--------------------- + // private member data + //--------------------- + char + *fileName; + NotePage + *firstNotePage, + *lastNotePage; + long + pageCount, + cleanPageCount; + Logical + dirtyFlag; + NotePage + *saveNotePage; + Enumeration + operationModes; + + enum WriteMode + { + //-------------------------------------------- + // NOTE: These numbers are not arbitrary! + // See code before changing or adding values. + //-------------------------------------------- + Size_Only = 0, + Disk_File = 1, + Text_Memory = 2, + Binary_Memory = 3 // not implemented yet + }; + + public: + +#if 0 + enum Mode + { + // Access Modes: + EXCLUSIVE = 0, + SHARED = 1, + // Error Modes: + QUIET = 0, + FATAL = 2, + // Default Modes: + DEFAULT = (EXCLUSIVE | QUIET) + }; +#endif + + enum OperationModes + { + RawOperationModes = 0x0000, + SkipBlanksListMode = 0x0001, + CleanPageListMode = 0x0002, + CleanEntryListMode = 0x0004, + IgnorePageCaseMode = 0x0008, + IgnoreEntryCaseMode = 0x0010, + DefaultOperationModes = (SkipBlanksListMode), + CleanListMode = (CleanPageListMode | CleanEntryListMode), + IgnoreCaseMode = (IgnorePageCaseMode | IgnoreEntryCaseMode), + RelaxedOperationModes = (CleanListMode | IgnoreCaseMode) + }; + + //------------------------- + // public member functions + //------------------------- + NotationFile( + const char *filename = NULL, + Enumeration operation_modes = DefaultOperationModes + ); + + ~NotationFile(); + + Enumeration + GetModes() + { Check(this); return operationModes; } + Enumeration + PutModes(Enumeration operation_modes) + { Check(this); return (operationModes = operation_modes); } + Enumeration + SetMode(Enumeration operation_modes) + { Check(this); return (operationModes |= operation_modes); } + Enumeration + ClearMode(Enumeration operation_modes) + { Check(this); return (operationModes &= ~operation_modes); } + Logical + IsDirty() const + { Check(this); return dirtyFlag; } + Logical + IsEmpty() const + { Check(this); return (pageCount == 0L); } + const char* + GetFileName() const + { Check(this); return fileName; } + long + PageCount() const + { Check(this); return ((operationModes&CleanPageListMode)?cleanPageCount:pageCount); } + Logical + PageExists(const char *pagename); + long + EntryCount(const char *pagename); + + NotePage* + SetPage( + const char *pagename, + const char *comment = NULL + ); + NotePage* + AppendPage( + const char *pagename, + const char *comment = NULL + ); + + int + GetEntry( + const char *pagename, + const char *entryname, + const char **contents + ); + int + GetEntry( + const char *pagename, + const char *entryname, + int *value + ); + int + GetEntry( + const char *pagename, + const char *entryname, + Scalar *value + ); + int + GetEntry( + const char *pagename, + const char *entryname, + double *value + ); + int + GetLogicalEntry( + const char *pagename, + const char *entryname, + Logical *value + ); + + void + SetEntry( + const char *pagename, + const char *entryname, + const char *contents + ); + void + SetEntry( + const char *pagename, + const char *entryname, + int value + ); + void + SetEntry( + const char *pagename, + const char *entryname, + Scalar value + ); + void + SetEntry( + const char *pagename, + const char *entryname, + double value + ); + void + SetLogicalEntry( + const char *pagename, + const char *entryname, + Logical value + ); + + void + AppendEntry( + const char *pagename, + const char *entryname, + const char *contents + ); + void + AppendEntry( + const char *pagename, + const char *entryname, + int value + ); + void + AppendEntry( + const char *pagename, + const char *entryname, + Scalar value + ); + void + AppendEntry( + const char *pagename, + const char *entryname, + double value + ); + void + AppendLogicalEntry( + const char *pagename, + const char *entryname, + Logical value + ); + + NameList* + MakeEntryList( + const char *pagename, + const char *entryname_prefix = NULL + ); + NameList* + MakeEntryList( + NotationFile::NotePage *notepage, + const char *entryname_prefix = NULL + ); + NameList* + MakePageList(const char *pagename_prefix = NULL); + + AlphaNameList* + MakeAlphaEntryList( + const char *pagename, + const char *entryname_prefix = NULL + ); + AlphaNameList* + MakeAlphaEntryList( + NotationFile::NotePage *notepage, + const char *entryname_prefix = NULL + ); + AlphaNameList* + MakeAlphaPageList(const char *pagename_prefix = NULL); + + void + DeleteEntry( + const char *pagename, + const char *entryname + ); + void + DeletePage(const char *pagename); + void + ReadFile(const char *filename); + void + ReadText( + char *start, // memory is corrupted during processing + long length + ); + Logical + WriteFile(const char *filename = NULL); + long + SizeOfText(); + long + WriteText( + char *buffer, + long size + ); + void + Abort(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // remove all pages except those beginning with "_" and [LAB_ONLY] + void + DeleteStandardPages(); + void + MarkLabOnly(); + Logical + IsMarkedLabOnly() + { Check(this); return PageExists("LAB_ONLY"); } + + private: + //-------------------------- + // private member functions + //-------------------------- + void + AppendNotePage(NotePage *notepage); + Logical + FindNotePage( + const char *pagename, + NotePage **notepage + ); + Logical + FindNotePage( + const char *pagename, + NotePage **notepage, + NotePage **prevpage + ); + void + SetDirty() + { Check(this); dirtyFlag = True; } + void + DeletePage( + NotePage *notepage, + NotePage *prev + ); + void + Read(char *buffer); + long + Write( + ostream &stream, + WriteMode mode = Disk_File + ); + + public: + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + //########################################################################## + //############## NotationFile::Notation ############################## + //########################################################################## + + class NotationFile__Notation SIGNATURED + { + friend class NotationFile; + friend class NotationFile__NotePage; + + private: + //--------------------- + // private member data + //--------------------- + NotationFile::Notation + *nextNotation; + char + *notationName, + *notationEntry; + Logical + cleanNotation; + + //-------------------------- + // private member functions + //-------------------------- + NotationFile__Notation() + { + nextNotation = NULL; + notationName = notationEntry = NULL; + cleanNotation = False; + } + ~NotationFile__Notation(); + + void + SetName( + const char *entryname, + long *clean_notation_count + ); + void + SetEntry(const char *contents); + const char* + GetName() const + { Check(this); return notationName; } + const char* + GetEntry() const + { Check(this); return notationEntry; } + long + WriteNotation( + ostream &stream, + NotationFile::WriteMode mode + ) const; + Logical + TestInstance() const; + }; + + //########################################################################## + //############## NotationFile::NotePage ############################## + //########################################################################## + + class NotationFile__NotePage SIGNATURED + { + friend class NotationFile; + + private: + //--------------------- + // private member data + //--------------------- + NotationFile + *notationFile; + NotationFile::NotePage + *nextNotePage; + NotationFile::Notation + *firstNotation, + *lastNotation; + long + notationCount, + cleanNotationCount; + char + *pageName, + *pageComment; + Logical + cleanPage; + + //-------------------------- + // private member functions + //-------------------------- + NotationFile__NotePage(NotationFile *notation_file); + ~NotationFile__NotePage(); + + void + SetName( + const char *pagename, + long *clean_page_count + ); + void + SetComment(const char *comment); + const char* + GetName() const + { Check(this); return pageName; } + void + AppendNote(NotationFile::Notation *note); + Logical + FindNote( + const char *entryname, + NotationFile::Notation **note + ); + Logical + FindNote( + const char *entryname, + NotationFile::Notation **note, + NotationFile::Notation **prev + ); + void + UpdateNote(NotationFile::Notation *note); + void + DeleteNote(const char *entryname); + long + WriteNote( + ostream &stream, + NotationFile::WriteMode mode + ) const; + Logical + TestInstance() const; + }; + +#endif + +//===========================================================================// diff --git a/CODE/RP/MUNGA/NOTATION.TCP b/CODE/RP/MUNGA/NOTATION.TCP new file mode 100644 index 0000000..f1da047 --- /dev/null +++ b/CODE/RP/MUNGA/NOTATION.TCP @@ -0,0 +1,450 @@ +//===========================================================================// +// File: notation.tcp // +// Title: Definition of NotationFile TestClass methods. // +// Project: Munga // +// Author: Ken Olsen // +// Purpose: Provide general purpose access to data stored in a formatted // +// text file. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/07/95 KEO Stub-out TestClass method. // +// 02/07/95 KEO Add AppendEntry methods. // +// 02/17/95 KEO Change page and entry lists to make nomenclature. // +// 03/24/95 KEO Add tests for new in-memory read and write methods. // +// 03/31/95 KEO Add tests for lab only methods. // +// 11/11/95 KEO Correct and improve testing. // +//---------------------------------------------------------------------------// +// Copyright (c) 1994, 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +//############################################################################# +//############## NotationFile::TestClass ################################ +//############################################################################# + +Logical + NotationFile::TestClass() +{ + DEBUG_STREAM << "Starting NotationFile test..." << endl; + +#if 0 + ofstream + output; + + if (output.open(TEST_FILENAME)) + { + //------------------------------ + // write out test notation file + //------------------------------ + output << + endl << + "; this is a comment" << endl << + endl << + "[header]" << endl; + + + } + else + { + cerr << "NotationFile: ERROR - Could not open test file." << endl; + return False; + } +#endif + + const char + *test_filename = "notation.ini", + *lab_only = "LAB_ONLY", + *page_1 = "Page 1", + *page_2 = "Page 2", + *page_3 = "Page 3", +// *page_4 = "Page 4", + *page_5 = "Page 5", +// *page_6 = "Page 6", + *page_7 = "Page 7", + *page_8 = "Page 8", + *_page9 = "_Page9", + *entry_1 = "Entry 1", + *entry_2 = "Entry 2", + *entry_3 = "Entry 3", + *entry_4 = "Entry 4", + *entry_5 = "Entry 5", + *entry_6 = "Entry 6", + *entry_7 = "Entry 7", +// *entry_8 = "Entry 8", + *entry_9 = "Entry 9", + *text_a = "Text Line A", + *text_b = "Text Line B", + *text_c = "Text Line C", + *text_i = "-35", + *text_s = "3.1415", + *text_d = "1.99d+199", + *text_t = "yes", + *text_f = "no"; + + NotationFile + *ini_file; + char + *buffer; + long + size, + actual_size; + const char + *string_value; + int + count, + integer_value; + Scalar + scalar_value; + double + double_value; + Logical + logical_value; + NameList + *name_list; + AlphaNameList + *alpha_name_list; + NameList::Entry + *page, + *prev, + *entry; + + //---------------------------------------- + // test NotationFile part 1 - create file + //---------------------------------------- + ini_file = new NotationFile; + Register_Object(ini_file); + Test( ini_file->GetModes() == DefaultOperationModes ); + Test( ini_file->IsEmpty() ); + Test( !ini_file->IsDirty() ); + Test( !ini_file->IsMarkedLabOnly() ); + + Test( ini_file->PageCount() == 0 ); + name_list = ini_file->MakePageList(); + Register_Object(name_list); + Test( name_list->EntryCount() == 0 ); + Unregister_Object(name_list); + delete name_list; + + alpha_name_list = ini_file->MakeAlphaPageList(); + Register_Object(alpha_name_list); + Test( alpha_name_list->EntryCount() == 0 ); + Unregister_Object(alpha_name_list); + delete alpha_name_list; + + ini_file->MarkLabOnly(); + Test( !ini_file->IsEmpty() ); + Test( ini_file->IsDirty() ); +// Test( ini_file->WriteFile("notation.ini.tst") ); // EDO_DEBUG + Test( ini_file->IsMarkedLabOnly() ); + Test( ini_file->PutModes(RelaxedOperationModes) == RelaxedOperationModes) + Test( ini_file->PageCount() == 0 ); + Test( ini_file->ClearMode(RelaxedOperationModes) == RawOperationModes) + Test( ini_file->SetMode(DefaultOperationModes) == DefaultOperationModes) + Test_And_Dump( ini_file->PageCount() == 1, ini_file->PageCount() ); + + Test( ini_file->PageCount() == 1 ); + name_list = ini_file->MakePageList(); + Register_Object(name_list); + Test( name_list->EntryCount() == 1 ); + page = name_list->GetFirstEntry(); + Test( page == name_list->GetLastEntry() ); + Test( !strcmp(page->GetName(), lab_only) ); + Unregister_Object(name_list); + delete name_list; + + alpha_name_list = ini_file->MakeAlphaPageList(); + Register_Object(alpha_name_list); + Test( alpha_name_list->EntryCount() == 1 ); + page = alpha_name_list->GetFirstEntry(); + Test( page == alpha_name_list->GetLastEntry() ); + Test( !strcmp(page->GetName(), lab_only) ); + Unregister_Object(alpha_name_list); + delete alpha_name_list; + + ini_file->SetEntry(page_2, entry_4, text_a); + + Test( !ini_file->GetEntry(page_1, entry_1, &string_value) ); + Test( !ini_file->GetEntry(page_2, entry_2, &string_value) ); + Test( ini_file->GetEntry(page_2, entry_4, &string_value) ); + Test( !strcmp(string_value, text_a) ); + + ini_file->SetEntry(page_2, entry_2, text_s); + ini_file->SetEntry(page_1, entry_5, text_i); + ini_file->SetEntry(_page9, entry_6, text_b); + ini_file->SetPage(page_8, "\t// this is page_8"); + ini_file->SetEntry(page_2, entry_3, text_d); + ini_file->SetEntry(page_1, entry_4, text_b); + ini_file->SetEntry(_page9, entry_5, (int)True); + ini_file->SetEntry(page_8, entry_3, text_c); + ini_file->SetEntry(page_5, entry_5, text_a); + ini_file->SetLogicalEntry(_page9, entry_2, False); + ini_file->DeleteEntry(page_7, entry_7); + ini_file->DeleteEntry(page_8, entry_1); + ini_file->DeleteEntry(page_1, entry_5); + ini_file->SetEntry(_page9, entry_1, text_t); + ini_file->SetEntry(page_2, entry_3, text_c); + ini_file->SetEntry(page_1, entry_1, text_i); + ini_file->AppendEntry(page_5, entry_5, text_b); + ini_file->SetEntry(_page9, entry_3, text_f); + ini_file->SetEntry(page_8, entry_1, text_d); + ini_file->SetEntry(page_1, entry_9, text_s); + ini_file->AppendLogicalEntry(_page9, entry_9, True); + ini_file->SetEntry(page_8, entry_2, text_i); + ini_file->SetEntry(_page9, entry_4, (int)False); + + // notation file should look like this: + // (lab_only, NULL, NULL) + // (page_2, entry_4, text_a) + // (page_2, entry_2, text_s) + // (page_2, entry_3, text_c) + // (page_1, entry_4, text_b) + // (page_1, entry_1, text_i) + // (page_1, entry_9, text_s) + // (_page9, entry_6, text_b) + // (_page9, entry_5, 1) + // (_page9, entry_2, False) + // (_page9, entry_1, text_t) + // (_page9, entry_3, text_f) + // (_page9, entry_9, True) + // (_page9, entry_4, 0) + // (page_8, entry_3, text_c) + // (page_8, entry_1, text_d) + // (page_8, entry_2, text_i) + // (page_5, entry_5, text_a) + // (page_5, entry_5, text_b) + + Test_And_Dump( ini_file->EntryCount(page_1) == 3, ini_file->EntryCount(page_1) ); + name_list = ini_file->MakeEntryList(page_1); + Register_Object(name_list); + Test( name_list->EntryCount() == 3 ); + count = 0; + prev = NULL; + entry = name_list->GetFirstEntry(); + while (entry) + { + count++; + prev = entry; + entry = entry->GetNextEntry(); + } + Test( count == 3 ); + Test( (entry = prev) != NULL); + Test( entry == name_list->GetLastEntry() ); + Test( !strcmp(entry->GetName(), entry_9) ); + Test( !strcmp((char *)entry->dataReference, text_s) ); + Unregister_Object(name_list); + delete name_list; + + alpha_name_list = ini_file->MakeAlphaEntryList(page_8); + Register_Object(alpha_name_list); + Test( alpha_name_list->EntryCount() == 3 ); + count = 0; + prev = NULL; + entry = alpha_name_list->GetFirstEntry(); + while (entry) + { + count++; + prev = entry; + entry = entry->GetNextEntry(); + } + Test( count == 3 ); + Test( (entry = prev) != NULL); + Test( entry == alpha_name_list->GetLastEntry() ); + Test( !strcmp(entry->GetName(), entry_3) ); + Test( !strcmp((char *)entry->dataReference, text_c) ); + Unregister_Object(alpha_name_list); + delete alpha_name_list; + + Test( ini_file->SetMode(IgnorePageCaseMode) == (DefaultOperationModes|IgnorePageCaseMode) ); + Test( ini_file->PageExists("_pAgE9") ); + name_list = ini_file->MakePageList("pAgE"); + Register_Object(name_list); + Test( ini_file->PutModes(DefaultOperationModes) == DefaultOperationModes ); + Test( name_list->EntryCount() == 4 ); + page = name_list->GetFirstEntry(); + page = page->GetNextEntry(); + page = page->GetNextEntry(); + page = page->GetNextEntry(); + Test( page == name_list->GetLastEntry() ); + Test( !strcmp(page->GetName(), page_5) ); + Unregister_Object(name_list); + delete name_list; + + Test( !ini_file->WriteFile() ); + Test( ini_file->WriteFile(test_filename) ); + Test( !ini_file->IsDirty() ); + Unregister_Object(ini_file); + delete ini_file; + + //--------------------------------------- + // test NotationFile part 2 - check file + //--------------------------------------- + + // notation file should look like this: + // (lab_only, NULL, NULL) + // (page_2, entry_4, text_a) + // (page_2, entry_2, text_s) + // (page_2, entry_3, text_c) + // (page_1, entry_4, text_b) + // (page_1, entry_1, text_i) + // (page_1, entry_9, text_s) + // (_page9, entry_6, text_b) + // (_page9, entry_5, 1) + // (_page9, entry_2, False) + // (_page9, entry_1, text_t) + // (_page9, entry_3, text_f) + // (_page9, entry_9, True) + // (_page9, entry_4, 0) + // (page_8, entry_3, text_c) + // (page_8, entry_1, text_d) + // (page_8, entry_2, text_i) + // (page_5, entry_5, text_a) + // (page_5, entry_5, text_b) + + ini_file = new NotationFile(test_filename); + Register_Object(ini_file); + + ini_file->MarkLabOnly(); + Test( !ini_file->IsDirty() ); +// Test( ini_file->WriteFile("notation.ini.tst") ); // EDO_DEBUG + Test_And_Dump( ini_file->PageCount() == 6, ini_file->PageCount() ); + Test( ini_file->SetMode(CleanPageListMode) == (DefaultOperationModes|CleanPageListMode) ); + Test_And_Dump( ini_file->PageCount() == 5, ini_file->PageCount() ); + Test( ini_file->ClearMode(CleanPageListMode) == DefaultOperationModes ); + Test_And_Dump( ini_file->EntryCount(page_2) == 3, ini_file->EntryCount(page_2) ); + Test_And_Dump( ini_file->EntryCount(page_1) == 3, ini_file->EntryCount(page_1) ); + Test_And_Dump( ini_file->EntryCount(_page9) == 7, ini_file->EntryCount(_page9) ); + Test_And_Dump( ini_file->EntryCount(page_8) == 3, ini_file->EntryCount(page_8) ); + Test_And_Dump( ini_file->EntryCount(page_5) == 2, ini_file->EntryCount(page_5) ); + + name_list = ini_file->MakePageList(); + Register_Object(name_list); + Test( name_list->EntryCount() == 6 ); + entry = name_list->GetLastEntry(); + Test( !strcmp(entry->GetName(), page_5) ); + Unregister_Object(name_list); + delete name_list; + + //----------------- + // write to memory + //----------------- + size = ini_file->SizeOfText(); + Test( size > 10L ); + buffer = new char[size]; + Register_Pointer(buffer); + actual_size = ini_file->WriteText(buffer, 10L); + Test( actual_size == -1L ); + actual_size = ini_file->WriteText(buffer, size); + Test( actual_size == size ); + Unregister_Object(ini_file); + delete ini_file; + + //------------------ + // read from memory + //------------------ + ini_file = new NotationFile(); + Register_Object(ini_file); + + ini_file->ReadText(buffer, size); +// Test( ini_file->WriteFile("notation.ini.tst") ); // EDO_DEBUG + Unregister_Pointer(buffer); + delete buffer; + + Test( ini_file->IsMarkedLabOnly() ); + Test( ini_file->PageCount() == 6 ); + alpha_name_list = ini_file->MakeAlphaPageList(); + Register_Object(alpha_name_list); + Test( alpha_name_list->EntryCount() == 6 ); + entry = alpha_name_list->GetLastEntry(); + Test( !strcmp(entry->GetName(), _page9) ); + Unregister_Object(alpha_name_list); + delete alpha_name_list; + + name_list = ini_file->MakeEntryList(page_5); + Register_Object(name_list); + Test_And_Dump( ini_file->EntryCount(page_5) == 2, ini_file->EntryCount(page_5) ); + Test_And_Dump( name_list->EntryCount() == 2, name_list->EntryCount() ); + entry = name_list->GetFirstEntry(); + Test_And_Dump( !strcmp(entry->GetName(), entry_5), entry->GetName() ); + Test( !strcmp((char *)entry->dataReference, text_a) ); + entry = name_list->GetLastEntry(); + Test( !strcmp(entry->GetName(), entry_5) ); + Test( !strcmp((char *)entry->dataReference, text_b) ); + Unregister_Object(name_list); + delete name_list; + + Test( !ini_file->GetEntry(page_3, entry_2, &integer_value) ); + Test( !ini_file->GetEntry(page_2, entry_5, &scalar_value) ); + Test( ini_file->GetEntry(page_8, entry_1, &double_value) ); + Test( (fabs(double_value - atof(text_d)) < (1.0e-10)) ); + Test( ini_file->GetEntry(page_1, entry_1, &integer_value) ); + Test( integer_value == atoi(text_i) ); + Test( ini_file->GetEntry(page_2, entry_2, &scalar_value) ); + Test( Close_Enough(scalar_value, atof(text_s)) ); + Test( ini_file->GetEntry(page_1, entry_4, &string_value) ); + Test( !strcmp(string_value, text_b) ); + Test( ini_file->GetEntry(page_5, entry_5, &string_value) ); + Test( !strcmp(string_value, text_a) ); + Test( ini_file->GetLogicalEntry(_page9, entry_9, &logical_value) ); + Test( logical_value ); + Test( ini_file->GetLogicalEntry(_page9, entry_1, &logical_value) ); + Test( logical_value ); + Test( ini_file->GetLogicalEntry(_page9, entry_5, &logical_value) ); + Test( logical_value ); + Test( ini_file->GetLogicalEntry(_page9, entry_3, &logical_value) ); + Test( !logical_value ); + Test( ini_file->GetLogicalEntry(_page9, entry_2, &logical_value) ); + Test( !logical_value ); + Test( ini_file->GetLogicalEntry(_page9, entry_4, &logical_value) ); + Test( !logical_value ); + Test( !ini_file->IsDirty() ); + + ini_file->DeletePage(page_2); + Test( ini_file->IsDirty() ); + Test( !ini_file->PageExists(page_2) ); + + ini_file->DeleteEntry(page_1, entry_1); + name_list = ini_file->MakeEntryList(page_1); + Register_Object(name_list); + Test( name_list->EntryCount() == 2 ); + entry = name_list->GetFirstEntry(); + Test( entry != NULL ); + Test( !strcmp(entry->GetName(), entry_4) ); + Test( !strcmp((char *)entry->dataReference, text_b) ); + Unregister_Object(name_list); + delete name_list; + + Test( ini_file->SetMode(IgnoreEntryCaseMode) == (DefaultOperationModes|IgnoreEntryCaseMode) ); + alpha_name_list = ini_file->MakeAlphaEntryList(_page9, "eNtRy"); + Register_Object(alpha_name_list); + Test( ini_file->ClearMode(IgnoreEntryCaseMode) == DefaultOperationModes ); + Test( alpha_name_list->EntryCount() == 7 ); + entry = alpha_name_list->GetFirstEntry(); + Test( entry != NULL ); + Test( !strcmp(entry->GetName(), entry_1) ); + Test( !strcmp((char *)entry->dataReference, text_t) ); + Unregister_Object(alpha_name_list); + delete alpha_name_list; + + ini_file->DeleteStandardPages(); + Test( ini_file->PageCount() == 2 ); + Test( ini_file->IsMarkedLabOnly() ); + Test( ini_file->PageExists(_page9) ); + Test( !ini_file->PageExists(page_5) ); + + ini_file->Abort(); + Test( !ini_file->IsDirty() ); + + ini_file->SetEntry(page_2, entry_4, text_a); + Test( ini_file->IsDirty() ); + + Unregister_Object(ini_file); + delete ini_file; + + Tell(" NotationFile::TestClass() is not rigorous!\n"); + return True; +} + +//############################################################################# +//############################################################################# diff --git a/CODE/RP/MUNGA/NTTMGR.CPP b/CODE/RP/MUNGA/NTTMGR.CPP new file mode 100644 index 0000000..0e68a7a --- /dev/null +++ b/CODE/RP/MUNGA/NTTMGR.CPP @@ -0,0 +1,251 @@ +//===========================================================================// +// File: entity2.cc // +// Project: MUNGA Brick: Entity Manager // +// Contents: Implementation details of the entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(NTTMGR_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +#if !defined(DROPZONE_HPP) + #include +#endif + +#if !defined(REGISTRY_HPP) + #include +#endif + +//############################################################################# +//############################ EntityGroup ############################## +//############################################################################# + + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityGroup::EntityGroup(): + groupMembers(NULL) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityGroup::~EntityGroup() +{ +} + +//############################################################################# +//########################### EntityManager ############################# +//############################################################################# + +Derivation + EntityManager::ClassDerivations( + NetworkClient::ClassDerivations, + "EntityManager" + ); + +EntityManager::SharedData + EntityManager::DefaultData( + EntityManager::ClassDerivations, + EntityManager::MessageHandlers + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityManager::EntityManager(): + NetworkClient( + EntityManager::EntityManagerClassID, + DefaultData, + NetworkClient::EntityManagerClientID + ) +{ + deathRow = UseGroup("DeathRow"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityManager::~EntityManager() +{ + // + //---------------------------------------------- + // Erase all the groups listed in the group list + //---------------------------------------------- + // + ObjectNameList::Entry *entry; + while ((entry = groupList.GetFirstEntry()) != NULL) + { + Check(entry); + EntityGroup *group = (EntityGroup*)entry->GetData(); + groupList.DeleteEntry(entry->GetName()); + Unregister_Object(group); + delete group; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntityManager::FryDeathRow() +{ + Check(this); + Check(deathRow); + + // + // ECH 8/23/95 - Just delete one ... this allows the application to + // delete as many entities as it can within the current frame + // + ChainIteratorOf iterator(deathRow->groupMembers); + Node *node; + + if ((node = iterator.GetCurrent()) != NULL) + { + Unregister_Object(node); + delete node; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntityManager::ReceiveNetworkPacket( + NetworkPacket*, + Receiver::Message *packet_message + ) +{ + Check(this); + Check_Pointer(packet_message); + + // + //------------------------------------------------------------------------- + // Check to see if the interest zone contained in the message is one we are + // interested in, and if not, ignore the message + //------------------------------------------------------------------------- + // + Entity::MakeMessage + *message = Cast_Object(Entity::MakeMessage*, packet_message); + + // + //----------------------------------------------------------------------- + // Find the address of the entity. If it exists, post the message on the + // application event queue. + //----------------------------------------------------------------------- + // + Entity + *entity = + application->GetHostManager()->GetEntityPointer(message->entityID); + if (entity) + { + // + // HACK -- This hack puts dropzone messages on max priority. It should + // really be done with a message priority encoded in the message + // + if ( + entity->GetClassID() == DropZoneClassID + && message->messageID == DropZone::AssignDropZoneMessageID + ) + { + application->Post(MaxEventPriority, entity, message); + } + else + { + application->Post(EntityManagerEventPriority, entity, message); + } + } + + // + //-------------------------------------------------------------------------- + // If the entity does not exist, check to see if this is a manager message, + // or see if we have to ask for a remake + //-------------------------------------------------------------------------- + // + else + { + switch (message->messageID) + { + case Entity::MakeMessageID: + { + #if DEBUG_LEVEL>0 + Entity *entity = application->GetRegistry()->MakeEntity(message); + Register_Object(entity); + #else + application->GetRegistry()->MakeEntity(message); + #endif + } + break; + + // + //--------------------------------------------------------------------- + // Send a remake message to the sending host to have our entity rebuilt + //--------------------------------------------------------------------- + // + default: + break; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityGroup* + EntityManager::UseGroup(const char *name) +{ + EntityGroup *group = FindGroup(name); + if (!group) + { + group = new EntityGroup; + group->groupName = groupList.AddEntry(name, group); + Register_Object(group); + } + return group; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntityManager::RemoveGroup(EntityGroup *group) +{ + Check(group); + groupList.DeleteEntry(group->groupName); + Unregister_Object(group); + delete group; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityManager::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA/NTTMGR.HPP b/CODE/RP/MUNGA/NTTMGR.HPP new file mode 100644 index 0000000..1073c46 --- /dev/null +++ b/CODE/RP/MUNGA/NTTMGR.HPP @@ -0,0 +1,149 @@ +//===========================================================================// +// File: entity2.hh // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification for entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/29/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(NTTMGR_HPP) + #define NTTMGR_HPP + + #if !defined(NAMELIST_HPP) + #include + #endif + + #if !defined(NODE_HPP) + #include + #endif + + #if !defined(CHAIN_HPP) + #include + #endif + + #if !defined(NETWORK_HPP) + #include + #endif + + class Entity; + + //########################################################################## + //######################### EntityGroup ############################## + //########################################################################## + + class EntityGroup: + public Node + { + friend class EntityManager; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + protected: + EntityGroup(); + ~EntityGroup(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Naming functions + // + public: + const char* + GetGroupName() + {Check(this); return groupName;} + + protected: + const char + *groupName; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Grouping functions + // + public: + void + Add(Entity *entity) + { + Check(this); + groupMembers.Add(Cast_Object(Node*,entity)); + } + + void + Add(EntityGroup *group) + {Check(this); Check(group); groupMembers.Add(group);} + + ChainOf + groupMembers; + }; + + //########################################################################## + //######################## EntityManager ############################# + //########################################################################## + + class EntityManager: + public NetworkClient + { + friend class Entity; + + //########################################################################## + // Shared Data support + // + protected: + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + //########################################################################## + // Construction and destruction support + // + public: + EntityManager(); + ~EntityManager(); + + void + FryDeathRow(); + + protected: + EntityGroup + *deathRow; + + //########################################################################## + // Message packet receiving + // + public: + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + + //########################################################################## + // Entity grouping + // + public: + EntityGroup* + UseGroup(const char *name); + EntityGroup* + FindGroup(const char *name) + { + Check_Pointer(name); + return (EntityGroup*)groupList.FindObject(name); + } + void + RemoveGroup(EntityGroup* group); + + Logical + TestInstance() const; + + protected: + ObjectNameList + groupList; + }; + +#endif + diff --git a/CODE/RP/MUNGA/OBJSTRM.HPP b/CODE/RP/MUNGA/OBJSTRM.HPP new file mode 100644 index 0000000..dcd2991 --- /dev/null +++ b/CODE/RP/MUNGA/OBJSTRM.HPP @@ -0,0 +1,363 @@ +//===========================================================================// +// File: objstrm.hpp // +// Project: MUNGA Brick: Resource Manager // +// Contents: Implementation Details of resource management // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(OBJSTRM_HPP) +# define OBJSTRM_HPP + +# if !defined(MEMSTRM_HH) +# include +# endif + +# if !defined(NODE_HH) +# include +# endif + +# if !defined(HASH_HH) +# include +# endif + +# if !defined(TREE_HH) +# include +# endif + +# if !defined(CSTR_HH) +# include +# endif + + class NotationFile; + class NameList; + class CString; + class ResourceFile; + class ResourceDescription; + + //########################################################################## + //######################### ObjectStream ############################# + //########################################################################## + + class ObjectStream: + public DynamicMemoryStream + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + ObjectStream(); + ObjectStream( + void *stream_start, + size_t stream_size + ); + ObjectStream(ResourceDescription *resource_description); + ~ObjectStream(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Object creation + // + public: + virtual void + CreateObjects(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Notation file parsing + // + public: + virtual void + BuildFromNotationFile( + NotationFile *notation_file, + ResourceFile *resource_file + ); + + ResourceFile* + GetResourceFile() + {return resourceFile;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Object ID generation + // + protected: + static ObjectID + MakeUniqueObjectID(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Implementations + // + protected: + virtual RegisteredClass* + MakeObjectImplementation(Enumeration class_ID); + + virtual void + CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ); + + virtual void + BuildFromPageImplementation( + NameList *name_list, + Enumeration class_ID, + ObjectID object_ID + ); + + virtual void + BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name_string + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + void + ParseNotationFile(NotationFile *notation_file); + void + ReadIncludedFiles(NameList *entry_list); + void + ReadMacros(NameList *entry_list); + + void + PerformMacroReplacement(NameList *entry_list); + CString + DeriveMacroValue(const CString &token_string); + void + CleanupMacroReplacement(NameList *entry_list); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + typedef PlugOf + MacroValue; + typedef TreeOf + MacroSocket; + typedef TreeIteratorOf + MacroIterator; + + static ObjectID + lastObjectID; + ResourceFile + *resourceFile; + MacroSocket + *macroSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ObjectIDPlug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef PlugOf + ObjectIDPlug; + + //########################################################################## + //###################### PlugStreamManager ########################### + //########################################################################## + + class PlugStreamManager: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Plug stream types + // + public: + typedef HashOf + PlugIndex; + + typedef TreeOf + ObjectIDIndex; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + PlugStreamManager(); + ~PlugStreamManager(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Program termination + // + public: + void + Cleanup(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Manager Accessors + // + public: + static void + AddPlug( + Plug *plug, + ObjectID object_ID + ); + + static Plug* + FindPlug(ObjectID object_ID); + + static void + AddPlugName( + ObjectID object_ID, + const CString &object_name_string + ); + + static ObjectID + FindPlugName(const CString &object_name_string); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + PlugIndex + plugIndex; + ObjectIDIndex + objectIDIndex; + + static PlugStreamManager + plugStreamManager; + }; + + //########################################################################## + //########################## PlugStream ############################## + //########################################################################## + + class PlugStream: + public ObjectStream + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Plug stream types + // + public: + typedef VChainOf + LocalPlugIndex; + + typedef VChainOf + LocalObjectIDIndex; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + PlugStream(); + PlugStream( + void *stream_start, + size_t stream_size + ); + PlugStream(ResourceDescription *resource_description); + ~PlugStream(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Object creation and utilities + // + public: + void + CreateObjects(); + + void + AddLocalPlug( + Plug *plug, + ObjectID object_ID + ); + + void + AddGlobalPlug( + Plug *plug, + ObjectID object_ID + ); + + Plug* + FindPlug(ObjectID object_ID); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Notation file parsing + // + public: + void + BuildFromNotationFile( + NotationFile *notation_file, + ResourceFile *resource_file + ); + + void + AddLocalObjectID( + ObjectID object_ID, + const CString &object_name_string + ); + + void + AddGlobalObjectID( + ObjectID object_ID, + const CString &object_name_string + ); + + ObjectID + FindObjectID(const CString &object_name_string); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Implementations + // + protected: + void + CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ); + + void + BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name_string + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + LocalPlugIndex + *localPlugIndex; + LocalObjectIDIndex + *localObjectIDIndex; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugStream functions ~~~~~~~~~~~~~~~~~~~~~~~~ + + template void + PlugStream_ReadObjectIDAndFindPlug( + PlugStream *stream, + T** type_pointer + ) + { + Check(stream); + Check_Pointer(type_pointer); + + ObjectID object_ID; + Plug *plug; + + MemoryStream_Read(stream, &object_ID); + plug = stream->FindPlug(object_ID); + *type_pointer = Cast_Object(T*, plug); + } + + void + PlugStream_FindEntryAndWriteObjectID( + PlugStream *stream, + NameList *name_list, + const CString &entry_name + ); + +#endif + diff --git a/CODE/RP/MUNGA/ORIGIN.CPP b/CODE/RP/MUNGA/ORIGIN.CPP new file mode 100644 index 0000000..5896eec --- /dev/null +++ b/CODE/RP/MUNGA/ORIGIN.CPP @@ -0,0 +1,159 @@ +//===========================================================================// +// File: origin.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the position class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +// 11/29/94 JMA Added origin concatenation // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(ORIGIN_HPP) + #include +#endif + +#if !defined(MOTION_HPP) + #include +#endif + +#if !defined(LINMTRX_HPP) + #include +#endif + +const Origin + Origin::Identity(Point3D::Identity, Quaternion::Identity); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Origin *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +Origin::Origin(const LinearMatrix &matrix) +{ + Check(&matrix); + linearPosition = matrix; + angularPosition = matrix; +} + +// +//########################################################################### +//########################################################################### +// +Origin& + Origin::operator=(const Origin &origin) +{ + Check_Pointer(this); + Check(&origin); + + angularPosition = origin.angularPosition; + linearPosition = origin.linearPosition; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Origin& + Origin::operator=(const LinearMatrix &matrix) +{ + Check_Pointer(this); + Check(&matrix); + + angularPosition = matrix; + linearPosition = matrix; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Origin::operator==(const Origin &origin) const +{ + Check(this); + return (memcmp(this, &origin, sizeof(Origin)) == 0); +} + +// +//########################################################################### +//########################################################################### +// +Origin& + Origin::AddScaled( + const Origin& source, + const Motion& delta, + Scalar t + ) +{ + Check_Pointer(this); + Check(&source); + Check(&delta); + Verify(t >= 0.0f); + + linearPosition.AddScaled(source.linearPosition, delta.linearMotion, t); + angularPosition.AddScaled(source.angularPosition, delta.angularMotion, t); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Origin& + Origin::Lerp( + const Origin &start, + const Origin &end, + Scalar t + ) +{ + Check_Pointer(this); + Check(&start); + Check(&end); + + linearPosition.Lerp(start.linearPosition, end.linearPosition, t); + angularPosition.Lerp(start.angularPosition, end.angularPosition, t); + Check(this); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator<<( + ostream& stream, + const Origin& p + ) +{ + return stream << '{' << p.linearPosition << ',' << p.angularPosition << '}'; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Origin::TestInstance() const +{ + return angularPosition.TestInstance(); +} +#if defined(TEST_CLASS) +# include "origin.tcp" +#endif + diff --git a/CODE/RP/MUNGA/ORIGIN.HPP b/CODE/RP/MUNGA/ORIGIN.HPP new file mode 100644 index 0000000..08d5ac6 --- /dev/null +++ b/CODE/RP/MUNGA/ORIGIN.HPP @@ -0,0 +1,133 @@ +//===========================================================================// +// File: origin.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the position class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +// 11/29/94 JMA Added origin concatenation // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ORIGIN_HPP) +# define ORIGIN_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + +# if !defined(ROTATION_HPP) +# include +# endif + + class Motion; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Origin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Origin + { + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Origin *); + #endif + + public: + Point3D + linearPosition; + Quaternion + angularPosition; + + static const Origin + Identity; + + // + // Constructors + // + Origin() + {} + Origin( + const Point3D &t, + const EulerAngles& q + ) + {Check(&t); Check(&q); linearPosition = t; angularPosition = q;} + Origin( + const Point3D &t, + const Quaternion& q + ) + {Check(&t); Check(&q); linearPosition = t; angularPosition = q;} + Origin(const LinearMatrix &matrix); + + // + // Assignment operators + // + Origin& + operator=(const Origin& p); + Origin& + operator=(const Point3D& p) + {Check_Pointer(this); Check(&p); linearPosition = p; return *this;} + Origin& + operator=(const EulerAngles& q) + {Check_Pointer(this); Check(&q); angularPosition = q; return *this;} + Origin& + operator=(const YawPitchRoll& q) + {Check_Pointer(this); Check(&q); angularPosition = q; return *this;} + Origin& + operator=(const Quaternion& q) + {Check_Pointer(this); Check(&q); angularPosition = q; return *this;} + Origin& + operator=(const LinearMatrix &m); + + // + // Equality operator + // + Logical + operator==(const Origin&) const; + + // + // Origin motion + // + Origin& + AddScaled( + const Origin& source, + const Motion& delta, + Scalar t + ); + Origin& + Lerp( + const Origin& start, + const Origin& end, + Scalar t + ); + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const Origin& p + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + inline Point3D& + Point3D::operator=(const Origin& p) + {return operator=(p.linearPosition);} + + inline EulerAngles& + EulerAngles::operator=(const Origin& p) + {return operator=(p.angularPosition);} + + inline Quaternion& + Quaternion::operator=(const Origin& p) + {return operator=(p.angularPosition);} + +#endif + diff --git a/CODE/RP/MUNGA/ORIGIN.TCP b/CODE/RP/MUNGA/ORIGIN.TCP new file mode 100644 index 0000000..9d7ccf4 --- /dev/null +++ b/CODE/RP/MUNGA/ORIGIN.TCP @@ -0,0 +1,67 @@ +//===========================================================================// +// File: origin.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the position class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LINMTRX_HPP) + #include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + Origin::TestClass() +{ + DEBUG_STREAM << "Starting Origin test...\n"; + + Point3D p(1.0f,2.0f,3.0f); + Quaternion q(0.0f, 1.0f, 0.0f, 0.0f); + + Quaternion r; + r = q; + const Origin + a(p,r); + Origin + b; + + Quaternion t; + t = a.angularPosition; + Test( + a.linearPosition == p + && t.x == q.x + && t.w == q.w + ); + + LinearMatrix + m; + + m = a; + b = m; + t = b; + Test( + a.linearPosition == b.linearPosition + && t.y == q.y + ); + + b = Point3D(3.0f,2.0f,1.0f); + p = b; + Test(p == Point3D(3.0f,2.0f,1.0f)); + Quaternion s(1.0f, 0.0f, 0.0f, 0.0f); + b = s; + q = b; + Test(q.x == s.x && q.y == s.y && q.z == s.z && q.w == s.w); + + return True; +} + diff --git a/CODE/RP/MUNGA/PLANE.CPP b/CODE/RP/MUNGA/PLANE.CPP new file mode 100644 index 0000000..32a6e27 --- /dev/null +++ b/CODE/RP/MUNGA/PLANE.CPP @@ -0,0 +1,219 @@ +//===========================================================================// +// File: plane.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the plane class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/01/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(PLANE_HPP) +# include +#endif + +#if !defined(SPHERE_HPP) +# include +#endif + +#if !defined(LINMTRX_HPP) +# include +#endif + +#if !defined(EXTNTBOX_HPP) +# include +#endif + +// +//############################################################################# +//############################################################################# +// +Plane::Plane( + const Point3D& p0, + const Point3D& p1, + const Point3D& p2 +) +{ + Vector3D v1,v2; + v1.Subtract(p1, p0); + v2.Subtract(p2, p1); + + Vector3D axis; + axis.Cross(v1, v2); + Verify(!Small_Enough(axis.Length())); + normal = axis; + offset = -(normal * p0); + Verify(Small_Enough(DistanceTo(p1))); + Verify(Small_Enough(DistanceTo(p2))); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +Plane& + Plane::Multiply( + const Plane &p, + const LinearMatrix &m + ) +{ + Check_Pointer(this); + Check(&p); + Check(&m); + + normal.x = p.normal.x*m(0,0) + p.normal.y*m(1,0) + p.normal.z*m(2,0); + normal.y = p.normal.x*m(0,1) + p.normal.y*m(1,1) + p.normal.z*m(2,1); + normal.z = p.normal.x*m(0,2) + p.normal.y*m(1,2) + p.normal.z*m(2,2); + offset = + p.normal.x*m(3,0) + p.normal.y*m(3,1) + p.normal.z*m(3,2) + p.offset; + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::Contains(const Point3D &point) const +{ + return normal * point <= offset; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsSomeOf(const Sphere &sphere) const +{ + return normal*sphere.center - offset <= sphere.radius; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsAllOf(const Sphere &sphere) const +{ + return offset - normal*sphere.center >= sphere.radius; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsSomeOf(const ExtentBox &box) const +{ + Check(this); + Check(&box); + + Point3D test; + test.x = (normal.x > 0.0f) ? box.minX : box.maxX; + test.y = (normal.y > 0.0f) ? box.minY : box.maxY; + test.z = (normal.z > 0.0f) ? box.minZ : box.maxZ; + return Contains(test); +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsAllOf(const ExtentBox &box) const +{ + Check(this); + Check(&box); + + Point3D test; + test.x = (normal.x < 0.0f) ? box.minX : box.maxX; + test.y = (normal.y < 0.0f) ? box.minY : box.maxY; + test.z = (normal.z < 0.0f) ? box.minZ : box.maxZ; + return Contains(test); +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::Intersect(const Sphere &sphere) const +{ + Scalar dist = normal*sphere.center - offset; + return Abs(dist) <= sphere.radius; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::Intersect(const ExtentBox &box) const +{ + if (!ContainsSomeOf(box)) + { + return False; + } + Plane inverse(-normal.x, -normal.y, -normal.z, -offset); + return inverse.ContainsSomeOf(box); +} + +// +//############################################################################# +//############################################################################# +// +ostream& + operator<<(ostream& Stream, const Plane &A_Plane) +{ + Stream << "\n\tPlane Normal: " << A_Plane.normal; + return Stream << "\n\tOffset: " << -A_Plane.offset; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Plane::TestInstance() const +{ + return True; +} + +Scalar + Plane::CalculateX(Scalar y, Scalar z) +{ + Check(this); + Verify(!Small_Enough(normal.x)); + Scalar result = (offset - y*normal.y - z*normal.z)/normal.x; + Check_Fpu(); + return result; +} + +Scalar + Plane::CalculateY(Scalar x, Scalar z) +{ + Check(this); + Verify(!Small_Enough(normal.y)); + Scalar result = (offset - x*normal.x - z*normal.z)/normal.y; + Check_Fpu(); + return result; +} +Scalar + Plane::CalculateZ(Scalar x, Scalar y) +{ + Check(this); + Verify(!Small_Enough(normal.z)); + Scalar result = (offset - x*normal.x - y*normal.y)/normal.z; + Check_Fpu(); + return result; +} diff --git a/CODE/RP/MUNGA/PLANE.HPP b/CODE/RP/MUNGA/PLANE.HPP new file mode 100644 index 0000000..1f96f15 --- /dev/null +++ b/CODE/RP/MUNGA/PLANE.HPP @@ -0,0 +1,139 @@ +//===========================================================================// +// File: plane.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification of the plane class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/01/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(PLANE_HPP) +# define PLANE_HPP + +# if !defined(NORMAL_HPP) +# include +# endif + +# if !defined(POINT3D_HPP) +# include +# endif + + class Sphere; + class ExtentBox; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Plane ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Plane SIGNATURED + { + public: + // + // The plane equation is P*N = 0, where P is a homogeneous point, and N + // is a quadruple representing the plane. Due to some slight + // improvements gained when the offset is negated, a negative offset is + // stored. This must be taken into account whenever we are doing the + // point-to-plane dot product, where we must do a subtraction instead of + // an addition + // + Normal + normal; + Scalar + offset; + + // + // Constructors + // + Plane() + {} + Plane( + Scalar x, + Scalar y, + Scalar z, + Scalar offset + ): + normal(x,y,z), + offset(offset) + {} + Plane( + const Normal& n, + Scalar offset + ): + normal(n), + offset(offset) + {} + Plane( + const Point3D& p0, + const Point3D& p1, + const Point3D& p2 + ); + + // + // Transform functions + // + Plane& + Multiply( + const Plane &p, + const LinearMatrix &m + ); + Plane& + operator*=(const LinearMatrix &m) + {Check(this); Plane t(*this); return Multiply(t,m);} + + // + // half-space division functions + // + Logical + SeenBy(const Vector3D &A_Vector) const + {return normal * A_Vector < 0.0;} + Logical + SeenBy(const Point3D &A_Point) const + {return normal * A_Point > offset;} + Scalar + DistanceTo(const Point3D& A_Point) const + {return normal * A_Point - offset;} + + // + // half-space containment functions + // + Logical + Contains(const Point3D &point) const; + Logical + ContainsSomeOf(const Sphere &sphere) const; + Logical + ContainsAllOf(const Sphere &sphere) const; + Logical + ContainsSomeOf(const ExtentBox &box) const; + Logical + ContainsAllOf(const ExtentBox &box) const; + + // + // plane surface intersection functions + // + Logical + Intersect(const Sphere &sphere) const; + Logical + Intersect(const ExtentBox &box) const; + + friend ostream& + operator<<(ostream& Stream, const Plane &A_Plane); + Logical + TestInstance() const; + static Logical + TestClass(); + + // + // Equation solutions + // + Scalar + CalculateX(Scalar y, Scalar z); + Scalar + CalculateY(Scalar x, Scalar z); + Scalar + CalculateZ(Scalar x, Scalar y); + }; + +#endif diff --git a/CODE/RP/MUNGA/PLAYER.HPP b/CODE/RP/MUNGA/PLAYER.HPP new file mode 100644 index 0000000..ae82ac8 --- /dev/null +++ b/CODE/RP/MUNGA/PLAYER.HPP @@ -0,0 +1,486 @@ +//===========================================================================// +// File: player.hh // +// Project: MUNGA Brick: Model Manager // +// Contents : Interface specification for Munga Player Class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +// 06/19/95 CPB Added BitMap field for gauge support // +// 11/17/95 CPB Moved StatusMessage stuff here from RPPLAYER.HPP // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(PLAYER_HPP) +# define PLAYER_HPP + +# if !defined(ENTITY_HPP) +# include +# endif + +# if !defined(ICOM_HPP) +# include +# endif + +# if !defined(SCNROLE_HPP) +# include +# endif + + class Mission; + class DropZone__ReplyMessage; + + //########################################################################## + //##################### Player::MakeMessage ########################## + //########################################################################## + class Player__MakeMessage: + public Entity::MakeMessage + { + public: + + int + playerBitmapIndex; + + Player__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int player_bitmap_index + ): + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + playerBitmapIndex(player_bitmap_index) + { } + + Player__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int player_bitmap_index + ): + Entity::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + playerBitmapIndex(player_bitmap_index) + { } + + }; + + //########################################################################## + //################### Player::UpdateRecord #################### + //########################################################################## + + struct Player__UpdateRecord : + public Entity::UpdateRecord + { + Scalar + currentScore; + Point3D + dropZoneLocation; + }; + + //########################################################################## + //################# ScoreZone::ReplyMessage ########################## + //########################################################################## + + class Player__ScoreMessage : + public Entity::Message + { + public: + Scalar + scoreAward; + + Player__ScoreMessage( + Receiver::MessageID message_ID, + size_t length, + Scalar score + ): + Entity::Message(message_ID, length), + scoreAward(score) + {} + }; + + //########################################################################## + //################# ScoreZone::ReplyMessage ########################## + //########################################################################## + + class Player__VehicleDeadMessage: + public Entity::Message + { + public: + int deathCount; + EntityID dropZoneID; + + Player__VehicleDeadMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &dropzone_id=EntityID::Null + ): + Entity::Message(message_ID, length), + deathCount(-1), + dropZoneID(dropzone_id) + {} + }; + + //########################################################################## + //###################### Player::StatusMessage ######################### + //########################################################################## + class Player; + + class Player__StatusMessage: + public Node + { + public: + Player__StatusMessage( + Player *player_involved, + int message_type, + Scalar display_time + ); + + enum { + NoMessage = -1, + NextMessageType = 0 + }; + + int + messageType; + Player + *playerInvolved; + Scalar + displayTime; + }; + + //########################################################################## + //########################### Player ################################ + //########################################################################## + + class Player: + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation + ClassDerivations; + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + enum + { + CurrentScoreAttributeID = Entity::NextAttributeID, + DropZoneLocationAttributeID, + PlayerRankingAttributeID, + StatusMessagePointerAttributeID, + PlayerBitmapIndexAttributeID, + PlayerHighlightedAttributeID, + NextAttributeID + }; + + private: + + static const IndexEntry + AttributePointers[]; + + protected: + + static AttributeIndexSet + AttributeIndex; + + virtual int + CalcRanking(); + + public: + + Logical + playerHighlighted; + + Scalar + currentScore; + int + playerRanking; + + Point3D + dropZoneLocation; + + Player__StatusMessage + *statusMessagePointer; + + int + playerBitmapIndex; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Gauge Support + // + public: + typedef Player__StatusMessage + StatusMessage; + void + AddStatusMessage(StatusMessage *status_message); + void + StatusMessageUpdate(Scalar time_slice); + + protected: + ChainOf + statusMessageQueue; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum + { + DropZoneReplyMessageID = Entity::NextMessageID, + ScoreMessageID, + VehicleDeadMessageID, + MissionStartingMessageID, + MissionEndingMessageID, + NextMessageID + }; + + typedef Player__VehicleDeadMessage VehicleDeadMessage; + + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Game start/stop support + // + public: + typedef Message MissionStartingMessage; + typedef Message MissionEndingMessage; + + protected: + void + MissionStartingMessageHandler(Message *message); + void + MissionEndingMessageHandler(Message *message); + + Scalar + fadeTimeRemaining; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + enum { + DropZoneAcquiredState = Entity::StateCount, + VehicleTranslocatedState, + MissionStartingState, + MissionEndingState, + StateCount + }; + + typedef void + (Player::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + virtual void + PlayerSimulation(Scalar time_slice); + + virtual void + CameraShipSimulation(Scalar time_slice); + + void + GoToVehicle(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Vehicle creation + // + protected: + void + DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + void + VehicleDeadMessageHandler(VehicleDeadMessage *message); + + void + HuntForDropZone(Scalar time_slice); + + Mission* + playerMission; + + Entity* + playerVehicle; + + int + deathCount; + + public: + Entity* + GetPlayerVehicle() + {Check(this); return playerVehicle;} + + void + SetPlayerVehicle(Entity *player_vehicle) + { + Check(player_vehicle); + Check(this); + playerVehicle = player_vehicle; + } + + Mission* + GetMission() + { + Check(this); + return playerMission; + } + + int + GetDeathCount() + {Check(this); return deathCount;} + protected: + + virtual void + CreatePlayerVehicle(Origin); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Renderer Support + // + public: + Enumeration + GetAudioRepresentation(Entity *linked_entity); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Intercom Support + // + public: + Icom* + GetIntercom() + { + Check(this); + return intercomPointer; + } + + protected: + Icom + *intercomPointer; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Scoring Support + // + public: + typedef Player__ScoreMessage ScoreMessage; + + const ScenarioRole* + GetScenarioRole() const + {Check(this); return scenarioRole; } + + protected: + void + ScoreMessageHandler(ScoreMessage *message); + + ScenarioRole + *scenarioRole; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Flag Support + // + public: + enum { + NonScoringPlayerBit = Entity::NextBit, + CameraShipPlayerBit, + NextBit + }; + + enum { + NonScoringPlayerFlag = 1 << NonScoringPlayerBit, + CameraShipPlayerFlag = 1 << CameraShipPlayerBit, + DefaultFlags = + Entity::DefaultFlags + | NonScoringPlayerFlag + | PreRunFlag + }; + + void + SetNonScoringPlayerFlag() + {Check(this); simulationFlags |= NonScoringPlayerFlag;} + void + SetScoringPlayerFlag() + {Check(this); simulationFlags &= ~NonScoringPlayerFlag;} + + Logical + IsScoringPlayer() + {Check(this); return (simulationFlags&NonScoringPlayerFlag) == 0;} + + Logical + IsCameraShipPlayer() + {Check(this); return (simulationFlags&CameraShipPlayerFlag);} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update Support + // + + typedef Player__UpdateRecord UpdateRecord; + + protected: + void + WriteUpdateRecord( + Simulation::UpdateRecord *message, + int update_model + ); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + + typedef Player__MakeMessage MakeMessage; + + static Player* + Make(MakeMessage *creation_message); + + Player( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~Player(); + + Logical + TestInstance() const; + + protected: + + void + ManageApplicationStatus(Scalar time_slice); + }; + +#endif diff --git a/CODE/RP/MUNGA/PLUG.CPP b/CODE/RP/MUNGA/PLUG.CPP new file mode 100644 index 0000000..9215b85 --- /dev/null +++ b/CODE/RP/MUNGA/PLUG.CPP @@ -0,0 +1,523 @@ +//===========================================================================// +// File: plug.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details for plugs and their iterators // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 09/82/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff, merged PLGITR.CPP, added Remove() to // +// PlugIterator // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/02/94 ECH Restored base ReceivePlugCommand // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/03/94 JMA Made constructor/destructor out-of-line, moved the // +// ReleasePlugLink into the virtual data, made compatible // +// with GNU C++ // +// 11/08/94 ECH Made compatible with BC4.0 // +// 12/01/94 JMA Made compatible with SGI CC // +// 12/12/94 ECH Removed release handler // +// 02/16/95 ECH Removed plug commands, added node command // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(PLUG_HPP) + #include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Plug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Plug +//############################################################################# +// +Plug::Plug(ClassID class_id): + RegisteredClass(class_id) +{ + linkHead = NULL; +} + +// +//############################################################################# +// Plug +//############################################################################# +// +Plug::Plug(PlugStream *stream): + RegisteredClass(stream) +{ + linkHead = NULL; +} + +// +//########################################################################### +// ~Plug +//########################################################################### +// +Plug::~Plug() +{ + while (linkHead != NULL) + { + Unregister_Object(linkHead); + delete(linkHead); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Plug::TestInstance() const +{ + if (linkHead != NULL) + { + Check(linkHead); + } + return True; +} + +// +//############################################################################# +// ReceivePlugCommand +//############################################################################# +// + +// Considering removal +#if 0 +int + Plug::ReceivePlugCommand( + Plug::CommandID, + void* + ) +{ + return 0; +} +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// PlugIterator +//############################################################################# +// +PlugIterator::PlugIterator( + const Plug *plug, + RegisteredClass::ClassID class_to_iterate +) +{ + Check(plug); + this->plug = plug; + classToIterate = class_to_iterate; + currentLink = plug->linkHead; +} + +PlugIterator::PlugIterator(const PlugIterator &iterator) +{ + Check(&iterator); + plug = iterator.plug; + classToIterate = iterator.classToIterate; + currentLink = iterator.currentLink; +} + +// +//############################################################################# +// PlugIterator +//############################################################################# +// +PlugIterator::~PlugIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + PlugIterator::TestInstance() const +{ + if (currentLink != NULL) + { + Check(currentLink); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + PlugIterator::First() +{ + Check(plug); + currentLink = plug->linkHead; + NextNode(); +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + PlugIterator::Last() +{ + if (currentLink == NULL) + { + Check(plug); + if ((currentLink = plug->linkHead) == NULL) + return; + } + + Check(currentLink); + while(currentLink->nextLink != NULL) + { + currentLink = currentLink->nextLink; + Check(currentLink); + } + PreviousNode(); +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + PlugIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->nextLink; + NextNode(); +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + PlugIterator::Previous() +{ + Check(currentLink); + currentLink = currentLink->prevLink; + PreviousNode(); +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void* + PlugIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + + node = currentLink->socket->GetReleaseNode(); + currentLink = currentLink->nextLink; + NextNode(); + return node; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void* + PlugIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + + node = currentLink->socket->GetReleaseNode(); + currentLink = currentLink->prevLink; + PreviousNode(); + return node; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + PlugIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + Check(currentLink->socket); + + return currentLink->socket->GetReleaseNode(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +#if 0 +CollectionSize + PlugIterator::GetSize() +{ + Link *link; + CollectionSize count; + + Check(plug); + + count = 0; + for + ( + link = plug->linkHead; + link != NULL; + link = link->nextLink + ) + { + Check(link); + Check(link->socket); + if (link->socket->GetReleaseNode() != NULL) + count++; + } + return count; +} +#else +CollectionSize + PlugIterator::GetSize() +{ + CollectionSize i = 0; + + First(); + while (GetCurrentImplementation() != NULL) + { + i++; + Next(); + } + return i; +} +#endif + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +#if 0 +void* + PlugIterator::GetNthImplementation( + CollectionSize index + ) +{ + Link *link; + CollectionSize count; + + Check(plug); + + count = 0; + for + ( + link = plug->linkHead; + link != NULL; + link = link->nextLink + ) + { + Check(link); + if (count == index) { + currentLink = link; + + Check(currentLink); + Check(currentLink->socket); + + return currentLink->socket->GetReleaseNode(); + } + count++; + } + return NULL; +} +#else +void* + PlugIterator::GetNthImplementation( + CollectionSize index + ) +{ + CollectionSize i = 0; + void *item; + + First(); + while ((item = GetCurrentImplementation()) != NULL) + { + if (i == index) + return item; + Next(); + i++; + } + return NULL; +} +#endif + +// +//########################################################################### +// NextNode +//########################################################################### +// +void + PlugIterator::NextNode() +{ + while (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + if ((node = currentLink->socket->GetReleaseNode()) != NULL) + { + Check(node); + if ( + node->GetClassID() == classToIterate || + classToIterate == RegisteredClass::NullClassID + ) + { + return; + } + } + currentLink = currentLink->nextLink; + } + return; +} + +// +//########################################################################### +// PreviousNode +//########################################################################### +// +void + PlugIterator::PreviousNode() +{ + while (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + if ((node = currentLink->socket->GetReleaseNode()) != NULL) + { + Check(node); + if ( + node->GetClassID() == classToIterate || + classToIterate == RegisteredClass::NullClassID + ) + { + return; + } + } + currentLink = currentLink->prevLink; + } + return; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + PlugIterator::Remove() +{ + Link *old_link; + + Check(currentLink); + + old_link = currentLink; + currentLink = currentLink->nextLink; + + Unregister_Object(old_link); + delete old_link; +} + +// +//############################################################################# +// SendNodeCommand +//############################################################################# +// +int + PlugIterator::SendNodeCommand( + NodeCommandID node_command, + void *info + ) +{ + int ret; + Node *node; + + First(); + while ((node = (Node *)GetCurrentImplementation()) != NULL) + { + Check(node); + if ((ret = node->ReceiveNodeCommand(node_command, info)) != 0) + return ret; + Next(); + } + return 0; +} + +// +//########################################################################### +// RemoveSocket +//########################################################################### +// +void + PlugIterator::RemoveSocket(Socket *socket) +{ + Link *link; + + Check(socket); + Check(plug); + for + ( + link = plug->linkHead; + link != NULL; + link = link->nextLink + ) + { + Check(link); + if (link->GetSocket() == socket) + { + currentLink = link->nextLink; + Unregister_Object(link); + delete link; + return; + } + } +} + diff --git a/CODE/RP/MUNGA/PLUG.HPP b/CODE/RP/MUNGA/PLUG.HPP new file mode 100644 index 0000000..0e081a8 --- /dev/null +++ b/CODE/RP/MUNGA/PLUG.HPP @@ -0,0 +1,383 @@ +//===========================================================================// +// File: plug.hpp // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specifications for plugs and their iterators // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 10/19/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff, merged PLGITR.HPP, added Remove() to // +// PlugIterator // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/02/94 ECH Restored base ReceivePlugCommand // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/08/94 JMA Made compatible with GNU C++ // +// 11/29/94 JMA Changed ClassIdentity to ClassID // +// 11/30/94 JMA Adapted to style changes // +// 12/06/94 JMA Made virtual data publicly visible // +// 12/12/94 ECH Removed release handler // +// 02/16/95 ECH Removed plug commands, added node command // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(PLUG_HPP) +# define PLUG_HPP + +# if !defined(VDATA_HPP) +# include +# endif + +# if !defined(ITERATOR_HPP) +# include +# endif + +# if !defined(LINK_HPP) +# include +# endif + + class PlugStream; + + // + //-------------------------------------------------------------------- + // Node Commands - start at zero, inherited commands start with + // Node::NextCommand + //-------------------------------------------------------------------- + // + typedef Enumeration NodeCommandID; + + enum + { + NodeNullCommandID = 0, + NodeNextCommandID + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Plug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class PlugIterator; + + class Plug : + public RegisteredClass + { + friend class Link; + friend class PlugIterator; + + public: + // + //-------------------------------------------------------------------- + // Destructor and instance testing + //-------------------------------------------------------------------- + // + ~Plug(); + Logical + TestInstance() const; + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Plug(ClassID class_id = TrivialPlugClassID); + Plug(PlugStream *stream); + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Link *linkHead; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class PlugOf: + public Plug + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor + //-------------------------------------------------------------------- + // + PlugOf(const T &item); + ~PlugOf(); + + // + //-------------------------------------------------------------------- + // Can cast to the type + //-------------------------------------------------------------------- + // + operator T() const + {return item;} + + // + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- + // + T + GetItem() const + {return item;} + T* + GetPointer() + {return &item;} + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + T item; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + PlugOf::PlugOf(const T &the_item) + { + item = the_item; + } + + template + PlugOf::~PlugOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class PlugIterator: + public Iterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructor & testing + //-------------------------------------------------------------------- + // + PlugIterator( + const Plug *plug, + RegisteredClass::ClassID class_to_iterate=RegisteredClass::NullClassID + ); + PlugIterator(const PlugIterator &iterator); + ~PlugIterator(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + void + First(); + void + Last(); + void + Next(); + void + Previous(); + CollectionSize + GetSize(); + void + Remove(); + + // + //-------------------------------------------------------------------- + // SendNodeCommand - Send a command and related info to all nodes, + // returns when all nodes receive command or until + // receive method returns non-zero. If the receive + // returns non-zero, then the iterator will remain + // at that plug. + //-------------------------------------------------------------------- + // + int + SendNodeCommand( + NodeCommandID node_command, + void *info = NULL + ); + + // + //-------------------------------------------------------------------- + // RemoveSocket - Removes this plug from the specified socket. + //-------------------------------------------------------------------- + // + void + RemoveSocket(Socket *socket); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void* + ReadAndNextImplementation(); + void* + ReadAndPreviousImplementation(); + void* + GetCurrentImplementation(); + void* + GetNthImplementation(CollectionSize index); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + const Plug + *plug; + Link + *currentLink; + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + RegisteredClass::ClassID + classToIterate; + + void + NextNode(); + void + PreviousNode(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class PlugIteratorOf: + public PlugIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructors + //-------------------------------------------------------------------- + // + PlugIteratorOf( + const Plug *plug, + RegisteredClass::ClassID class_to_iterate=RegisteredClass::NullClassID + ); + PlugIteratorOf( + const Plug &plug, + RegisteredClass::ClassID class_to_iterate=RegisteredClass::NullClassID + ); + PlugIteratorOf(const PlugIteratorOf &iterator); + + ~PlugIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T + ReadAndNext() + {return (T)ReadAndNextImplementation();} + T + ReadAndPrevious() + {return (T)ReadAndPreviousImplementation();} + T + GetCurrent() + {return (T)GetCurrentImplementation();} + T + GetNth(CollectionSize index) + {return (T)GetNthImplementation(index);} + +#if 0 + // + //--------------------------------------------------- + // Operators useful when it is known that the iterator + // is a PlugIteratorOf<> Iterator + //--------------------------------------------------- + // + Logical + operator!() + {return currentLink == NULL;} + operator T() + {return GetCurrent();} + T + operator->() + {return GetCurrent();} + PlugIteratorOf& + operator++() + {Next(); return *this;} + PlugIteratorOf& + operator--() + {Previous(); return *this;} + T + operator++(int) + {return ReadAndNext();} + T + operator--(int) + {return ReadAndPrevious();} +#endif + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + PlugIteratorOf::PlugIteratorOf( + const Plug *plug, + RegisteredClass::ClassID class_to_iterate + ): + PlugIterator(plug, class_to_iterate) + { + } + + template + PlugIteratorOf::PlugIteratorOf( + const Plug &plug, + RegisteredClass::ClassID class_to_iterate + ): + PlugIterator(&plug, class_to_iterate) + { + } + + template + PlugIteratorOf::PlugIteratorOf(const PlugIteratorOf &iterator): + PlugIterator(iterator) + { + } + + template + PlugIteratorOf::~PlugIteratorOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/POINT2D.HPP b/CODE/RP/MUNGA/POINT2D.HPP new file mode 100644 index 0000000..2abac2d --- /dev/null +++ b/CODE/RP/MUNGA/POINT2D.HPP @@ -0,0 +1,149 @@ +//===========================================================================// +// File: point.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification of the point class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(POINT_HH) +# define POINT_HH + +# if !defined(VECTOR3D_HH) +# include "vector3d.hh" +# endif + +# if !defined(VECTOR4D_HH) +# include "vector4d.hh" +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Point2D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class Point2DOf: + public Vector2DOf + { + public: + // + // Constructors + // + Point2DOf() + {} + Point2DOf( + T x, + T y + ): + Vector2DOf(x,y) + {} + Point2DOf(const Vector2DOf &v): + Vector2DOf(v) + {} + + // + // Assignment operators + // + Point2DOf& operator=(const Vector2DOf& v) + {Vector2DOf::operator=(v); return *this;} + + // + // Math operators + // + Point2DOf& + Negate(const Vector2DOf &v) + {Vector2DOf::Negate(v); return *this;} + + Point2DOf& + Add( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) + {Vector2DOf::Add(v1,v2); return *this;} + Point2DOf& + operator+=(const Vector2DOf& v) + {return Add(*this,v);} + + Point2DOf& + Subtract( + const Point2DOf& p, + const Vector2DOf& v + ) + {Vector2DOf::Subtract(p,v); return *this;} + Point2DOf& + operator-=(const Vector2DOf& v) + {return Subtract(*this,v);} + + float + operator*(const Vector2DOf& v) const + {return Vector2DOf::operator*(v);} + + Point2DOf& + Multiply( + const Point2DOf& p, + float scale + ) + {Vector2DOf::Multiply(p,scale); return *this;} + Point2DOf& + operator*=(float value) + {return Multiply(*this,value);} + + Point2DOf& + Multiply( + const Point2DOf& p, + const Vector2DOf& v + ) + {Vector2DOf::Multiply(p,v); return *this;} + Point2DOf& + operator*=(const Vector2DOf &v) + {return Multiply(*this,v);} + + Point2DOf& + Divide( + const Vector2DOf& v, + float scale + ) + {Vector2DOf::Divide(v,scale); return *this;} + Point2DOf& + operator/=(float value) + {return Divide(*this,value);} + + Point2DOf& + Divide( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) + {Vector2DOf::Divide(v1,v2); return *this;} + Point2DOf& + operator/=(const Vector2DOf &v) + {return Divide(*this,v);} + + // + // Miscellaneous functions + // + Point2DOf& + Combine( + const Vector2DOf& v1, + float t1, + const Vector2DOf& v2, + float t2 + ) + {Vector2DOf::Combine(v1,t1,v2,t2); return *this;} + + // + // Template support functions + // + Point2DOf& + Lerp( + const Vector2DOf& v1, + const Vector2DOf& v2, + float t + ) + {Vector2DOf::Lerp(v1,v2,t); return *this;} + }; + +#endif + diff --git a/CODE/RP/MUNGA/POINT3D.CPP b/CODE/RP/MUNGA/POINT3D.CPP new file mode 100644 index 0000000..5bda534 --- /dev/null +++ b/CODE/RP/MUNGA/POINT3D.CPP @@ -0,0 +1,92 @@ +//===========================================================================// +// File: point3d.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the point class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(POINT3D_HPP) + #include +#endif + +#if !defined(LINMTRX_HPP) + #include +#endif + +#if !defined(VECTOR4D_HPP) + #include +#endif + +const Point3D + Point3D::Identity(0.0f,0.0f,0.0f); + +// +//########################################################################### +//########################################################################### +// +Point3D& + Point3D::operator=(const Vector4D& v) +{ + Check_Pointer(this); + Check(&v); + Verify(v.w); + + x = v.x/v.w; + y = v.y/v.w; + z = v.z/v.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Point3D& + Point3D::Multiply(const Point3D& p,const AffineMatrix& m) +{ + Check_Pointer(this); + Check(&p); + Check(&m); + + x = p.x*m(0,0) + p.y*m(1,0) + p.z*m(2,0) + m(3,0); + y = p.x*m(0,1) + p.y*m(1,1) + p.z*m(2,1) + m(3,1); + z = p.x*m(0,2) + p.y*m(1,2) + p.z*m(2,2) + m(3,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Point3D& + Point3D::MultiplyByInverse( + const Point3D &p, + const LinearMatrix &m + ) +{ + x = + p.x*m(0,0) + p.y*m(0,1) + p.z*m(0,2) + - m(3,0)*m(0,0) - m(3,1)*m(0,1) - m(3,2)*m(0,2); + y = + p.x*m(1,0) + p.y*m(1,1) + p.z*m(1,2) + - m(3,0)*m(1,0) - m(3,1)*m(1,1) - m(3,2)*m(1,2); + z = + p.x*m(2,0) + p.y*m(2,1) + p.z*m(2,2) + - m(3,0)*m(2,0) - m(3,1)*m(2,1) - m(3,2)*m(2,2); + return *this; +} + +#if defined(TEST_CLASS) +# include "point3d.tcp" +#endif + diff --git a/CODE/RP/MUNGA/POINT3D.HPP b/CODE/RP/MUNGA/POINT3D.HPP new file mode 100644 index 0000000..cbd9139 --- /dev/null +++ b/CODE/RP/MUNGA/POINT3D.HPP @@ -0,0 +1,192 @@ +//===========================================================================// +// File: point.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification of the point class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(POINT_HPP) +# define POINT_HPP + +# if !defined(VECTOR3D_HPP) +# include +# endif + + class Origin; + class Vector4D; + class AffineMatrix; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Point3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Point3D: + public Vector3D + { + public: + static const Point3D + Identity; + + // + // Constructors + // + Point3D() + {} + Point3D( + Scalar x, + Scalar y, + Scalar z + ): + Vector3D(x,y,z) + {} + + // + // Assignment operators + // + Point3D& + operator=(const Vector3D& v) + {Vector3D::operator=(v); return *this;} + Point3D& + operator=(const Vector4D& v); + Point3D& + operator=(const Origin &p); + Point3D& + operator=(const AffineMatrix &matrix); + + // + // Math operators + // + Point3D& + Negate(const Vector3D &v) + {Vector3D::Negate(v); return *this;} + + Point3D& + Add( + const Vector3D& v1, + const Vector3D& v2 + ) + {Vector3D::Add(v1,v2); return *this;} + Point3D& + operator+=(const Vector3D& v) + {return Add(*this,v);} + + Point3D& + Subtract( + const Point3D& p, + const Vector3D& v + ) + {Vector3D::Subtract(p,v); return *this;} + Point3D& + operator-=(const Vector3D& v) + {return Subtract(*this,v);} + + Scalar + operator*(const Vector3D& v) const + {return Vector3D::operator*(v);} + + Point3D& + Multiply( + const Point3D& p, + Scalar scale + ) + {Vector3D::Multiply(p,scale); return *this;} + Point3D& + operator*=(Scalar value) + {return Multiply(*this,value);} + + Point3D& + Multiply( + const Point3D& p, + const Vector3D& v + ) + {Vector3D::Multiply(p,v); return *this;} + Point3D& + operator*=(const Vector3D &v) + {return Multiply(*this,v);} + + Point3D& + Divide( + const Vector3D& v, + Scalar scale + ) + {Vector3D::Divide(v,scale); return *this;} + Point3D& + operator/=(Scalar value) + {return Divide(*this,value);} + + Point3D& + Divide( + const Vector3D& v1, + const Vector3D& v2 + ) + {Vector3D::Divide(v1,v2); return *this;} + Point3D& + operator/=(const Vector3D &v) + {return Divide(*this,v);} + + // + // Transforms + // + Point3D& + Multiply( + const Vector3D &v, + const AffineMatrix &m + ) + {Vector3D::Multiply(v,m); return *this;} + Point3D& + Multiply( + const Point3D &p, + const AffineMatrix &m + ); + Point3D& + operator*=(const AffineMatrix &m) + {Point3D src(*this); return Multiply(src,m);} + Point3D& + MultiplyByInverse( + const Vector3D &v, + const LinearMatrix &m + ) + {Vector3D::MultiplyByInverse(v,m); return *this;} + Point3D& + MultiplyByInverse( + const Point3D &p, + const LinearMatrix &m + ); + + // + // Miscellaneous functions + // + Point3D& + Combine( + const Vector3D& v1, + Scalar t1, + const Vector3D& v2, + Scalar t2 + ) + {Vector3D::Combine(v1,t1,v2,t2); return *this;} + + // + // Template support functions + // + Point3D& + Lerp( + const Vector3D& v1, + const Vector3D& v2, + Scalar t + ) + {Vector3D::Lerp(v1,v2,t); return *this;} + + static Logical + TestClass(); + }; + +#endif + +#if !defined(AFFNMTRX_HPP) +# include +#endif diff --git a/CODE/RP/MUNGA/POINT3D.TCP b/CODE/RP/MUNGA/POINT3D.TCP new file mode 100644 index 0000000..00fc95d --- /dev/null +++ b/CODE/RP/MUNGA/POINT3D.TCP @@ -0,0 +1,137 @@ +//===========================================================================// +// File: point.tst // +// Project: MUNGA Brick: Math Library // +// Contents: test code for point class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ORIGIN_HPP) + #include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + Point3D::TestClass() +{ + DEBUG_STREAM << "Starting Point3D test...\n"; + + const Point3D + a(Identity); + Point3D + b; + const Point3D + c(1.0f,2.0f,3.0f); + Point3D + d(2.0f,3.0f,1.0f); + + Test(!a.x && !a.y && !a.z); + Test(c.x == 1.0f && c.y == 2.0f && c.z == 3.0f); + + Test(c[2] == c.z); + Test(a[1] == a.y); + + Test(Small_Enough(a)); + Test(!a); + + b = c; + Test(b.x == c.x && b.y == c.y && b.z == c.z); + Test(Close_Enough(b,c)); + Test(b == c); + Test(a != b); + + b.Negate(c); + Test(b == Point3D(-c.x,-c.y,-c.z)); + + b.Add(c,d); + Test(b == Point3D(c.x+d.x,c.y+d.y,c.z+d.z)); + b = c; + b += d; + Test(b == Point3D(c.x+d.x,c.y+d.y,c.z+d.z)); + + b.Subtract(d,c); + Test(b == Point3D(d.x-c.x,d.y-c.y,d.z-c.z)); + b = d; + b -= c; + Test(b == Point3D(d.x-c.x,d.y-c.y,d.z-c.z)); + + Scalar f = c*d; + Test(f == c.x*d.x + c.y*d.y + c.z*d.z); + + b.Cross(c,d); + Test(b == Point3D(c.y*d.z-c.z*d.y,c.z*d.x-c.x*d.z,c.x*d.y-c.y*d.x)); + + f = 2.0f; + b.Multiply(c,f); + Test(b == Point3D(f*c.x,f*c.y,f*c.z)); + b = c; + b *= f; + Test(b == Point3D(f*c.x,f*c.y,f*c.z)); + + b.Multiply(c,d); + Test(b == Point3D(c.x*d.x,c.y*d.y,c.z*d.z)); + b = c; + b *= d; + Test(b == Point3D(c.x*d.x,c.y*d.y,c.z*d.z)); + + b.Divide(c,f); + Test(b == Point3D(c.x/f,c.y/f,c.z/f)); + b = c; + b /= f; + Test(b == Point3D(c.x/f,c.y/f,c.z/f)); + + b.Divide(c,d); + Test(b == Point3D(c.x/d.x,c.y/d.y,c.z/d.z)); + b = c; + b /= d; + Test(b == Point3D(c.x/d.x,c.y/d.y,c.z/d.z)); + + AffineMatrix + m; + EulerAngles + r(PI_OVER_4,0.0f,0.0f); + m = r; + m = c; + b = m; + Test(b == c); + b.Multiply(c,m); + Test(b == Point3D(c.x+m(3,0),c.y*m(1,1)+c.z*m(2,1)+m(3,1),c.y*m(1,2)+c.z*m(2,2)+m(3,2))); + b = c; + b *= m; + Test(b == Point3D(c.x+m(3,0),c.y*m(1,1)+c.z*m(2,1)+m(3,1),c.y*m(1,2)+c.z*m(2,2)+m(3,2))); + + Test(!a.LengthSquared()); + f = c.LengthSquared(); + Test(f == c.x*c.x + c.y*c.y + c.z*c.z); + f = c.Length(); + Test(Close_Enough(f,Sqrt(c.x*c.x + c.y*c.y + c.z*c.z))); + b.Normalize(c); + Test(b == Point3D(c.x/f, c.y/f, c.z/f)); + + b.Combine(c,2.0f,d,2.0f); + Test(b == Point3D(2.0f*(c.x+d.x),2.0f*(c.y+d.y),2.0f*(c.z+d.z))); + + b.Lerp(c,d,0.5f); + Test(b == Point3D(0.5f*(c.x+d.x),0.5f*(c.y+d.y),0.5f*(c.z+d.z))); + + Vector4D v(2.0f,4.0f,6.0f,2.0f); + b = v; + Test(b == Point3D(v.x/v.w, v.y/v.w, v.z/v.w)); + + Origin t; + t.linearPosition = Point3D(2.0f,3.0f,4.0f); + t.angularPosition = EulerAngles(0.0f,0.0f,0.0f); + b = t; + Test(b == Point3D(t.linearPosition.x,t.linearPosition.y,t.linearPosition.z)); + + return True; +} diff --git a/CODE/RP/MUNGA/RANDOM.HPP b/CODE/RP/MUNGA/RANDOM.HPP new file mode 100644 index 0000000..9e03af1 --- /dev/null +++ b/CODE/RP/MUNGA/RANDOM.HPP @@ -0,0 +1,74 @@ +//===========================================================================// +// File: random.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for the random number generator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/93 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RANDOM_HPP) +# define RANDOM_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Random ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class RandomGenerator SIGNATURED + { + private: + static int + Numbers[250]; // the random number table + static int + Index; // the current entry within the table + + static void + Init(); + + static int + GetRandomInt(); + + public: + RandomGenerator() + {if (Index == -1) Init();} + + // + //------------------------ + // Random number functions + //------------------------ + // + int + GetInt() // returns 0 .. RAND_MAX + {return GetRandomInt();} + operator Scalar(); // returns 0.0f <= x < 1.0f + int // returns 0 .. Range-1 + operator ()(int Range); + + static Logical + TestClass(); + }; + + extern RandomGenerator Random; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Die ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Die SIGNATURED + { + private: + int + highestRandom, // the highest random number giving a uniform dist. + dieSides; // the number of sides on the die (starting from 1) + + public: + Die(int sides); + operator int(); // returns 1 .. dieSides + }; + +#endif diff --git a/CODE/RP/MUNGA/RANDOM.TCP b/CODE/RP/MUNGA/RANDOM.TCP new file mode 100644 index 0000000..0e957d0 --- /dev/null +++ b/CODE/RP/MUNGA/RANDOM.TCP @@ -0,0 +1,44 @@ +//===========================================================================// +// File: random.tst // +// Project: MUNGA Brick: Math Library // +// Contents: test function for the random number generator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/93 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + RandomGenerator::TestClass() +{ + DEBUG_STREAM << "Starting Random test...\n"; + +#define RANDOM_TEST_COUNT 10000 + + int i; + for (i=0; i= 0.0f && r < 1.0f,r); + } + + int array[10]; + for (i = 0; i= 0 && r < ELEMENTS(array)); + ++array[r]; + } + + return True; +} + diff --git a/CODE/RP/MUNGA/RAY.HPP b/CODE/RP/MUNGA/RAY.HPP new file mode 100644 index 0000000..ed78c4f --- /dev/null +++ b/CODE/RP/MUNGA/RAY.HPP @@ -0,0 +1,103 @@ +//########################################################################### +// +// $Workfile: RAY.HPP $ +// $Revision: 1.5 $ +// $Modtime: 14 May 1996 20:06:14 $ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Copyright(c) 1993 J. M. Albertson - All Rights Reserved +// +//########################################################################### + +#if !defined(RAY_HPP) +# define RAY_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + +# if !defined(UNITVEC_HPP) +# include +# endif + + class Plane; + class Sphere; + class Cylinder; + class Cone; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ray ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Ray SIGNATURED + { + public: + Point3D + origin; + UnitVector + direction; + + Ray() + {} + Ray( + const Point3D &origin, + const UnitVector &direction + ): + origin(origin), + direction(direction) + {} + + // + // Ray projection functions + // + void + Project( + Scalar length, + Point3D *result + ); + Scalar + LengthToClosestPointTo(const Point3D &point); + void + ClosestPointTo( + const Point3D &point, + Point3D *result + ) + { + Check(this); Check(result); Check(&point); + Project(LengthToClosestPointTo(point),result); + } + + // + // Ray intersection functions + // + Scalar + DistanceTo( + const Plane &plane, + Scalar *product + ) const; + Scalar + DistanceTo( + const Sphere &sphere, + Scalar *penetration + ) const; + + // + // Test support + // + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + extern Scalar + Find_Closest_Approach( + const Point3D& origin1, + const Vector3D& velocity1, + Point3D *result1, + const Point3D& origin2, + const Vector3D& velocity2, + Point3D *result2, + Scalar *time, + Logical *constant + ); + +#endif diff --git a/CODE/RP/MUNGA/RAY.TCP b/CODE/RP/MUNGA/RAY.TCP new file mode 100644 index 0000000..5ff72d9 --- /dev/null +++ b/CODE/RP/MUNGA/RAY.TCP @@ -0,0 +1,22 @@ +//===========================================================================// +// File: ray.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for the ray class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/25/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + Ray::TestClass() +{ + DEBUG_STREAM << "Starting Ray test...\n"; + Tell(" Ray::TestClass is stubbed out!\n"); + return True; +} + diff --git a/CODE/RP/MUNGA/RECEIVER.HPP b/CODE/RP/MUNGA/RECEIVER.HPP new file mode 100644 index 0000000..0691b95 --- /dev/null +++ b/CODE/RP/MUNGA/RECEIVER.HPP @@ -0,0 +1,589 @@ +//===========================================================================// +// File: receiver.hpp // +// Project: MUNGA Brick: Dynamic Dispatch // +// Contents: Dynamic Dispatch Interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/04/94 JMA Made compatible with GNU C++ // +// 11/04/94 ECH Added null handler set // +// 11/29/94 JMA Changed ClassIdentity to ClassID // +// 11/30/94 JMA Adapted to new style conventions // +// 12/04/94 JMA Moved Message under Receiver, merged with message.hpp // +// 12/06/94 JMA Made DefaultData publicly visible // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(RECEIVER_HPP) +# define RECEIVER_HPP + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + +# if !defined(MEMSTRM_HPP) +# include +# endif + + class Receiver__SharedData; + class Receiver__InheritanceSet; + struct Receiver__HandlerEntry; + class Receiver__MessageHandlerSet; + class Receiver__Message; + class Receiver__DynamicMessage; + class Derivation; + class Event; + class DynamicMemoryStream; + class MessageTap; + + //########################################################################## + //########################## Receiver ################################ + //########################################################################## + // + // It is suggested that calls to methods meant to be serviced by a receiver + // be built through inline functions in the derived class, rather than + // having to build the parameter block in the scope of the caller. Letting + // the inline code build the parameter block is much cleaner, and allows the + // message code numbers to be held inside the derived class, further + // protecting against calling methods for objects not in a proper derivation + // chain. + // + class Receiver: + public Node + { + //########################################################################## + // Shared Data Support + // + public: + typedef Receiver__SharedData SharedData; + SharedData* + GetSharedData() const; + + static Derivation ClassDerivations; + Derivation* + GetDerivation() const; + + static SharedData DefaultData; + + Logical + IsDerivedFrom(Derivation& parent) const; + Logical + IsDerivedFrom(const char* parent) const; + + protected: + const SharedData* sharedData; + + //########################################################################## + // Construction and Destruction Support + // + protected: + Receiver( + ClassID class_ID, + SharedData &shared_data + ): + Node(class_ID), + sharedData(&shared_data) + {} + + Receiver( + PlugStream *stream, + SharedData &shared_data + ): + Node(stream), + sharedData(&shared_data) + {} + + //########################################################################## + // Messaging Support + // + public: + typedef Receiver__Message Message; + typedef Receiver__DynamicMessage DynamicMessage; + typedef Receiver__InheritanceSet InheritanceSet; + typedef Receiver__HandlerEntry HandlerEntry; + typedef Receiver__MessageHandlerSet MessageHandlerSet; + typedef void (Receiver::*Handler)(const Message*); + typedef Enumeration MessageID; + + enum { + AnyMessageID=0, + WatcherChangedMessageID, + LoadResourceFinishedMessageID, + NextMessageID + }; + + static const Handler NullHandler; + + void + Receive(Message *What); + + virtual void + Dispatch(Message *What) + {Receive(What);} + + void + DefaultMessageHandler(Message*); + + typedef void (Receiver::*ScanCallback)( + Receiver::Message *message, + Receiver *receiver + ); + + MessageTap* + MakeMessageTap( + Derivation *derivation, + ScanCallback callback + ); + MessageTap* + MakeMessageTap( + Derivation *derivation, + ScanCallback callback, + Receiver::MessageID matching_message, + Receiver *match_receiver + ); + + protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //########################################################################## + // Event Support + // + public: + virtual void + Receive(Event *event); + + void + FlushEvents(int max_priority=-1); + void + FlushMatchingEvents( + MessageID target_message, + int max_priority=-1 + ); + + void + ProcessDeferredQueue(); + + //########################################################################## + // Test Support + // + public: + static Logical + TestClass(); + Logical + TestInstance() const; + }; + + //########################################################################## + //###################### Receiver::Message ########################### + //########################################################################## + + class Receiver__Message + { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Receiver__Message *); + #endif + + size_t + messageLength; + Receiver::MessageID + messageID; + + enum { + ReliableBit, + NextBit + }; + + enum { + ReliableFlag = 1 << ReliableBit + }; + + LWord + messageFlags; + + Receiver__Message( + Receiver::MessageID id, + size_t message_length + ): + messageID(id), + messageLength(message_length), + messageFlags(ReliableFlag) // HACK + {} + + Logical + TestInstance() const; + }; + + //########################################################################## + //################### Receiver::DynamicMessage ####################### + //########################################################################## + + class Receiver__DynamicMessage: + public DynamicMemoryStream + { + public: + Receiver__DynamicMessage() + {} + Receiver__DynamicMessage( + void *stream_start, + size_t stream_size, + size_t initial_offset=0 + ): + DynamicMemoryStream(stream_start, stream_size, initial_offset) + {} + Receiver__DynamicMessage( + Receiver::MessageID message_ID, + size_t size = sizeof(Receiver::Message) + ); + + Receiver::Message* + GetMessagePointer() + {Check(this); return Cast_Object(Receiver::Message*, streamStart);} + + protected: + MemoryStream& + WriteBytes( + const void *ptr, + size_t number_of_bytes + ); + }; + + //########################################################################## + //#################### ReceiverDataMessageOf ######################### + //########################################################################## + + template class ReceiverDataMessageOf: + public Receiver::Message + { + public: + T + dataContents; + + ReceiverDataMessageOf( + Receiver::MessageID id, + size_t message_length, + const T& data + ): + Receiver::Message(id, message_length), + dataContents(data) + {} + }; + + //########################################################################## + //######################### MessageTap ############################### + //########################################################################## + + class MessageTap: + public Plug + { + //########################################################################## + // MessageTap Functionality + // + public: + MessageTap( + Derivation *derivation, + Receiver *client, + Receiver::ScanCallback callback + ); + MessageTap( + Derivation *derivation, + Receiver *client, + Receiver::ScanCallback callback, + Receiver::MessageID matching_message, + Receiver *match_receiver + ); + + private: + Receiver::ScanCallback scanCallback; + Receiver* clientReceiver; + Receiver* matchingReceiver; + Receiver::MessageID matchingMessageID; + + public: + void + Scan( + Receiver *receiver, + Receiver::Message *message + ); + + //########################################################################## + // Memory Allocation + // + private: + static MemoryBlock AllocatedMemory; + + public: + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + + //########################################################################## + // Test support + // + public: + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + //########################################################################## + //################## Receiver::InheritanceSet ######################## + //########################################################################## + // + // NOTE: An InheritanceSet generated for a class should only be inherited by + // other classes derived from that base class. If this is not done, + // SEVERE run-time weirdness will happen + // + class Receiver__InheritanceSet SIGNATURED + { + public: + Logical + TestInstance() const; + Enumeration + GetEntryCount() + {Check(this); return entryCount;} + + protected: + Enumeration + entryCount; + + Receiver__InheritanceSet() + {} + ~Receiver__InheritanceSet() + {} + }; + + //########################################################################## + //################### Receiver::HandlerEntry ######################### + //########################################################################## + + struct Receiver__HandlerEntry + { + Enumeration + entryID; + const char* + entryName; + Receiver::Handler + entryHandler; + }; + + #define MESSAGE_ENTRY(class,message)\ + {\ + class::message##MessageID,\ + #message,\ + (Receiver::Handler)&class::message##MessageHandler\ + } + + //########################################################################## + //################# Receiver::MessageHandlerSet ###################### + //########################################################################## + + class Receiver__MessageHandlerSet: + public Receiver__InheritanceSet + { + //########################################################################## + // Constructors and Destructors + // + public: + Receiver__MessageHandlerSet( + Receiver::MessageID count, + const Receiver::HandlerEntry handler_table[], + const Receiver::MessageHandlerSet &inheritance + ) + {Build(count, handler_table, &inheritance);} + Receiver__MessageHandlerSet( + Receiver::MessageID count, + const Receiver::HandlerEntry handler_table[] + ) + {Build(count, handler_table, NULL);} + Receiver__MessageHandlerSet() + {messageHandlers = NULL; entryCount = 0;} + ~Receiver__MessageHandlerSet(); + + protected: + void + Build( + Receiver::MessageID count, + const Receiver::HandlerEntry handler_table[], + const Receiver::MessageHandlerSet *inheritance + ); + + //########################################################################## + // HandlerSet Functionality + // + public: + static const Receiver::MessageHandlerSet + NullSet; + + Receiver::Handler + Find(Receiver::MessageID message) const + { + Check(this); + Verify(message > 0); + return (message<=entryCount) + ? messageHandlers[message-1].entryHandler + : Receiver::NullHandler; + } + const Receiver::HandlerEntry* + Find(const char* name) const; + + const char * + GetName(Receiver::MessageID message) const + { + Check(this); + return (message<=entryCount) + ? messageHandlers[message-1].entryName + : NULL; + } + + protected: + Receiver::HandlerEntry* messageHandlers; + + //########################################################################## + // Test Support + // + public: + static Logical + TestClass(); + }; + + //########################################################################## + //########################## Derivation ############################## + //########################################################################## + + class Derivation: + public Node + { + friend class Receiver; + + //########################################################################## + // Construction and Destruction + // + public: + Derivation(char *who); + Derivation(Derivation& parent,char *who); + + char *className; + + //########################################################################## + // Messagetap support + // + private: + Derivation(Derivation& copy); + ChainOf + activeTaps; + + public: + void + AppendMessageTap(MessageTap* tap); + Logical + IsDescendedFrom(Derivation& parent); + Logical + IsDescendedFrom(const char* parent); + + //########################################################################## + // Inheritance Registration Support + // + private: + ChainOf + classDerivations; + + void + AppendDerivation(Derivation* child) + {Check(this); classDerivations.Add(child);} + + //########################################################################## + // Test Support + // + public: + static Logical + TestClass(); + }; + + //########################################################################## + //################### Receiver::SharedData ########################## + //########################################################################## + + class Receiver__SharedData SIGNATURED + { + public: + Receiver__SharedData( + Derivation& derivation, + Receiver::MessageHandlerSet &handler + ): + derivedClasses(&derivation), + activeMessageHandlers(&handler) + {} + + Derivation + *derivedClasses; + Receiver::MessageHandlerSet + *activeMessageHandlers; + + Logical + TestInstance() const; + }; + + inline Receiver::SharedData* + Receiver::GetSharedData() const + {Check(this); return Cast_Object(SharedData*,sharedData);} + + inline Derivation* + Receiver::GetDerivation() const + {Check(this); return GetSharedData()->derivedClasses;} + + inline Logical + Receiver::IsDerivedFrom(Derivation& parent) const + {return sharedData->derivedClasses->IsDescendedFrom(parent);} + + inline Logical + Receiver::IsDerivedFrom(const char* parent) const + {Check(this); return GetDerivation()->IsDescendedFrom(parent);} + + inline MessageTap* + Receiver::MakeMessageTap( + Derivation *derivation, + ScanCallback callback + ) + {Check(this); return new MessageTap(derivation, this, callback);} + + inline MessageTap* + Receiver::MakeMessageTap( + Derivation *derivation, + ScanCallback callback, + Receiver::MessageID matching_message, + Receiver *match_receiver + ) + { + Check(this); + return new MessageTap( + derivation, + this, + callback, + matching_message, + match_receiver + ); + } +#endif + diff --git a/CODE/RP/MUNGA/RECEIVER.TCP b/CODE/RP/MUNGA/RECEIVER.TCP new file mode 100644 index 0000000..cb8c3fe --- /dev/null +++ b/CODE/RP/MUNGA/RECEIVER.TCP @@ -0,0 +1,510 @@ +//===========================================================================// +// File: receiver.tst // +// Project: MUNGA Brick: Dynamic Dispatch // +// Contents: Test routines for MessageHandlerSet, Derivation and Receiver // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 11/02/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/01/94 JMA Made compatible with SGI CC // +// 12/04/94 JMA Moved Message under Receiver, merged in message.tst // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "testclas.hpp" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Alpha ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Alpha::Alpha( + ClassID class_ID, + SharedData &vdata +): + Receiver(class_ID,vdata) +{ + x = -1; +} + +Alpha::~Alpha() +{ +} + +void + Alpha::Method0Handler(Message*) +{ + x = 0; +} + +void + Alpha::Method1Handler(Message*) +{ + x = 1; +} + +Alpha::SharedData + Alpha::DefaultData( + Alpha::ClassDerivations, + Alpha::handlerSet + ); +Derivation + Alpha::ClassDerivations(Receiver::ClassDerivations,"Alpha"); + +const Receiver::HandlerEntry + Set_1[]= +{ + { + Alpha::message0ID, + "message0", + (Receiver::Handler)&Alpha::Method0Handler + }, + { + Alpha::message1ID, + "message1", + (Receiver::Handler)&Alpha::Method1Handler + } +}; + +Receiver::MessageHandlerSet + Alpha::handlerSet( + ELEMENTS(Set_1), + Set_1, + Receiver::MessageHandlers + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Beta ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Beta::Beta( + ClassID class_id, + SharedData &vdata +): + Alpha(class_id, vdata) +{ + x = -2; +} + +Beta::~Beta() +{ +} + +void + Beta::Method1aHandler(Message*) +{ + x = 6; +} + +void + Beta::Method2Handler(Message*) +{ + x = 2; +} + +void + Beta::Method3Handler(Message*) +{ + x = 3; +} + +Beta::SharedData + Beta::DefaultData( + Beta::ClassDerivations, + Beta::handlerSet + ); +Derivation + Beta::ClassDerivations(Alpha::ClassDerivations,"Beta"); + +const Receiver::HandlerEntry + Set_2[]= +{ + { + Beta::message1ID, + "message1", + (Receiver::Handler)&Beta::Method1aHandler + }, + { + Beta::message2ID, + "message2", + (Receiver::Handler)&Beta::Method2Handler + }, + { + Beta::message3ID, + "message3", + (Receiver::Handler)&Beta::Method3Handler + } +}; + +Receiver::MessageHandlerSet + Beta::handlerSet( + ELEMENTS(Set_2), + Set_2, + Alpha::handlerSet + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Gamma ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Gamma::Gamma(): + Beta(TrivialReceiverClassID, DefaultData) +{ + x = -3; +} + +Gamma::~Gamma() +{ +} + +void + Gamma::Method4Handler(Message*) +{ + x = 4; +} + +Gamma::SharedData + Gamma::DefaultData( + Gamma::ClassDerivations, + Gamma::handlerSet + ); +Derivation + Gamma::ClassDerivations(Beta::ClassDerivations,"Gamma"); + +const Receiver::HandlerEntry + Set_3[]= +{ + { + Gamma::message4ID, + "message4", + (Receiver::Handler)&Gamma::Method4Handler + } +}; + +Receiver::MessageHandlerSet + Gamma::handlerSet( + ELEMENTS(Set_3), + Set_3, + Beta::handlerSet + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ MessageHandlerSet ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + Receiver::MessageHandlerSet::TestClass() +{ + DEBUG_STREAM << "Starting Receiver::MessageHandlerSet test...\n"; + // + //-------------------------------- + // Test the inherited construction + //-------------------------------- + // + Test(Alpha::handlerSet.entryCount == Alpha::message1ID); + Test(Beta::handlerSet.entryCount == Beta::message3ID); + Test(Gamma::handlerSet.entryCount == Gamma::message4ID); + + // + //-------------------------- + // Verify that Find() works + //-------------------------- + // + Test( + Alpha::handlerSet.Find(Alpha::message1ID) + == (Receiver::Handler)&Alpha::Method1Handler + ); + Test(Alpha::handlerSet.Find(Gamma::message4ID) == Receiver::NullHandler); + + Test( + Beta::handlerSet.Find(Alpha::message1ID) + == (Receiver::Handler)&Beta::Method1aHandler + ); + Test( + Beta::handlerSet.Find(Beta::message2ID) + == (Receiver::Handler)&Beta::Method2Handler + ); + + Test( + Gamma::handlerSet.Find(Alpha::message1ID) + == (Receiver::Handler)&Beta::Method1aHandler + ); + Test( + Gamma::handlerSet.Find(Beta::message2ID) + == (Receiver::Handler)&Beta::Method2Handler + ); + Test( + Gamma::handlerSet.Find(Gamma::message4ID) + == (Receiver::Handler)&Gamma::Method4Handler + ); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Derivation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + Derivation::TestClass() +{ + DEBUG_STREAM << "Starting Derivation test...\n"; + + Tell(" Derivation::TestClass() is stubbed out...\n"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Receiver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + Receiver::TestClass() +{ + DEBUG_STREAM << "Starting Receiver test...\n"; + + Alpha a; + Beta b; + Gamma c; + Message m(0, sizeof(Message)); + + // + // Check construction stability + // + ChainIteratorOf + i(Alpha::ClassDerivations.classDerivations); + Test(i.ReadAndNext() == &Beta::ClassDerivations); + Test(i.GetCurrent() == NULL); + + ChainIteratorOf + j(Beta::ClassDerivations.classDerivations); + Test(j.ReadAndNext() == &Gamma::ClassDerivations); + Test(j.GetCurrent() == NULL); + + ChainIteratorOf + k(Gamma::ClassDerivations.classDerivations); + Test(k.GetCurrent() == NULL); + + Test(a.x == -1); + Test(b.x == -2); + Test(c.x == -3); + + // + // Check basic method response + // + + a.Method0(); + b.Method0(); + c.Method0(); + Test(a.x == 0); + Test(b.x == 0); + Test(c.x == 0); + + a.Method1(); + b.Method1(); + c.Method1(); + Test(a.x == 1); + Test(b.x == 6); + Test(c.x == 6); + + m.messageID = Beta::message2ID; + a.Dispatch(&m); + b.Method2(); + c.Method2(); + Test(a.x == 1); + Test(b.x == 2); + Test(c.x == 2); + + b.Method3(); + c.Method3(); + Test(b.x == 3); + Test(c.x == 3); + + c.Method4(); + Test(c.x == 4); + + // + // Now test tapping. First, hierarchy... + // +#if 0 + MessageTap + *t = new MessageTap(a.GetDerivation(),f); + + Verify(t); + x = -1; + a.Method0(); + Test(a.x == 0); + Test(x == 1); + + x = -1; + b.Method1(); + Test(b.x == 6); + Test(x == 1); + + x = -1; + c.Method3(); + Test(c.x == 3); + Test(x == 1); + + // + // Now test multiple tap operation + // + MessageTap + *u = new MessageTap(b.GetDerivation(),g); + + x = -1; + y = -1; + a.Method0(); + Test(a.x == 0); + Test(x == 1); + Test(y == -1); + + x = -1; + b.Method1(); + Test(b.x == 6); + Test(x == 1); + Test(y == 2); + + x = -1; + y = -2; + c.Method3(); + Test(c.x == 3); + Test(x == 1); + Test(y == 2); + + delete t; + delete u; +#endif + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MessageTap ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + MessageTap::TestClass() +{ + DEBUG_STREAM << "Starting MessageTap test...\n"; +#if 0 + Alpha a; + Receiver::Message m; + + // + // Check universal tap + // + MessageTap + *t = new MessageTap(a.GetDerivation(),f); + + Test(t); + Test(t->scanCallback == f); + Test(t->matchingReceiver == NULL); + Test(t->matchingMessageID == Receiver::AnyMessageID); + + x = -1; + m.messageID = Receiver::AnyMessageID; + t->Scan(NULL,&m); + Test(x == 1); + + x = -1; + t->Scan(&a,&m); + Test(x == 1); + + x = -1; + m.messageID = Alpha::message1ID; + t->Scan(NULL,&m); + Test(x == 1); + + x = -1; + t->Scan(&a,&m); + Test(x == 1); + delete t; + + // + // Check message match tap + // + t = new MessageTap(a.GetDerivation(),f,2,NULL); + + Test(t); + Test(t->scanCallback == f); + Test(t->matchingReceiver == NULL); + Test(t->matchingMessageID == 2); + + x = -1; + m.messageID = Receiver::AnyMessageID; + t->Scan(NULL,&m); + Test(x == -1); + + t->Scan(&a,&m); + Test(x == -1); + + m.messageID = 2; + t->Scan(NULL,&m); + Test(x == 1); + + x = -1; + t->Scan(&a,&m); + Test(x == 1); + delete t; + + // + // Check receiver match tap + // + t = new MessageTap(a.GetDerivation(),f,Receiver::AnyMessageID,&a); + + Test(t); + Test(t->scanCallback == f); + Test(t->matchingReceiver == &a); + Test(t->matchingMessageID == Receiver::AnyMessageID); + + x = -1; + m.messageID = Receiver::AnyMessageID; + t->Scan(NULL,&m); + Test(x == -1); + + t->Scan(&a,&m); + Test(x == 1); + + x = -1; + m.messageID = Beta::message2ID; + t->Scan(NULL,&m); + Test(x == -1); + + t->Scan(&a,&m); + Test(x == 1); + delete t; + + // + // Check message&receiver match tap + // + t = new MessageTap(a.GetDerivation(),f,Beta::message2ID,&a); + + Test(t); + Test(t->scanCallback == f); + Test(t->matchingReceiver == &a); + Test(t->matchingMessageID == Beta::message2ID); + + x = -1; + m.messageID = Receiver::AnyMessageID; + t->Scan(NULL,&m); + Test(x == -1); + + t->Scan(&a,&m); + Test(x == -1); + + m.messageID = Beta::message2ID; + t->Scan(NULL,&m); + Test(x == -1); + + t->Scan(&a,&m); + Test(x == 1); + delete t; +#endif + return True; +} + diff --git a/CODE/RP/MUNGA/RECEIVER.THP b/CODE/RP/MUNGA/RECEIVER.THP new file mode 100644 index 0000000..89d4dbe --- /dev/null +++ b/CODE/RP/MUNGA/RECEIVER.THP @@ -0,0 +1,137 @@ +//===========================================================================// +// File: testclas.hh // +// Project: MUNGA Brick: Dynamic Dispatch, Event and Journalling // +// Contents: defines test classes for use by Dispatch and Events // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/03/94 JMA Initial coding. // +// 11/05/94 JMA Made compatible with GNU C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(TESTCLAS_THP) +# define TESTCLAS_THP) + +# if !defined(RECEIVER_HPP) +# include "receiver.hpp" +# endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Alpha ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Alpha: + public Receiver +{ +protected: + static SharedData + DefaultData; + +public: + int + x; + + enum { + message0ID = Receiver::NextMessageID, + message1ID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Alpha( + ClassID class_ID = TrivialReceiverClassID, + SharedData &vdata = DefaultData); + ~Alpha(); + + void + Method0Handler(Message*); + void + Method1Handler(Message*); + + inline void Method0() + {Message m(message0ID,sizeof(Message)); Dispatch(&m);} + inline void Method1() + {Message m(message1ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Beta ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Beta: + public Alpha +{ +protected: + static SharedData + DefaultData; + +public: + enum { + message2ID=Alpha::NextMessageID, + message3ID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Beta( + ClassID class_id = TrivialReceiverClassID, + SharedData &vdata = DefaultData + ); + ~Beta(); + + void + Method1aHandler(Message*); + void + Method2Handler(Message*); + void + Method3Handler(Message*); + + inline void Method1() + {Message m(message1ID,sizeof(Message)); Dispatch(&m);} + inline void Method2() + {Message m(message2ID,sizeof(Message)); Dispatch(&m);} + inline void Method3() + {Message m(message3ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Gamma ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Gamma: + public Beta +{ +public: + enum { + message4ID=Beta::NextMessageID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Gamma(); + ~Gamma(); + + void + Method4Handler(Message*); + + inline void Method4() + {Message m(message4ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; + +protected: + static SharedData + DefaultData; +}; + +#endif diff --git a/CODE/RP/MUNGA/RECT2D.CPP b/CODE/RP/MUNGA/RECT2D.CPP new file mode 100644 index 0000000..9f667f4 --- /dev/null +++ b/CODE/RP/MUNGA/RECT2D.CPP @@ -0,0 +1,162 @@ +//===========================================================================// +// File: rect2d.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 2/01/95 CPB Initial coding (copied from vector3d.cc) // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RECT2D_HPP) +# include +#endif + +// +//------------------------------------------------------------------------ +// Creators +//------------------------------------------------------------------------ +// +Rectangle2D::Rectangle2D() +{ + MakeEmpty(); // uninitialized rectangles should be "empty" +} + +Rectangle2D::Rectangle2D( + Vector2DOf bl, + Vector2DOf tr + ) +{ + bottomLeft = bl; + topRight = tr; +} + +Rectangle2D::Rectangle2D( + int x1, int y1, int x2, int y2 + ) +{ + bottomLeft.x = x1; + bottomLeft.y = y1; + topRight.x = x2; + topRight.y = y2; +} + +// +//------------------------------------------------------------------------ +// Union (returns bounding rectangle) +//------------------------------------------------------------------------ +// +void + Rectangle2D::Union( + const Rectangle2D& r1, + const Rectangle2D& r2 + ) +{ + Check(this); + Check(&r1); + Check(&r2); + + if (r1.IsEmpty()) + { + if (r2.IsEmpty()) + { + MakeEmpty(); + } + else + { + bottomLeft = r2.bottomLeft; + topRight = r2.topRight; + } + } + else + { + if (r2.IsEmpty()) + { + bottomLeft = r1.bottomLeft; + topRight = r1.topRight; + } + else + { + bottomLeft.x = Min(r1.bottomLeft.x, r2.bottomLeft.x); + bottomLeft.y = Min(r1.bottomLeft.y, r2.bottomLeft.y); + topRight.x = Max(r1.topRight.x, r2.topRight.x); + topRight.y = Max(r1.topRight.y, r2.topRight.y); + } + } +} + +// +//------------------------------------------------------------------------ +// Intersection (returns overlapping section) +//------------------------------------------------------------------------ +// +void + Rectangle2D::Intersection( + const Rectangle2D& r1, + const Rectangle2D& r2 + ) +{ + Check(this); + Check(&r1); + Check(&r2); + + if (r1.IsEmpty()) + { + MakeEmpty(); + } + else + { + if (r2.IsEmpty()) + { + MakeEmpty(); + } + else + { + bottomLeft.x = Max(r1.bottomLeft.x, r2.bottomLeft.x); + bottomLeft.y = Max(r1.bottomLeft.y, r2.bottomLeft.y); + topRight.x = Min(r1.topRight.x, r2.topRight.x); + topRight.y = Min(r1.topRight.y, r2.topRight.y); + } + } +} + +// +//------------------------------------------------------------------------ +// Output stream operator +//------------------------------------------------------------------------ +// +ostream& + operator<<( + ostream& Stream, + const Rectangle2D& r + ) +{ + Check(&r); + return Stream << '(' << r.bottomLeft << ',' << r.topRight << ')'; +} + +// +//------------------------------------------------------------------------ +// TestInstance +//------------------------------------------------------------------------ +// +Logical + Rectangle2D::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) +# include "rect2d.tcp" +#endif + + + + diff --git a/CODE/RP/MUNGA/RECT2D.HPP b/CODE/RP/MUNGA/RECT2D.HPP new file mode 100644 index 0000000..834b52c --- /dev/null +++ b/CODE/RP/MUNGA/RECT2D.HPP @@ -0,0 +1,90 @@ +//===========================================================================// +// File: Rect2D.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for two-dimensional rectangle class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 2/01/95 CPB Initial coding (started from Vector2D.hh) // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RECT2D_HPP) +# define RECT2D_HPP + +# if !defined(VECTOR2D_HPP) +# include +# endif + + // Note that the coordinate system used here is such that + // (0,0) is in the lower left corner. + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rectangle2D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Rectangle2D SIGNATURED + { + public: + Vector2DOf bottomLeft, topRight; + + Rectangle2D(); + Rectangle2D(Vector2DOf bl, Vector2DOf tr); + Rectangle2D(int x1, int y1, int x2, int y2); + ~Rectangle2D() + {} + + Logical + operator==(const Rectangle2D& r) const + {return ((bottomLeft == r.bottomLeft) && (topRight == r.topRight));} + Logical + operator!=(const Rectangle2D& r) const + {return ((bottomLeft != r.bottomLeft) || (topRight != r.topRight));} + + void + Union( + const Rectangle2D& r1, + const Rectangle2D& r2 + ); + + void + Intersection( + const Rectangle2D& r1, + const Rectangle2D& r2 + ); + + void + MakeEmpty() + { + Check(this); + bottomLeft.x = 1; + topRight.x = 0; + } + + Logical + IsEmpty() const + { + if ((bottomLeft.x > topRight.x) || (bottomLeft.y > topRight.y)) + { + return True; + } + else + { + return False; + } + } + + + friend ostream& + operator<<( + ostream& stream, + const Rectangle2D& r + ); + + Logical + TestInstance() const; + + static Logical + TestClass(); + }; +#endif diff --git a/CODE/RP/MUNGA/RECT2D.TCP b/CODE/RP/MUNGA/RECT2D.TCP new file mode 100644 index 0000000..cea24b1 --- /dev/null +++ b/CODE/RP/MUNGA/RECT2D.TCP @@ -0,0 +1,128 @@ +//===========================================================================// +// File: rect2d.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Test code for two-dimensional rectangle class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 2/01/94 CPB Initial coding (copied from vector3d.tst) // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +//########################################################################### +//########################################################################### +// +Logical + Rectangle2D::TestClass() +{ + DEBUG_STREAM << "Starting Rectangle2D test...\n"; + + // + //------------------------------------------------------------------- + // Constructors (and IsEmpty()) + //------------------------------------------------------------------- + // + { + Vector2DOf v1(0,0), v2(1,1); + + Rectangle2D a; + Check(&a); + Test(a.IsEmpty()); + + Rectangle2D b(v1,v2); + Check(&b); + Test(!b.IsEmpty()); + Test(b.bottomLeft == v1); + Test(b.topRight == v2); + + Rectangle2D c(0,1,2,3); + Check(&c); + Test(!c.IsEmpty()); + Test(c.bottomLeft.x == 0); + Test(c.bottomLeft.y == 1); + Test(c.topRight.x == 2); + Test(c.topRight.y == 3); + } + // + //------------------------------------------------------------------- + // Union + //------------------------------------------------------------------- + // + { + Rectangle2D a; + Rectangle2D b(0,0,2,2); + Rectangle2D c(1,1,3,3); + Rectangle2D d(10,10,11,11); + Rectangle2D e(2,3,4,5); + + e.Union(a,a); + Test(e.IsEmpty()); + + e.Union(a,b); + Test(e.bottomLeft == b.bottomLeft); + Test(e.topRight == b.topRight); + + e.Union(b,a); + Test(e.bottomLeft == b.bottomLeft); + Test(e.topRight == b.topRight); + + e.Union(b,c); + Test(e.bottomLeft == b.bottomLeft); + Test(e.topRight == c.topRight); + + e.Union(c,b); + Test(e.bottomLeft == b.bottomLeft); + Test(e.topRight == c.topRight); + + e.Union(b,d); + Test(e.bottomLeft == b.bottomLeft); + Test(e.topRight == d.topRight); + + e.Union(d,b); + Test(e.bottomLeft == b.bottomLeft); + Test(e.topRight == d.topRight); + } + // + //------------------------------------------------------------------- + // Intersection + //------------------------------------------------------------------- + // + { + Rectangle2D a; + Rectangle2D b(0,0,2,2); + Rectangle2D c(1,1,3,3); + Rectangle2D d(10,10,11,11); + Rectangle2D e(2,3,4,5); + + e.Intersection(a,a); + Test(e.IsEmpty()); + + e.Intersection(a,b); + Test(e.IsEmpty()); + + e.Intersection(b,a); + Test(e.IsEmpty()); + + e.Intersection(b,c); + Test(e.bottomLeft == c.bottomLeft); + Test(e.topRight == b.topRight); + + e.Intersection(c,b); + Test(e.bottomLeft == c.bottomLeft); + Test(e.topRight == b.topRight); + + e.Intersection(b,d); + Test(e.IsEmpty()); + + e.Intersection(d,b); + Test(e.IsEmpty()); + } + + return True; +} + + diff --git a/CODE/RP/MUNGA/REGISTRY.CPP b/CODE/RP/MUNGA/REGISTRY.CPP new file mode 100644 index 0000000..25837cc --- /dev/null +++ b/CODE/RP/MUNGA/REGISTRY.CPP @@ -0,0 +1,738 @@ +//===========================================================================// +// File: registry.cc // +// Project: MUNGA Brick: Registry Manager // +// Contents: Interface specification for Registry Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/22/94 ECH Initial coding. // +// 11/29/94 JMA Changed Identities to IDs // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(REGISTRY_HPP) +# include +#endif + +#if !defined(PLAYER_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +// +// Registered classes... +// +#if !defined(TERRAIN_HPP) +# include +#endif + +#if !defined(CULTURAL_HPP) +# include +#endif + +#if !defined(DROPZONE_HPP) +# include +#endif + +#if !defined(EXPLODE_HPP) +# include +#endif + +#if !defined(DOORFRAM_HPP) +# include +#endif + +#if !defined(EYECANDY_HPP) +# include +#endif + +#if !defined(DIRECTOR_HPP) +# include +#endif + +#if !defined(CAMSHIP_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +//############################################################################# +//############################# Registry ################################ +//############################################################################# + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Registry::MessageHandlerEntries[]= +{ + { + Registry::MakeEntityMessageID, + "MakeEntity", + (Registry::Handler)&Registry::MakeEntityMessageHandler + } +}; + +Registry::MessageHandlerSet + Registry::MessageHandlers( + ELEMENTS(Registry::MessageHandlerEntries), + Registry::MessageHandlerEntries, + Receiver::MessageHandlers + ); + +//############################################################################# +// Shared Data support +// +Derivation + Registry::ClassDerivations( + Receiver::ClassDerivations, + "Registry" + ); + +Registry::SharedData + Registry::DefaultData( + Registry::ClassDerivations, + Registry::MessageHandlers + ); + +// +//############################################################################# +// Registry +//############################################################################# +// +Registry::Registry( + ClassID class_ID, + SharedData &shared_data +): + Receiver(class_ID, shared_data) +{ +} + +// +//############################################################################# +// Registry +//############################################################################# +// +Registry::Registry(): + Receiver(TrivialReceiverClassID, DefaultData) +{ +} + +// +//############################################################################# +// ~Registry +//############################################################################# +// +Registry::~Registry() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Registry::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +// +//############################################################################# +// MakeEntity +//############################################################################# +// +Entity* + Registry::MakeEntity(Entity::MakeMessage *message) +{ + Check(this); + Check(message); + + Entity::SharedData *static_data = GetStaticData(message->classToCreate); + + if (static_data != NULL) + { + Check(static_data); + Check_Pointer(static_data->makeHandler); + return (*static_data->makeHandler)(message); + } + return NULL; +} + +// +//############################################################################# +// MakeTransferedEntity +//############################################################################# +// +Entity* + Registry::MakeTransferedEntity( + HostID, + EntityID, + void* + ) +{ + Fail("Registry::MakeTransferedEntity - under construction"); + return NULL; +} + +// +//############################################################################# +// MakeEntityReplacement +//############################################################################# +// +Entity* + Registry::MakeEntityReplacement( + HostID, + EntityID + ) +{ + Fail("Registry::MakeEntityReplacement - under construction"); + return NULL; +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Entity::SharedData* + Registry::GetStaticData(ClassID class_ID) +{ + switch (class_ID) + { + case TrivialEntityClassID: + return &Entity::DefaultData; + case DropZoneClassID: + return &DropZone::DefaultData; + case TerrainClassID: + return &Terrain::DefaultData; + case CulturalIconClassID: + return &CulturalIcon::DefaultData; + case LandmarkClassID: + return &Landmark::DefaultData; + case TeamClassID: + return &Team::DefaultData; + case UnscalableTerrainClassID: + return &UnscalableTerrain::DefaultData; + case ExplosionClassID: + return &Explosion::DefaultData; + case PlayerClassID: + return &Player::DefaultData; + case DoorFrameClassID: + return &DoorFrame::DefaultData; + case EyeCandyClassID: + return &EyeCandy::DefaultData; + case CameraShipClassID: + return &CameraShip::DefaultData; + case CameraDirectorClassID: + return &CameraDirector::DefaultData; + default: + return NULL; + } +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Player* + Registry::MakePlayer(Mission *mission) +{ + Check(mission); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See if we are a CameraShip + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Enumeration player_flags = Player::DefaultFlags; + if (!strcmp(mission->GetGameModel(), "camera")) + { + player_flags |= Player::CameraShipPlayerFlag; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See if we are a MissionReview, CameraShipHost + // GameMachine CameraShip or regular Player! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application); + HostManager *host_mgr = application->GetHostManager(); + Host *host_ptr = host_mgr->GetLocalHost(); + Check(host_ptr); + HostType host_type = host_ptr->GetHostType(); + + switch(host_type) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make A Player Which is a GameMachine Host + // i.e. VTV, Mech, CameraShip w/controls + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + case GameMachineHostType: + { + Player::MakeMessage make_player( + Player::MakeMessageID, + sizeof(Player::MakeMessage), + PlayerClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + player_flags, + Origin::Identity, + mission->GetPlayerBitmapIndex() + ); + return new Player(&make_player); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make A CameraShip Or Mission Review + // Not a CameraShip to Run on a POD! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + case CameraShipHostType: + case MissionReviewHostType: + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Add any extra flags for a director + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + player_flags |= CameraDirector::DefaultFlags; + CameraDirector::MakeMessage create_director( + CameraDirector::MakeMessageID, + sizeof(CameraDirector::MakeMessage), + CameraDirectorClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + player_flags, + Origin::Identity, + mission->GetPlayerBitmapIndex() + ); + return new CameraDirector(&create_director); + } + } + return NULL; +} + +// +//############################################################################# +// MakeEntityMessageHandler +//############################################################################# +// +void + Registry::MakeEntityMessageHandler(MakeEntityMessage *message) +{ + Check(this); + Check(message); + Verify(message->messageID == MakeEntityMessageID); + + // + // Extract the make message + // + MemoryStream + memory_stream( + message, + message->messageLength + ); + Entity::MakeMessage + *make_message; + + memory_stream.AdvancePointer(sizeof(MakeEntityMessage)); + make_message = Cast_Object(Entity::MakeMessage*, memory_stream.GetPointer()); + Check(make_message); + + // + // Make the entity + // +#if DEBUG_LEVEL>0 + Entity *entity = MakeEntity(make_message); + if (entity) + { + Register_Object(entity); + } +#else + MakeEntity(make_message); +#endif +} + +// +//############################################################################# +// CreateStaticObjectStreamResource +//############################################################################# +// +ResourceDescription::ResourceID + Registry::CreateStaticObjectStreamResource( + NotationFile *notation_file, + ResourceFile *resource_file + ) +{ + Check(notation_file); + Check(resource_file); + + // + //-------------------------------------------------------------------------- + // Build the static object stream + //-------------------------------------------------------------------------- + // + RegistryObjectStream static_object_stream; + + Check(&static_object_stream); + static_object_stream.BuildFromNotationFile( + notation_file, + resource_file + ); + + // + //-------------------------------------------------------------------------- + // Add the resource + //-------------------------------------------------------------------------- + // + ResourceDescription *res_description; + + res_description = + resource_file->AddResourceMemoryStream( + "RegistryStaticObjectStream", + ResourceDescription::RegistryStaticObjectStreamResourceType, + 1, + ResourceDescription::Preload, + &static_object_stream + ); + Check(res_description); + return res_description->resourceID; +} + +// +//############################################################################# +// LoadStaticObjectStreamResource +//############################################################################# +// +void + Registry::LoadStaticObjectStreamResource() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Create static objects + //-------------------------------------------------------------------------- + // + +#if 0 + // + // Get static object stream resource + // + ResourceDescription *resource_description; + + Check(application); + Check(application->GetResourceFile()); + resource_description = + application->GetResourceFile()->FindResourceDescription( + "RegistryStaticObjectStream", + ResourceDescription::RegistryStaticObjectStreamResourceType + ); + + if (resource_description != NULL) + { + Check(resource_description); + + // + // Parse the static object stream + // + RegistryObjectStream static_object_stream(resource_description); + + Check(&static_object_stream); + static_object_stream.CreateObjects(); + } +#else + // + // Load all static object streams + // + ResourceFile *resource_file; + ResourceDescription::ResourceID index, max_resource_ID; + + Check(application); + resource_file = application->GetResourceFile(); + Check(resource_file); + max_resource_ID = resource_file->GetMaxResourceID(); + + for (index = 0; index <= max_resource_ID; index++) + { + ResourceDescription *resource_description = + resource_file->FindResourceDescription(index); + if (resource_description) + { + Check(resource_description); + + // + // Load the static object streams + // + if ( + resource_description->resourceType == + ResourceDescription::RegistryStaticObjectStreamResourceType + ) + { + resource_description->Lock(); + // + // Parse the static object stream + // + RegistryObjectStream static_object_stream(resource_description); + + Check(&static_object_stream); + static_object_stream.CreateObjects(); + resource_description->Unlock(); + } + } + } + resource_file->ReleaseUnlockedResources(); +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~ Registry__MakeEntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Registry__MakeEntityMessage +//############################################################################# +// +Registry__MakeEntityMessage::Registry__MakeEntityMessage(size_t total_length): + Receiver::Message( + Registry::MakeEntityMessageID, + total_length + ) +{ +} + +// +//############################################################################# +// Make +//############################################################################# +// +Registry__MakeEntityMessage* + Registry__MakeEntityMessage::Make(Entity::MakeMessage *make_message) +{ + Check(make_message); + + // + // Allocate memory for the make message + // + size_t + total_length; + void + *buffer; + + total_length = + sizeof (Registry__MakeEntityMessage) + make_message->messageLength; + buffer = new unsigned char[total_length]; + Check_Pointer(buffer); + + // + // Build the make message + // + MemoryStream + memory_stream(buffer, total_length); + Registry__MakeEntityMessage + *make_entity_message; + + make_entity_message = + new (memory_stream.GetPointer()) Registry__MakeEntityMessage(total_length); + Check(make_entity_message); + + memory_stream.AdvancePointer(sizeof(Registry__MakeEntityMessage)); + Mem_Copy( + memory_stream.GetPointer(), + make_message, + make_message->messageLength, + memory_stream.GetBytesRemaining() + ); + + return make_entity_message; +} + +//############################################################################# +//####################### RegistryObjectStream ########################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +RegistryObjectStream::RegistryObjectStream( + ResourceDescription *resource_description +): + PlugStream(resource_description) +{ +} + +// +//############################################################################# +//############################################################################# +// +RegistryObjectStream::RegistryObjectStream() +{ +} + +// +//############################################################################# +//############################################################################# +// +RegistryObjectStream::~RegistryObjectStream() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + RegistryObjectStream::TestInstance() const +{ + PlugStream::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +RegisteredClass* + RegistryObjectStream::MakeObjectImplementation(Enumeration class_ID) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + + RegisteredClass *object; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::ExplosionResourceTableClassID: + object = new ExplosionResourceTable(this); + break; + + // + // Inherited behavior + // + default: + object = PlugStream::MakeObjectImplementation(class_ID); + break; + } + return object; +} + +// +//############################################################################# +//############################################################################# +// +void + RegistryObjectStream::CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ) +{ + Check(this); + Check(object); + Verify(object_ID != NullObjectID); + + // + // Decide which index to add object to + // + switch (object->GetClassID()) + { + // + // Static resources ... + // + case RegisteredClass::ExplosionResourceTableClassID: + AddGlobalPlug(Cast_Object(Plug*, object), object_ID); + break; + + default: + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + RegistryObjectStream::BuildFromPageImplementation( + NameList *name_list, + Enumeration class_ID_enumeration, + ObjectID object_ID + ) +{ + Check(this); + Verify(class_ID_enumeration != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + + RegisteredClass::ClassID + class_ID = (RegisteredClass::ClassID)class_ID_enumeration; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::ExplosionResourceTableClassID: + ExplosionResourceTable::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Inherited behavior + // + default: + PlugStream::BuildFromPageImplementation(name_list, class_ID, object_ID); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + RegistryObjectStream::BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name + ) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + Check(&object_name); + + // + // Decide which index to add object to + // + switch (class_ID) + { + case RegisteredClass::ExplosionResourceTableClassID: + AddGlobalObjectID(object_ID, object_name); + break; + + default: + break; + } +} + + diff --git a/CODE/RP/MUNGA/REGISTRY.HPP b/CODE/RP/MUNGA/REGISTRY.HPP new file mode 100644 index 0000000..c3694ff --- /dev/null +++ b/CODE/RP/MUNGA/REGISTRY.HPP @@ -0,0 +1,237 @@ +//===========================================================================// +// File: registry.hh // +// Project: MUNGA Brick: Registry Manager // +// Contents: Interface specification for Registry Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/22/94 ECH Initial coding. // +// 11/29/94 JMA Changed Identities to IDs // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(REGISTRY_HPP) +# define REGISTRY_HPP + +# if !defined(HOST_HPP) +# include +# endif + +# if !defined(OBJSTRM_HPP) +# include +# endif + +# if !defined(ENTITY_HPP) && 0 +# include +# endif + +# if !defined(ENTITYID_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + + //########################################################################## + //############################ Registry ############################## + //########################################################################## + + class Player; + class Registry__MakeEntityMessage; + class Entity; + class Entity__MakeMessage; + class Entity__SharedData; + + class Registry: + public Receiver + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + Registry( + ClassID class_ID, + SharedData &shared_data + ); + Registry(); + ~Registry(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Entity creation + // + public: + // + //----------------------------------------------------------------------- + // MakeEntity + //----------------------------------------------------------------------- + // + Entity* + MakeEntity(Entity__MakeMessage *message); + + // + //----------------------------------------------------------------------- + // MakeTransferedEntity + // + // The registry creates an entity on this machine which + // represents the transfer of ownership from the old host to this + // host. + //----------------------------------------------------------------------- + // + Entity* + MakeTransferedEntity( + HostID old_entity_host, + EntityID old_entity_ID, + void *old_entity_state_data + ); + + // + //----------------------------------------------------------------------- + // MakeEntityReplacement + // + // If a host abnormally terminates there may be replicants + // hanging unattended by updates. The host manager attempts + // to create a replacement for the lost entity using the + // replicant as a recipe for the replacement. + //----------------------------------------------------------------------- + // + Entity* + MakeEntityReplacement( + HostID old_entity_host, + EntityID replicant_entity_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Entity data access + // + public: + // + //----------------------------------------------------------------------- + // GetStaticData + // + // Provides an interface by which the static data for a class + // may be accessed. + //----------------------------------------------------------------------- + // + virtual Entity__SharedData* + GetStaticData(ClassID entity_class); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Player creation + // + public: + // + //----------------------------------------------------------------------- + // Create the player object + //----------------------------------------------------------------------- + // + virtual Player* + MakePlayer(Mission *mission); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum { + MakeEntityMessageID = Receiver::NextMessageID, + NextMessageID + }; + + typedef Registry__MakeEntityMessage + MakeEntityMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void + MakeEntityMessageHandler(MakeEntityMessage *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Static object methods + // + public: + static ResourceDescription::ResourceID + CreateStaticObjectStreamResource( + NotationFile *notation_file, + ResourceFile *resource_file + ); + + void + LoadStaticObjectStreamResource(); + }; + + //~~~~~~~~~~~~~~~~~~~~~ Registry__MakeEntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~ + + class Registry__MakeEntityMessage: + public Receiver::Message + { + public: + Registry__MakeEntityMessage(size_t total_length); + + static Registry__MakeEntityMessage* + Make(Entity__MakeMessage *message); + }; + + //########################################################################## + //##################### RegistryObjectStream ######################### + //########################################################################## + + class RegistryObjectStream: + public PlugStream + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + RegistryObjectStream(); + RegistryObjectStream(ResourceDescription *resource_description); + ~RegistryObjectStream(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Implementations + // + private: + RegisteredClass* + MakeObjectImplementation(Enumeration class_ID); + + void + CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ); + + void + BuildFromPageImplementation( + NameList *entry_list, + Enumeration class_ID, + ObjectID object_ID + ); + + void + BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name_string + ); + }; + +#endif + diff --git a/CODE/RP/MUNGA/RENDERER.CPP b/CODE/RP/MUNGA/RENDERER.CPP new file mode 100644 index 0000000..fb6fb91 --- /dev/null +++ b/CODE/RP/MUNGA/RENDERER.CPP @@ -0,0 +1,1069 @@ +//===========================================================================// +// File: renderer.cc // +// Project: MUNGA Brick: Renderer Manager // +// Contents: Interface specification Renderer and Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RENDERER_HPP) +# include +#endif + +#if !defined(RNDORGN_HPP) +# include +#endif + +#if !defined(EXPLODE_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +#if !defined(SUBSYSTM_HPP) + #include +#endif + +//############################################################################# +//############################ Renderer ################################# +//############################################################################# + +const RendererRate DefaultRendererRate = 30.0f; +const RendererComplexity MaxRendererComplexity = 3.0f; +const RendererComplexity MinRendererComplexity = 0.0f; +const RendererFrameBudget DefaultRendererFrameBudget = 0.14f; //0.12f; // 0.16f; + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Renderer::MessageHandlerEntries[]= +{ + { + Renderer::NotifyOfNewInterestingEntityMessageID, + "NotifyOfNewInterestingEntity", + (Renderer::Handler)&Renderer::NotifyOfNewInterestingEntityMessageHandler + }, + { + Renderer::NotifyOfBecomingUninterestingEntityMessageID, + "NotifyOfBecomingUninterestingEntity", + (Renderer::Handler)&Renderer::NotifyOfBecomingUninterestingEntityMessageHandler + }, + { + Renderer::StartEntityEffectMessageID, + "StartEntityEffect", + (Renderer::Handler)&Renderer::StartEntityEffectMessageHandler + }, + { + Renderer::StopAllEntityEffectsMessageID, + "StopAllEntityEffects", + (Renderer::Handler)&Renderer::StopAllEntityEffectsMessageHandler + }, + { + Renderer::StartEntityAlarmMessageID, + "StartEntityAlarm", + (Renderer::Handler)&Renderer::StartEntityAlarmMessageHandler + }, + { + Renderer::StopEntityAlarmMessageID, + "StopEntityAlarm", + (Renderer::Handler)&Renderer::StopEntityAlarmMessageHandler + } +}; + +Renderer::MessageHandlerSet + Renderer::MessageHandlers( + ELEMENTS(Renderer::MessageHandlerEntries), + Renderer::MessageHandlerEntries, + Receiver::MessageHandlers + ); + +//############################################################################# +// Shared Data Support +// +Derivation + Renderer::ClassDerivations( + Receiver::ClassDerivations, + "Renderer" + ); + +Renderer::SharedData + Renderer::DefaultData( + Renderer::ClassDerivations, + Renderer::MessageHandlers + ); + +// +//############################################################################# +// Renderer +//############################################################################# +// +Renderer::Renderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration, + ClassID class_ID, + SharedData &virtual_data +): + Receiver(class_ID, virtual_data), + rendererOriginSocket(NULL), + entitySocket(NULL) +{ + rendererStatus = InactiveRendererStatus; + + calibrationRate = calibration_rate; + calibrationFrameDuration = 1.0f / calibration_rate; + nextRenderTime = 0.0f; + + Verify(MinRendererComplexity < calibration_complexity); + Verify(calibration_complexity <= MaxRendererComplexity); + calibrationComplexity = calibration_complexity; + + calibrationPriority = calibration_priority; + interestType = interest_type; + depthCalibration = depth_calibration; + framePercentBudget = DefaultRendererFrameBudget; + Check_Fpu(); +} + +// +//############################################################################# +// ~Renderer +//############################################################################# +// +Renderer::~Renderer() +{ + UnlinkFromEntity(); + Check_Fpu(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Renderer::TestInstance() const +{ + if (!IsDerivedFrom(ClassDerivations)) + { + return False; + } + Check(&rendererOriginSocket); + Check(&entitySocket); + return True; +} + +// +//############################################################################# +// LinkToEntity +//############################################################################# +// +void + Renderer::LinkToEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + //-------------------------------------------------------------------------- + // Unlink from current entity and add new entity + //-------------------------------------------------------------------------- + // + UnlinkFromEntity(); + entitySocket.Add(entity); + + // + //-------------------------------------------------------------------------- + // Make an interest origin for the given entity + //-------------------------------------------------------------------------- + // + RendererOrigin *rendererOrigin; + + rendererOrigin = + new RendererOrigin( + this, + entity, + interestType, + depthCalibration + ); + Register_Object(rendererOrigin); + + Check(application); + application->GetInterestManager()->AdoptInterestOrigin(rendererOrigin); + rendererOriginSocket.Add(rendererOrigin); + Check_Fpu(); +} + +// +//############################################################################# +// UnlinkFromEntity +//############################################################################# +// +void + Renderer::UnlinkFromEntity() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Delete current interest origin + //-------------------------------------------------------------------------- + // + RendererOrigin *rendererOrigin; + + if ((rendererOrigin = rendererOriginSocket.GetCurrent()) != NULL) + { + Check(rendererOrigin); + + // + // Remove entity from socket + // + entitySocket.Remove(); + + // + // Delete the interest origin + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->OrphanInterestOrigin(rendererOrigin); + Unregister_Object(rendererOrigin); + delete rendererOrigin; + } + Check_Fpu(); +} + +// +//############################################################################# +// LoadMission +//############################################################################# +// +void + Renderer::LoadMission(Mission *mission) +{ + Check(this); + + Verify(rendererStatus == InactiveRendererStatus); + rendererStatus = LoadingRendererStatus; + nextRenderTime = Now(); + + Check(application); + application->GetRendererManager()->StartRenderer(this); + LoadMissionImplementation(mission); + Check_Fpu(); +} + +// +//############################################################################# +// Shutdown +//############################################################################# +// +void + Renderer::Shutdown() +{ + Check(this); + + // + //------------------------------------------------- + // Shutdown and unhook the renderer if it is active + //------------------------------------------------- + // + if (rendererStatus == InactiveRendererStatus) + { + return; + } + + rendererStatus = InactiveRendererStatus; + Check(application); + application->GetRendererManager()->StopRenderer(this); + + ShutdownImplementation(); + Check_Fpu(); +} + +// +//############################################################################# +// SetRendererStatusToRunning +//############################################################################# +// +void + Renderer::SetRendererStatusToRunning() +{ + Verify(rendererStatus == LoadingRendererStatus); + rendererStatus = RunningRendererStatus; + Check_Fpu(); +} + +// +//############################################################################# +// UpdateRendererOrigin +//############################################################################# +// +void + Renderer::UpdateInterestOrigin(Time target_render_time) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // If the renderer is inactive, skip it + //-------------------------------------------------------------------------- + // + if (rendererStatus == InactiveRendererStatus) + return; + + // + //-------------------------------------------------------------------------- + // Does the renderer need to run this frame to meet its frame rate? + //-------------------------------------------------------------------------- + // + if (nextRenderTime > target_render_time) + return; + + // + //-------------------------------------------------------------------------- + // Update the interest origin + //-------------------------------------------------------------------------- + // + Entity *entity; + RendererOrigin *rendererOrigin; + + entity = entitySocket.GetCurrent(); + Check(entity); + rendererOrigin = rendererOriginSocket.GetCurrent(); + Check(rendererOrigin); + rendererOrigin->Update(entity->GetInterestZoneID()); + Check_Fpu(); +} + +// +//############################################################################# +// Execute +//############################################################################# +// +void + Renderer::Execute( + Time target_render_time, + RendererComplexity complexity_update + ) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // If the renderer is suspended, skip it + //-------------------------------------------------------------------------- + // + if (rendererStatus == InactiveRendererStatus) + return; + + // + //-------------------------------------------------------------------------- + // Does the renderer need to run this frame to meet its frame rate? + //-------------------------------------------------------------------------- + // + if (nextRenderTime > target_render_time) + return; + // nextRenderTime += calibrationFrameDuration; + nextRenderTime = Now(); + nextRenderTime += calibrationFrameDuration; + + // + //-------------------------------------------------------------------------- + // Keep track of renderers frame budget + //-------------------------------------------------------------------------- + // + RendererFrameBudget start_percent; + RendererFrameBudget end_percent; + + start_percent = Get_Frame_Percent_Used(); + end_percent = start_percent + framePercentBudget; + Clamp(end_percent, 0.0f, 1.0f); + + // + //-------------------------------------------------------------------------- + // Get interest orign + //-------------------------------------------------------------------------- + // + RendererOrigin *rendererOrigin; + + rendererOrigin = rendererOriginSocket.GetCurrent(); + Check(rendererOrigin); + + // + //-------------------------------------------------------------------------- + // Get iterators for the renderers interest origin and execute + // renderer + //-------------------------------------------------------------------------- + // + RendererOrigin::InterestingEntityIterator + interesting_entity_iterator(rendererOrigin); + + Check(&interesting_entity_iterator); + + ExecuteImplementation( + complexity_update, + &interesting_entity_iterator + ); + + // + //-------------------------------------------------------------------------- + // If the renderer is under budget then run background if available + //-------------------------------------------------------------------------- + // + RendererFrameBudget current_frame_use; + for ( + current_frame_use = Get_Frame_Percent_Used(); + (start_percent < current_frame_use) && (current_frame_use < end_percent); + current_frame_use = Get_Frame_Percent_Used() + ) + { + if (!ExecuteBackground()) + break; + } + + Check_Fpu(); +} + +// +//############################################################################# +// NotifyOfNewInterestingEntityMessageHandler +//############################################################################# +// +void + Renderer::NotifyOfNewInterestingEntityMessageHandler( + NotifyOfNewInterestingEntityMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == NotifyOfNewInterestingEntityMessageID); + + Entity *entity; + + if ((entity = message->GetInterestingEntity()) != NULL) + { + Check(entity); + NotifyOfNewInterestingEntity(entity); + } + Check_Fpu(); +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntityMessageHandler +//############################################################################# +// +void + Renderer::NotifyOfBecomingUninterestingEntityMessageHandler( + NotifyOfBecomingUninterestingEntityMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == NotifyOfBecomingUninterestingEntityMessageID); + + NotifyOfBecomingUninterestingEntity(message->GetUninterestingEntity()); + Check_Fpu(); +} + +// +//############################################################################# +// StartEntityEffectMessageHandler +//############################################################################# +// +void + Renderer::StartEntityEffectMessageHandler( + StartEntityEffectMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StartEntityEffectMessageID); + + // + //-------------------------------------------------------------------------- + // If the entity does not exists then return + //-------------------------------------------------------------------------- + // + Entity *entity; + if ((entity = message->GetEntity()) == NULL) + return; + Check(entity); + + // + //-------------------------------------------------------------------------- + // Get the effect model resource + //-------------------------------------------------------------------------- + // + ResourceDescription::ResourceID effect_resource_ID; + ResourceDescription *resource_description; + Explosion::ModelResource *model_resource; + + effect_resource_ID = message->GetResourceID(); + Check(application); + Check(application->GetResourceFile()); + resource_description = + application->GetResourceFile()->SearchList( + effect_resource_ID, + ResourceDescription::GameModelResourceType + ); + Check(resource_description); + resource_description->Lock(); + model_resource = + (Explosion::ModelResource*)resource_description->resourceAddress; + Check_Pointer(model_resource); + + // + //-------------------------------------------------------------------------- + // If an explosion resource table is being used then use it to set + // the resource + //-------------------------------------------------------------------------- + // + if (model_resource->resourceTableObjectID != NullObjectID) + { + // + // Get resource table pointer, + // Then set the appropriate resource ID + // + Plug *plug; + ExplosionResourceTable *resource_table; + ResourceDescription::ResourceID new_resource_ID; + + plug = PlugStreamManager::FindPlug(model_resource->resourceTableObjectID); + resource_table = Cast_Object(ExplosionResourceTable*, plug); + Check(resource_table); + new_resource_ID = resource_table->FindResourceID(entity); + if (new_resource_ID != ResourceDescription::NullResourceID) + { + effect_resource_ID = new_resource_ID; + } + } + + // + //-------------------------------------------------------------------------- + // Call the start effect implementation + //-------------------------------------------------------------------------- + // + StartEntityEffectImplementation( + entity, + message->GetDamageZone(), + effect_resource_ID + ); + resource_description->Unlock(); +} + +// +//############################################################################# +// StopAllEntityEffectsMessageHandler +//############################################################################# +// +void + Renderer::StopAllEntityEffectsMessageHandler( + StopAllEntityEffectsMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StopAllEntityEffectsMessageID); + + Entity *entity; + if ((entity = message->GetEntity()) != NULL) + { + Check(entity); + StopAllEntityEffectsImplementation(entity); + } +} + +// +//############################################################################# +// StartEntityAlarmMessageHandler +//############################################################################# +// +void + Renderer::StartEntityAlarmMessageHandler( + StartEntityAlarmMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StartEntityAlarmMessageID); + + Entity *entity; + if ((entity = message->GetEntity()) != NULL) + { + Check(entity); + StartEntityAlarmImplementation( + entity, + message->GetSubsystem(), + message->GetCondition(), + message->GetResourceID() + ); + } +} + +// +//############################################################################# +// StopEntityAlarmMessageHandler +//############################################################################# +// +void + Renderer::StopEntityAlarmMessageHandler( + StopEntityAlarmMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StopEntityAlarmMessageID); + + Entity *entity; + if ((entity = message->GetEntity()) != NULL) + { + Check(entity); + StopEntityAlarmImplementation( + entity, + message->GetSubsystem(), + message->GetCondition() + ); + } +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +void + Renderer::ExecuteImplementation( + RendererComplexity, + RendererOrigin::InterestingEntityIterator* + ) +{ + Fail("Renderer::ExecuteImplementation - Should never reach here"); +} + +// +//############################################################################# +// LoadMissionImplementation +//############################################################################# +// +void + Renderer::LoadMissionImplementation(Mission*) +{ + Fail("Renderer::LoadMissionImplementation - Should never reach here"); +} + +// +//############################################################################# +// ShutdownImplementation +//############################################################################# +// +void + Renderer::ShutdownImplementation() +{ + Fail("Renderer::ShutdownImplementation - Should never reach here"); +} + +//############################################################################# +//######################### RendererManager ############################# +//############################################################################# + +// +//############################################################################# +// RendererManager +//############################################################################# +// +RendererManager::RendererManager(): + Receiver(RendererManagerClassID, DefaultData), + renderers(NULL) +{ +} + +// +//############################################################################# +// ~RendererManager +//############################################################################# +// +RendererManager::~RendererManager() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + RendererManager::TestInstance() const +{ + Receiver::TestInstance(); + Check(&renderers); + Check_Fpu(); + return True; +} + +// +//############################################################################# +// StartRenderer +//############################################################################# +// +void + RendererManager::StartRenderer(Renderer *renderer) +{ + Check(this); + Check(renderer); + + #if DEBUG_LEVEL>0 + SChainIterator iterator(&renderers); + Verify(iterator.IsPlugMember(renderer) == False); + #endif + + renderers.Add(renderer); + Check_Fpu(); +} + +// +//############################################################################# +// StopRenderer +//############################################################################# +// +void + RendererManager::StopRenderer(Renderer *renderer) +{ + Check(this); + Check(renderer); + + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&renderers); + Verify(iterator.IsPlugMember(renderer) == True); + } + #endif + + SChainIteratorOf iterator(&renderers); + iterator.RemovePlug(renderer); + Check_Fpu(); +} + +// +//############################################################################# +// AreRenderersRunning +//############################################################################# +// +Logical + RendererManager::AreRenderersRunning() +{ + Check(this); + + Renderer + *renderer; + SChainIteratorOf + renderers_iterator(&renderers); + + if (renderers_iterator.GetCurrent() == NULL) + return False; + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + if (renderer->GetRendererStatus() != RunningRendererStatus) + return False; + } + Check_Fpu(); + return True; +} + +// +//############################################################################# +// UpdateInterestOrigins +//############################################################################# +// +void + RendererManager::UpdateInterestOrigins(Time target_render_time) +{ + Check(this); + + // + // HACK - under construction, does not include complexity or priorities + // + Renderer + *renderer; + SChainIteratorOf + renderers_iterator(&renderers); + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + renderer->UpdateInterestOrigin(target_render_time); + } + Check_Fpu(); +} + +// +//############################################################################# +// Execute +//############################################################################# +// +void + RendererManager::Execute( + Time target_render_time, + Time, + Time + ) +{ + Check(this); + + // + // HACK - under construction, does not include complexity or priorities + // + Renderer + *renderer; + RendererComplexity + complexity_update; + SChainIteratorOf + renderers_iterator(&renderers); + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + + // + // Calculate current complexity + // HACK - use calibration complexity for now + // + complexity_update = renderer->GetCalibrationComplexity(); + + // + // Execute + // + renderer->Execute(target_render_time, complexity_update); + } + Check_Fpu(); +} + +// +//############################################################################# +// CompleteCycles +//############################################################################# +// +void + RendererManager::CompleteCycles() +{ + Check(this); + + Renderer + *renderer; + SChainIteratorOf + renderers_iterator(&renderers); + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + renderer->CompleteCycle(); + } + Check_Fpu(); +} + +// +//############################################################################# +// PostRendererEvent +//############################################################################# +// +void + RendererManager::PostRendererEvent( + Entity *entity, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(message); + + Renderer + *renderer; + SChainIteratorOf + renderers_iterator(&renderers); + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->PostRendererEvent( + entity, + renderer, + message + ); + } +} + +//~~~~~~~~~~~~~~~~~ Renderer__NotifyOfNewInterestingEntityMessage ~~~~~~~~~~~~~ + +Renderer__NotifyOfNewInterestingEntityMessage:: + Renderer__NotifyOfNewInterestingEntityMessage( + Entity *interesting_entity + ): + Receiver::Message( + Renderer::NotifyOfNewInterestingEntityMessageID, + sizeof(Renderer__NotifyOfNewInterestingEntityMessage) + ) +{ + Check(interesting_entity); + entityID = interesting_entity->GetEntityID(); + Check_Fpu(); +} + +Entity* + Renderer__NotifyOfNewInterestingEntityMessage::GetInterestingEntity() +{ + Check(this); + Check(application); + Check(application->GetHostManager()); + + Check_Fpu(); + return application->GetHostManager()->GetEntityPointer(entityID); +} + +//~~~~~~~~~~~~~~ Renderer__NotifyOfBecomingUninterestingEntityMessage ~~~~~~~~~ + +Renderer__NotifyOfBecomingUninterestingEntityMessage:: + Renderer__NotifyOfBecomingUninterestingEntityMessage( + Entity *uninteresting_entity + ): + Receiver::Message( + Renderer::NotifyOfBecomingUninterestingEntityMessageID, + sizeof(Renderer__NotifyOfBecomingUninterestingEntityMessage) + ) +{ + uninterestingEntity = uninteresting_entity; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~ Renderer__EntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__EntityMessage::Renderer__EntityMessage( + Receiver::MessageID message_ID, + size_t message_size, + Entity *entity +): + Receiver::Message( + message_ID, + message_size + ) +{ + Check(entity); + entityID = entity->GetEntityID(); +} + +Entity* + Renderer__EntityMessage::GetEntity() +{ + Check(this); + Check(application); + Check(application->GetHostManager()); + return application->GetHostManager()->GetEntityPointer(entityID); +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityEffectMessage ~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__StartEntityEffectMessage::Renderer__StartEntityEffectMessage( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID +): + Renderer__EntityMessage( + Renderer::StartEntityEffectMessageID, + sizeof(Renderer__StartEntityEffectMessage), + entity + ) +{ + Check(damage_zone); + Verify(resource_ID != ResourceDescription::NullResourceID); + damageZone = damage_zone; + resourceID = resource_ID; +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StopAllEntityEffectsMessage ~~~~~~~~~~~~~~~~~~~~ + +Renderer__StopAllEntityEffectsMessage::Renderer__StopAllEntityEffectsMessage( + Entity *entity +): + Renderer__EntityMessage( + Renderer::StopAllEntityEffectsMessageID, + sizeof(Renderer__StopAllEntityEffectsMessage), + entity + ) +{ +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__StartEntityAlarmMessage::Renderer__StartEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition, + ResourceDescription::ResourceID resource_ID +): + Renderer__EntityMessage( + Renderer::StartEntityAlarmMessageID, + sizeof(Renderer__StartEntityAlarmMessage), + entity + ) +{ + Check(alarm_subsystem); + #if DEBUG_LEVEL>0 + if (resource_ID == ResourceDescription::NullResourceID) + { + Dump(alarm_subsystem->GetClassID()); + Dump(alarm_condition); + } + #endif + Warn(resource_ID == ResourceDescription::NullResourceID); // HACK - ECH Why is this sometimes NULL? + subsystem = alarm_subsystem; + condition = alarm_condition; + resourceID = resource_ID; +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StopEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__StopEntityAlarmMessage::Renderer__StopEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition +): + Renderer__EntityMessage( + Renderer::StopEntityAlarmMessageID, + sizeof(Renderer__StopEntityAlarmMessage), + entity + ) +{ + Check(alarm_subsystem); + subsystem = alarm_subsystem; + condition = alarm_condition; +} + +#ifdef TEST_CLASS +# include "renderer.tcp" +#endif + diff --git a/CODE/RP/MUNGA/RENDERER.HPP b/CODE/RP/MUNGA/RENDERER.HPP new file mode 100644 index 0000000..afc8dc5 --- /dev/null +++ b/CODE/RP/MUNGA/RENDERER.HPP @@ -0,0 +1,782 @@ +//===========================================================================// +// File: renderer.hpp // +// Project: MUNGA Brick: Renderer Manager // +// Contents: Interface specification Renderer and Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/21/94 ECH Initial coding. // +// 01/22/95 ECH Added NotifyOfBecomingUninterestingEntity // +// 05/25/95 CPB Moved GetLinkedEntity into public accessability for gauges // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RENDERER_HPP) +# define RENDERER_HPP + +# if !defined(INTEREST_HPP) +# include +# endif + +# if !defined(RNDORGN_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + + class DamageZone; + class Subsystem; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ Renderer support types ~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef Scalar RendererRate; + extern const RendererRate DefaultRendererRate; + + typedef Scalar RendererComplexity; + extern const RendererComplexity MaxRendererComplexity; + extern const RendererComplexity MinRendererComplexity; + + typedef Scalar RendererFrameBudget; + extern const RendererFrameBudget DefaultRendererFrameBudget; + + enum RendererPriority + { + LowRendererPriority = 0, + DefaultRendererPriority, + HighRendererPriority + }; + + enum RendererStatus + { + InactiveRendererStatus, + LoadingRendererStatus, + RunningRendererStatus + }; + + //########################################################################## + //########################### Renderer ############################### + //########################################################################## + + class Renderer__NotifyOfNewInterestingEntityMessage; + class Renderer__NotifyOfBecomingUninterestingEntityMessage; + + class Renderer__StartEntityEffectMessage; + class Renderer__StopAllEntityEffectsMessage; + class Renderer__StartEntityAlarmMessage; + class Renderer__StopEntityAlarmMessage; + + class Renderer: + public Receiver + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Destruction, and Testing + // + public: + ~Renderer(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Control and processing + // + public: + // + //----------------------------------------------------------------------- + // LoadMission, Shutdown + //----------------------------------------------------------------------- + // + void + LoadMission(Mission *mission); + void + Shutdown(); + + // + //----------------------------------------------------------------------- + // LinkToEntity + // + // This method links the renderer to an entity. Overrides must call + // the inherited method. + //----------------------------------------------------------------------- + // + virtual void + LinkToEntity(Entity *entity); + + // + //----------------------------------------------------------------------- + // UnlinkFromEntity + //----------------------------------------------------------------------- + // + virtual void + UnlinkFromEntity(); + + // + //----------------------------------------------------------------------- + // SetRendererStatusToRunning + //----------------------------------------------------------------------- + // + void + SetRendererStatusToRunning(); + + // + //----------------------------------------------------------------------- + // UpdateInterestOrigin + //----------------------------------------------------------------------- + // + void + UpdateInterestOrigin(Time target_render_time); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + void + Execute( + Time target_render_time, + RendererComplexity complexity_update + ); + virtual Logical + ExecuteBackground(); + + // + //----------------------------------------------------------------------- + // Complete a rendering cycle (starts new frame) + //----------------------------------------------------------------------- + // + virtual Logical + CompleteCycle(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessors + // + public: + // + //----------------------------------------------------------------------- + // GetLinkedEntity + //----------------------------------------------------------------------- + // + Entity* + GetLinkedEntity(); + + // + //----------------------------------------------------------------------- + // GetRendererStatus + //----------------------------------------------------------------------- + // + RendererStatus + GetRendererStatus(); + + // + //----------------------------------------------------------------------- + // Misc + //----------------------------------------------------------------------- + // + RendererComplexity + GetCalibrationComplexity(); + Time + GetCalibrationFrameDuration(); + RendererRate + GetCalibrationRate(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Manager support + // + public: + // + //----------------------------------------------------------------------- + // NotifyOfNewInterestingEntity + //----------------------------------------------------------------------- + // + virtual void + NotifyOfNewInterestingEntity(Entity *) {} + + // + //----------------------------------------------------------------------- + // NotifyOfBecomingUninterestingEntity + //----------------------------------------------------------------------- + // + virtual void + NotifyOfBecomingUninterestingEntity(Entity *) {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum { + NotifyOfNewInterestingEntityMessageID = Receiver::NextMessageID, + NotifyOfBecomingUninterestingEntityMessageID, + StartEntityEffectMessageID, + StopAllEntityEffectsMessageID, + StartEntityAlarmMessageID, + StopEntityAlarmMessageID, + NextMessageID + }; + + typedef Renderer__NotifyOfNewInterestingEntityMessage + NotifyOfNewInterestingEntityMessage; + typedef Renderer__NotifyOfBecomingUninterestingEntityMessage + NotifyOfBecomingUninterestingEntityMessage; + typedef Renderer__StartEntityEffectMessage + StartEntityEffectMessage; + typedef Renderer__StopAllEntityEffectsMessage + StopAllEntityEffectsMessage; + typedef Renderer__StartEntityAlarmMessage + StartEntityAlarmMessage; + typedef Renderer__StopEntityAlarmMessage + StopEntityAlarmMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void + NotifyOfNewInterestingEntityMessageHandler( + NotifyOfNewInterestingEntityMessage *message + ); + void + NotifyOfBecomingUninterestingEntityMessageHandler( + NotifyOfBecomingUninterestingEntityMessage *message + ); + void + StartEntityEffectMessageHandler( + StartEntityEffectMessage *message + ); + void + StopAllEntityEffectsMessageHandler( + StopAllEntityEffectsMessage *message + ); + void + StartEntityAlarmMessageHandler( + StartEntityAlarmMessage *message + ); + void + StopEntityAlarmMessageHandler( + StopEntityAlarmMessage *message + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction + // + protected: + // + //----------------------------------------------------------------------- + // Construction + // + // Where calibration_rate indicates the update rate, and + // calibration_complexity indicates an arbitrary "maximum" complexity + // level passed to the renderer. The renderer manager will dynamically + // vary the value of complexity based on the actual frame rate that the + // renderer is able to maintain (if the total system load exceeds + // 100% of the maximum, each renderer's actual frame rate will drop + // below the requested rate: the renderer manager will detect this and + // lower the complexity value). The renderer manager will then + // periodically invoke the renderer's execute function, passing it the + // value indicated in complexity. + //----------------------------------------------------------------------- + // + Renderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration, + ClassID class_ID=TrivialReceiverClassID, + SharedData &virtual_data=DefaultData + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected accessors + // + protected: + // + //----------------------------------------------------------------------- + // GetInterestOrigin + //----------------------------------------------------------------------- + // + RendererOrigin* + GetInterestOrigin(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected implementations + // + protected: + // + //----------------------------------------------------------------------- + // Execute + // + // This method is called by the rendering manager to execute renderer + // updates. Overrides must call the inherited method. + //----------------------------------------------------------------------- + // + virtual void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private implementations + // + private: + virtual void + LoadMissionImplementation(Mission *mission); + virtual void + ShutdownImplementation(); + virtual void + StartEntityEffectImplementation( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ) + {} + virtual void + StopAllEntityEffectsImplementation(Entity *entity) + {} + virtual void + StartEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID resource_ID + ) + {} + virtual void + StopEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ) + {} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + // + // Current running state of the renderer + // + RendererStatus + rendererStatus; + + // + // Renderer frame rate related valriables + // + RendererRate + calibrationRate; + Time + calibrationFrameDuration, + nextRenderTime; + + // + // Renderer complexity, depth, and priority + // control related variables + // + RendererComplexity + calibrationComplexity; + RendererPriority + calibrationPriority; + InterestType + interestType; + InterestDepth + depthCalibration; + RendererFrameBudget + framePercentBudget; + + // + // Sockets + // + SlotOf + rendererOriginSocket; + SlotOf + entitySocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Renderer inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline Entity* + Renderer::GetLinkedEntity() + { + Check(&entitySocket); + return entitySocket.GetCurrent(); + } + + inline RendererOrigin* + Renderer::GetInterestOrigin() + { + Check(&rendererOriginSocket); + return rendererOriginSocket.GetCurrent(); + } + + inline RendererStatus + Renderer::GetRendererStatus() + { + Check(this); + return rendererStatus; + } + + inline Logical + Renderer::CompleteCycle() + { + Check(this); + return True; + } + + inline RendererComplexity + Renderer::GetCalibrationComplexity() + { + Check(this); + return calibrationComplexity; + } + + inline Time + Renderer::GetCalibrationFrameDuration() + { + Check(this); + return calibrationFrameDuration; + } + + inline RendererRate + Renderer::GetCalibrationRate() + { + Check(this); + return calibrationRate; + } + + inline Logical + Renderer::ExecuteBackground() + { + Check(this); + return False; + } + + //########################################################################## + //######################## RendererManager ########################### + //########################################################################## + + class RendererManager: + public Receiver + { + friend class Renderer; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction. Testing + // + public: + RendererManager(); + ~RendererManager(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Control, and processing + // + public: + // + //----------------------------------------------------------------------- + // UpdateInterestOrigins + // + // Called by the application to update the renderers interest origins + // before the interest manager performs its execute method. + //----------------------------------------------------------------------- + // + void + UpdateInterestOrigins(Time target_render_time); + + // + //----------------------------------------------------------------------- + // Execute + // + // Perform renderer management functions + //----------------------------------------------------------------------- + // + void + Execute( + Time target_render_time, + Time target_frame_duration, + Time actual_frame_duration + ); + + // + //----------------------------------------------------------------------- + // Complete Cycle + // + // Perform renderer complete cycle functions + //----------------------------------------------------------------------- + // + void + CompleteCycles(); + + // + //----------------------------------------------------------------------- + // AreRenderersRunning + //----------------------------------------------------------------------- + // + Logical + AreRenderersRunning(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Effects and Alarms + // + public: + void + StartEntityEffect( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ); + + void + StopAllEntityEffects(Entity *entity); + + void + StartEntityAlarm( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID resource_ID + ); + + void + StopEntityAlarm( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + void + StartRenderer(Renderer *renderer); + void + StopRenderer(Renderer *renderer); + + void + RendererManager::PostRendererEvent( + Entity *entity, + Receiver::Message *message + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + SChainOf + renderers; + }; + + //~~~~~~~~~~~~~~ Renderer__NotifyOfNewInterestingEntityMessage ~~~~~~~~~~~~~ + + class Renderer__NotifyOfNewInterestingEntityMessage: + public Receiver::Message + { + public: + Renderer__NotifyOfNewInterestingEntityMessage( + Entity *interesting_entity + ); + + Entity* + GetInterestingEntity(); + + private: + EntityID + entityID; + }; + + //~~~~~~~~~~ Renderer__NotifyOfBecomingUninterestingEntityMessage ~~~~~~~~~~ + + class Renderer__NotifyOfBecomingUninterestingEntityMessage: + public Receiver::Message + { + public: + Renderer__NotifyOfBecomingUninterestingEntityMessage( + Entity *uninteresting_entity + ); + + Entity* + GetUninterestingEntity() + {return uninterestingEntity;} + + private: + Entity + *uninterestingEntity; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~ Renderer__EntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Renderer__EntityMessage: + public Receiver::Message + { + public: + Renderer__EntityMessage( + Receiver::MessageID message_ID, + size_t message_size, + Entity *entity + ); + + Entity* + GetEntity(); + + private: + EntityID + entityID; + }; + + //~~~~~~~~~~~~~~~~~~ Renderer__StartEntityEffectMessage ~~~~~~~~~~~~~~~~~~~~ + + class Renderer__StartEntityEffectMessage: + public Renderer__EntityMessage + { + public: + Renderer__StartEntityEffectMessage( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ); + + DamageZone* + GetDamageZone() + {return damageZone;} + ResourceDescription::ResourceID + GetResourceID() + {return resourceID;} + + private: + DamageZone + *damageZone; + ResourceDescription::ResourceID + resourceID; + }; + + //~~~~~~~~~~~~~~~~~~ Renderer__StopAllEntityEffectsMessage ~~~~~~~~~~~~~~~~~ + + class Renderer__StopAllEntityEffectsMessage: + public Renderer__EntityMessage + { + public: + Renderer__StopAllEntityEffectsMessage(Entity *entity); + }; + + //~~~~~~~~~~~~~~~~~~ Renderer__StartEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~ + + class Renderer__StartEntityAlarmMessage: + public Renderer__EntityMessage + { + public: + Renderer__StartEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition, + ResourceDescription::ResourceID resource_ID + ); + + Subsystem* + GetSubsystem() + {return subsystem;} + Enumeration + GetCondition() + {return condition;} + ResourceDescription::ResourceID + GetResourceID() + {return resourceID;} + + private: + Subsystem + *subsystem; + Enumeration + condition; + ResourceDescription::ResourceID + resourceID; + }; + + //~~~~~~~~~~~~~~~~~~ Renderer__StopEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~ + + class Renderer__StopEntityAlarmMessage: + public Renderer__EntityMessage + { + public: + Renderer__StopEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition + ); + + Subsystem* + GetSubsystem() + {return subsystem;} + Enumeration + GetCondition() + {return condition;} + + private: + Subsystem + *subsystem; + Enumeration + condition; + }; + + //~~~~~~~~~~~~~~~~~~~~~~ RendererManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline void + RendererManager::StartEntityEffect( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ) + { + Renderer::StartEntityEffectMessage + message(entity, damage_zone, resource_ID); + PostRendererEvent(entity, &message); + } + + inline void + RendererManager::StopAllEntityEffects(Entity *entity) + { + Renderer::StopAllEntityEffectsMessage + message(entity); + PostRendererEvent(entity, &message); + } + + inline void + RendererManager::StartEntityAlarm( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition, + ResourceDescription::ResourceID resource_ID + ) + { + Renderer::StartEntityAlarmMessage + message(entity, alarm_subsystem, alarm_condition, resource_ID); + PostRendererEvent(entity, &message); + } + + inline void + RendererManager::StopEntityAlarm( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition + ) + { + Renderer::StopEntityAlarmMessage + message(entity, alarm_subsystem, alarm_condition); + PostRendererEvent(entity, &message); + } + +#endif + diff --git a/CODE/RP/MUNGA/RENDERER.TCP b/CODE/RP/MUNGA/RENDERER.TCP new file mode 100644 index 0000000..9480cee --- /dev/null +++ b/CODE/RP/MUNGA/RENDERER.TCP @@ -0,0 +1,57 @@ +//===========================================================================// +// File: renderer.tst // +// Project: MUNGA Brick: Renderer Manager // +// Contents: Interface specification Renderer and Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "renderer.thp" + +TestRenderer::TestRenderer(): + Renderer( + 30.0f, + MaxRendererComplexity, + DefaultRendererPriority, + VisualInterestType, + DefaultInterestDepth + ) +{ +} + +TestRenderer::~TestRenderer() +{ +} + +Logical + TestRenderer::TestInstance() const +{ + Renderer::TestInstance(); + return True; +} + +void + TestRenderer::ExecuteImplementation( + RendererComplexity, + RendererOrigin::InterestingEntityIterator *interesting_entity_iterator + ) +{ + Check(interesting_entity_iterator); + + // + // HACK - Just step through the entities + // + Entity *entity; + + while ((entity = interesting_entity_iterator->ReadAndNext()) != NULL) + { + Check(entity); + } +} + diff --git a/CODE/RP/MUNGA/RENDERER.THP b/CODE/RP/MUNGA/RENDERER.THP new file mode 100644 index 0000000..6cd0f53 --- /dev/null +++ b/CODE/RP/MUNGA/RENDERER.THP @@ -0,0 +1,48 @@ +//===========================================================================// +// File: tstrend.hh // +// Project: MUNGA Brick: Renderer Manager // +// Contents: Interface specification Renderer and Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/06/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(TSTREND_THP) +# define TSTREND_THP + +# if !defined(RENDERER_HPP) +# include +# endif + + class TestRenderer: + public Renderer + { + public: + TestRenderer(); + ~TestRenderer(); + + Logical + TestInstance() const; + + private: + void + LoadMissionImplementation(Mission*) {}; + void + ShutdownImplementation() {}; + void + SuspendImplementation() {}; + void + ResumeImplementation() {}; + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + }; + +#endif diff --git a/CODE/RP/MUNGA/RESOURCE.HPP b/CODE/RP/MUNGA/RESOURCE.HPP new file mode 100644 index 0000000..6feaef2 --- /dev/null +++ b/CODE/RP/MUNGA/RESOURCE.HPP @@ -0,0 +1,462 @@ +//===========================================================================// +// File: resource.hh // +// Project: MUNGA Brick: Resource Manager // +// Contents: Implementation Details of resource management // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/20/95 GSY Initial coding. // +// 01/20/95 GAH Added MUNGA style comments and assertions. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(RESOURCE_HPP) +# define RESOURCE_HPP + +# if !defined(FILESTRM_HPP) +# include +# endif + + //########################################################################## + //#################### ResourceDirectories ########################### + //########################################################################## + + struct ResourcePhysicalFormat; + class ResourceFile; + + struct ResourceDirectories + { + const char *modelDirectory; + const char *mapDirectory; + const char *collisionDirectory; + const char *audioDirectory; + const char *videoDirectory; + const char *gaugeDirectory; + const char *animationDirectory; + }; + + //########################################################################## + //################### ResourceDescription ############################ + //########################################################################## + + class ResourceDescription SIGNATURED + { + friend class ResourceFile; + friend class StreamableResourceFile; + + //########################################################################## + // Resource ID stuff + // + public: + typedef int ResourceID; + + enum { + NullResourceID = -1 + }; + + ResourceID + resourceID; + + //########################################################################## + // Resource Lock stuff + // + public: + void + Lock() + {if (!lockCount++) LoadResource();} + void + Unlock() + {--lockCount;} + + Logical + IsLocked() + {return lockCount > 0;} + + void + ReleaseUnlockedResource(); + + protected: + int + lockCount; + + //########################################################################## + // Resource Type stuff + // + public: + typedef int ResourceType; + + enum + { + NullResourceType, + + // + // ONLY LIST RESOURCE TYPES HERE -- These Are Really OBSOLETE + // + ModelListResourceType, + MapListResourceType, + AudioStreamListResourceType, + VideoListResourceType, + SubsystemListResourceType, + ControlMappingsListResourceType, + DamageZoneListResourceType, + SkeletonListResourceType, + + FirstNonListResourceType, + MaxListResourceType = FirstNonListResourceType - 1, + // + // ALL OTHER RESOURCE TYPES + // + BoxedSolidStreamResourceType = FirstNonListResourceType, + VideoModelResourceType, + StaticAudioStreamResourceType, + InternalAudioStreamResourceType, + ExternalAudioStreamResourceType, + MakeMessageStreamResourceType, + GameModelResourceType, + AnimationResourceType, + SubsystemModelStreamResourceType, + GaugeImageStreamResourceType, + ControlMappingStreamResourceType, + DamageZoneStreamResourceType, + SkeletonStreamResourceType, + DropZoneResourceType, + EnvironmentZoneResourceType, + InterestZoneResourceType, + VehicleTableResourceType, + ExistanceBoxStreamResourceType, + CameraStreamResourceType, + RegistryStaticObjectStreamResourceType, + DamageLookupTableStreamResourceType, + ExplosionTableStreamResourceType, + GaugeAlarmStreamResourceType, + GaugeMissionReviewStreamResourceType, + ScenarioRoleResourceType + }; + + ResourceType + resourceType; + + //########################################################################## + // Resource Name stuff + // + public: + enum { + NameSize = 32 + }; + + char + resourceName[NameSize]; + + //########################################################################## + // Loading stuff + // + public: + enum + { + LoadedBit=0, + LoadOnDemandBit + }; + enum + { + Preload = 0, // HACK - for backwards compatability + LoadedFlag = 1 << LoadedBit, + LoadOnDemandFlag = 1 << LoadOnDemandBit, + }; + + int + downloadPriority; + + LWord + resourceFlags; + + size_t + offsetInFile; + + void + SetLoaded() + {Check(this); resourceFlags |= LoadedFlag;} + void + SetNotLoaded() + {Check(this); resourceFlags &= ~LoadedFlag;} + Logical + IsLoaded() + {Check(this); return (resourceFlags&LoadedFlag) != 0;} + + void + LoadOnDemand() + {Check(this); resourceFlags |= LoadOnDemandFlag;} + void + MarkForPreload() + {Check(this); resourceFlags &= ~LoadOnDemandFlag;} + Logical + IsPreloadable() + {Check(this); return (resourceFlags&LoadOnDemandFlag) == 0;} + + //########################################################################## + // Construction and Destruction + // + protected: + ResourceDescription( + ResourceFile *file, + const char* name, + ResourceType type, + int priority, + LWord resource_flags, + const void* address, + size_t size, + ResourceID index=NullResourceID + ); + + ~ResourceDescription(); + + void + LoadResource(); + + protected: + ResourceFile + *resourceFile; + + //########################################################################## + // Resource Data stuff + // + public: + void + *resourceAddress; + + size_t + resourceSize; + + //########################################################################## + // Test stuff + // + public: + Logical + TestInstance() const; + }; + + //########################################################################## + // Format in physical memory: FILE,ROM,CD... + // + struct ResourcePhysicalFormat + { + ResourceDescription::ResourceID + resourceID; + ResourceDescription::ResourceType + resourceType; + char + resourceName[32]; + int + downloadPriority; + LWord + resourceFlags; + size_t + resourceOffset, + resourceLength; + }; + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + ResourcePhysicalFormat *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const ResourcePhysicalFormat *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + + //########################################################################## + //####################### ResourceFile ############################### + //########################################################################## + + class ResourceFile SIGNATURED + { + friend class ResourceDescription; + + public: + // + //----------------------------------------------------------------------- + // Constructors & destructors + //----------------------------------------------------------------------- + // + ResourceFile(); + ~ResourceFile(); + + public: + // + //----------------------------------------------------------------------- + // Public data + //----------------------------------------------------------------------- + // + enum { + IndexBlockSize = 50 + }; + + Byte + versionArray[4]; + int + labOnly; + + protected: + ResourceDescription** + resourceArray; + int + resourceArraySize; + ResourceDescription::ResourceID + lastPreallocatedResourceID, + maxResourceID; + + virtual void + LoadResource(ResourceDescription* res) + {Check(res); res->SetLoaded();} + + public: + // + //----------------------------------------------------------------------- + // Public interface + //----------------------------------------------------------------------- + // + ResourceDescription::ResourceID + GetMaxResourceID() + {Check(this); return maxResourceID;} + void + PreAllocateIDs(ResourceDescription::ResourceID last_id) + { + Verify(lastPreallocatedResourceID == ResourceDescription::NullResourceID); + lastPreallocatedResourceID = last_id; + } + + ResourceDescription* + AddResource( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + const void* address, + size_t size, + ResourceDescription::ResourceID index=-1 + ); + ResourceDescription* + AddResourceList( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + const ResourceDescription::ResourceID* address, + int count, + ResourceDescription::ResourceID index=-1 + ); + ResourceDescription* + AddResourceMemoryStream( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + MemoryStream* memory_stream, + ResourceDescription::ResourceID index=-1 + ); + void + DeleteResource(ResourceDescription *resource); + + ResourceDescription* + FindResourceDescription( + const char* name, + ResourceDescription::ResourceType type, + ResourceDescription::ResourceID after=-1 + ); + ResourceDescription* + FindResourceDescription( + ResourceDescription::ResourceID index + ); + + ResourceDescription* + SearchList( + ResourceDescription::ResourceID list_id, + ResourceDescription::ResourceType type + ); + ResourceDescription* + SearchList( + ResourceDescription::ResourceID list_id, + const char* name + ); + + void + ReleaseUnlockedResources(); + void + ReportLockedResources(); + + // + //--------------------------------------------------------------------------- + // Lab tests + //--------------------------------------------------------------------------- + // + public: + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + //########################################################################## + //################### StreamableResourceFile ############################# + //########################################################################## + + class StreamableResourceFile: + public ResourceFile + { + public: + // + //------------------------------------------------------------------------ + // Constructors & destructors + //------------------------------------------------------------------------ + // + enum { + FileNameLength = 80 + }; + + + StreamableResourceFile(); + StreamableResourceFile(const char * name); + StreamableResourceFile( + const char * name, + Byte version_array[3], + int match_level=3 + ); + ~StreamableResourceFile(); + + protected: + void + LoadResource(ResourceDescription* res); + + FileStream + diskFile; + + // + //------------------------------------------------------------------------ + // Public data + //------------------------------------------------------------------------ + // + public: + char + resourceFilename[FileNameLength]; + + int + Open(const char *file_name); + int + Save(); + int + SaveAs(const char* file_name); + + Logical + TestInstance() const; + + static Logical + TestClass(); + }; + +#endif + diff --git a/CODE/RP/MUNGA/RESOURCE.TCP b/CODE/RP/MUNGA/RESOURCE.TCP new file mode 100644 index 0000000..7295b21 --- /dev/null +++ b/CODE/RP/MUNGA/RESOURCE.TCP @@ -0,0 +1,759 @@ +//===========================================================================// +// File: resource.tst // +// Project: MUNGA Brick: Resource Manager // +// Contents: Test methods for Resource Manager classes. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/19/95 GSY Initial coding. // +// 01/20/95 GAH Modified in the MUNGA style // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + + //GY: Directory (References) stuff wasn't tested so is not reliable yet !!!! + + +Logical + ResourceFile::TestClass() +{ + DEBUG_STREAM<<"Starting Resource test....\n"; + + typedef char ATTRIB[16]; + + + + ResourceFile + file; + +// +//---------------------------------- +// ResourceDescription* +// addResource( +// ResourceDescription::Name res_name, +// ResourceDescription::Type res_type, +// unsigned short res_priority, +// ResourceDescription::PreloadRequest load_flag, +// void* res_address, +// size_t res_size, +// int res_index=-1 //ResourceDescription::ResourceID res_index=-1 +// ); +//---------------------------------- +// + ATTRIB attrib4 = "data4"; + ResourceDescription + *res = file.AddResource( + "The fourth", + ResourceDescription::FirstNonListResourceType, // 4(3) + 1, + ResourceDescription::Preload, + attrib4, + sizeof(ATTRIB), + 3 + ); + Test(res->resourceID == 3); + + ATTRIB attrib1 = "data1"; + res = file.AddResource( + "The first", // 1 + ResourceDescription::FirstNonListResourceType, //DirectoryType = 0 + 0, + ResourceDescription::Preload, + attrib1, + sizeof(ATTRIB) + ); + Test(res->resourceID == 0); + + ATTRIB attrib2 = "data2"; + res = file.AddResource( // 2 + "The second", + ResourceDescription::FirstNonListResourceType, //DirectoryType = 0 + 0, + ResourceDescription::Preload, + attrib2, + sizeof(ATTRIB) + ); + Test(res->resourceID == 1); + + // Same data but different memory allocated + res = file.AddResource( + "The first", // 1.1 + ResourceDescription::FirstNonListResourceType, //DirectoryType = 0 + 0, + ResourceDescription::Preload, + attrib1, + sizeof(ATTRIB) + ); + Test(res->resourceID == 2); + + + ATTRIB attrib10 = "data10"; + res = file.AddResource( + "The tenth", // 10 (9) + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib10, + sizeof(ATTRIB), + 9 + ); + Test(res->resourceID == 9); + + ATTRIB attrib6 = "data6"; + res = file.AddResource("The sixth", // 6 (5) + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib6, + sizeof(ATTRIB), + 5 + ); + Test(res->resourceID == 5); + + + ATTRIB attrib5 = "data5"; // 5 + res = file.AddResource("The fifth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib5, + sizeof(ATTRIB) + ); + Test(res->resourceID == 4); + + ATTRIB attrib7 = "data7"; // 7 + res = file.AddResource("The seventh", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib7, + sizeof(ATTRIB) + ); + Test(res->resourceID == 6); + + ATTRIB attrib11 = "data11"; // 11 (10) + res = file.AddResource("The eleventh", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib11, + sizeof(ATTRIB), + 10 + ); + Test(res->resourceID == 10); + + + ATTRIB attrib1001 = "data1001"; // 1001 (1000) + res = file.AddResource("The thousand first", //last + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib1001, + sizeof(ATTRIB), + 1000 + ); + Test(res->resourceID == 1000); + + ATTRIB attrib8 = "data8"; // 8 + res = file.AddResource("The eighth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib8, + sizeof(ATTRIB) + ); + Test(res->resourceID == 7); + + ATTRIB attrib101 = "data101"; // 101 (100) + res = file.AddResource("The hundred first", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib101, + sizeof(ATTRIB), + 100 + ); + Test(res->resourceID == 100); + + +//------------------------------ +// ResourceDescription* +// FindResourceDescription( +// ResourceDescription::Name res_name, +// ResourceDescription::Type res_type) +//------------------------------ + + res = file.FindResourceDescription( + "The fourth", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + Test(!strcmp(res->resourceName, "The fourth")); + Test(res->resourceType == ResourceDescription::FirstNonListResourceType); + Test(res->resourceID == 3); + + res = file.FindResourceDescription( + "The hundred first", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + Test(!strcmp(res->resourceName, "The hundred first")); + Test(res->resourceType == ResourceDescription::FirstNonListResourceType); + +//-------------------------------------------------- +// void +// DeleteResource(ResourceDescription *resource); +//-------------------------------------------------- + //ID=3 + file.FindResourceDescription(3)->Unlock(); + Unregister_Object(file.FindResourceDescription(3)); + file.DeleteResource (file.FindResourceDescription(3)); + Test(!file.FindResourceDescription(3)); + + //ID=4 + file.FindResourceDescription(4)->Unlock(); + Unregister_Object(file.FindResourceDescription(4)); + file.DeleteResource (file.FindResourceDescription(4)); + Test(!file.FindResourceDescription(4)); + + //ID=5 + file.FindResourceDescription(5)->Unlock(); + Unregister_Object(file.FindResourceDescription(5)); + file.DeleteResource (file.FindResourceDescription(5)); + Test(!file.FindResourceDescription(5)); + + + //ID=2 + file.FindResourceDescription(2)->Unlock(); + Unregister_Object(file.FindResourceDescription(2)); + file.DeleteResource(file.FindResourceDescription(2)); + Test(!file.FindResourceDescription(2)); + + + + //ID=0 + file.FindResourceDescription(0)->Unlock(); + Unregister_Object(file.FindResourceDescription(0)); + file.DeleteResource(file.FindResourceDescription(0)); + Test(!file.FindResourceDescription(0)); + + file.FindResourceDescription( + "The second", + ResourceDescription::FirstNonListResourceType + )->Unlock(); + Unregister_Object( + file.FindResourceDescription( + "The second", + ResourceDescription::FirstNonListResourceType + ) + ); + file.DeleteResource( + file.FindResourceDescription( + "The second", + ResourceDescription::FirstNonListResourceType + ) + ); + Test( + !file.FindResourceDescription( + "The second", + ResourceDescription::FirstNonListResourceType + ) + ); + + file.FindResourceDescription( + "The hundred first", + ResourceDescription::FirstNonListResourceType + )->Unlock(); + Unregister_Object( + file.FindResourceDescription( + "The hundred first", + ResourceDescription::FirstNonListResourceType + ) + ); + file.DeleteResource( + file.FindResourceDescription( + "The hundred first", + ResourceDescription::FirstNonListResourceType + ) + ); + Test( + !file.FindResourceDescription( + "The hundred first", + ResourceDescription::FirstNonListResourceType + ) + ); + + file.FindResourceDescription( + "The thousand first", + ResourceDescription::FirstNonListResourceType + )->Unlock(); + Unregister_Object( + file.FindResourceDescription( + "The thousand first", + ResourceDescription::FirstNonListResourceType + ) + ); + file.DeleteResource( + file.FindResourceDescription( + "The thousand first", + ResourceDescription::FirstNonListResourceType + ) + ); + Test( + !file.FindResourceDescription( + "The thousand hundred first", + ResourceDescription::FirstNonListResourceType + ) + ); + +// +//------------------------------------------------------------------------------ +// ResourceDescription* +// AddResourceDirectory( +// ResourceDescription::ResourceName name, +// int priority, +// ResourceDescription::PreloadRequest load_flag, +// ResourceDescription::ResourceID* address, +// int count, +// ResourceDescription::ResourceID index=-1 +// ); +//------------------------------------------------------------------------------ +// + + //---------------------------------------- + // One way of directory describing: + // + //ResourceDescription::ResourceID + // dir[] = { + // 7, + // 9, + // 10 + // }; + + //---------------------------------------- + // The other way : + + ResourceDescription::ResourceID + dirRes[10]; + + res = + file.FindResourceDescription( + "The eighth", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + dirRes[0] = res->resourceID; //7 + Test(dirRes[0]==7); + + res = + file.FindResourceDescription( + "The tenth", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + dirRes[1] = res->resourceID; //9 + Test(dirRes[1]==9); + + res = + file.FindResourceDescription( + "The eleventh", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + dirRes[2] = res->resourceID; //10 + Test(dirRes[2]==10); + + //--------------------------------------------------------- + // test Directory assigned to resource "The seventh" + // Remember: Directory has to be appended to end of the list + // + Test(file.maxResourceID==10); + Test(!file.FindResourceDescription(file.maxResourceID +1)); + + res = file.AddResourceList( + "first directory", + ResourceDescription::ModelListResourceType, + 1, + ResourceDescription::Preload, + dirRes, + 3, //count of references + file.maxResourceID +1 //Dir. has to be in + ); //resourceArray after + //resources it references + + Test(res); + res = file.FindResourceDescription( + "first directory", + ResourceDescription::ModelListResourceType + ); + Test(res); + Test(res->resourceID == 11); + Test(res->resourceType == ResourceDescription::ModelListResourceType); + + ResourceDescription::ResourceID + *res_array = (ResourceDescription::ResourceID*)res->resourceAddress; + + Test(res_array[0] == 3); + + Test(res_array[1] == 7); + Test(res_array[2] == 9); + Test(res_array[3] == 10); + + return True; +} +// +//############################################################################## +//################# StreamableResourceFile::TestClass() ####################### +//############################################################################## +Logical + StreamableResourceFile::TestClass() +{ + +// ResourceFile::TestClass(); // ????? gives error: + //resourceArray[index] !=NULL + //in AddResource() + DEBUG_STREAM<<"Starting StreamableResource test....\n"; +// +//------------------------------------------------------------------------------ +// StreamableResourceFile(); +//------------------------------------------------------------------------------ +// + ResourceDescription *res; + typedef char ATTRIB[16]; + + { + StreamableResourceFile + file; + + ATTRIB attrib4 = "data4"; + res = + file.AddResource( + "The fourth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib4, + sizeof(ATTRIB), + 3 + ); + Test(res->resourceID == 3); + + ATTRIB attrib1 = "data1"; + res = + file.AddResource( + "The first", + ResourceDescription::FirstNonListResourceType, + 0, + ResourceDescription::Preload, + attrib1, + sizeof(ATTRIB) + ); + Test(res->resourceID == 0); + + ATTRIB attrib2 = "data2"; + res = + file.AddResource( + "The second", + ResourceDescription::FirstNonListResourceType, + 0, + ResourceDescription::Preload, + attrib2, + sizeof(ATTRIB) + ); + Test(res->resourceID == 1); + + // Same data but different memory allocated + res = + file.AddResource( + "The first", + ResourceDescription::FirstNonListResourceType, + 0, + ResourceDescription::Preload, + attrib1, + sizeof(ATTRIB) + ); + Test(res->resourceID == 2); + + ATTRIB attrib10 = "data10"; + res = + file.AddResource( + "The tenth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib10, + sizeof(ATTRIB), + 9 + ); + Test(res->resourceID == 9); + + ATTRIB attrib6 = "data6"; + res = + file.AddResource( + "The sixth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib6, + sizeof(ATTRIB), + 5 + ); + Test(res->resourceID == 5); + + ATTRIB attrib5 = "data5"; + res = + file.AddResource( + "The fifth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib5, + sizeof(ATTRIB) + ); + Test(res->resourceID == 4); + + ATTRIB attrib7 = "data7"; + res = + file.AddResource( + "The seventh", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib7, + sizeof(ATTRIB) + ); + Test(res->resourceID == 6); + + ATTRIB attrib11 = "data11"; + res = + file.AddResource( + "The eleventh", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib11, + sizeof(ATTRIB), + 10 + ); + Test(res->resourceID == 10); + + // + //------------------------------------------------------------------------------ + // int + // SaveAs(char* file_name); + //------------------------------------------------------------------------------ + // + file.SaveAs("temp.res"); + } + + // + //------------------------------------------------------------------------------ + // int + // Open(char *file_name); + //------------------------------------------------------------------------------ + // + { + StreamableResourceFile + file; + + Test(file.Open("temp.res")); + Test(!strcmp(file.FindResourceDescription(0)->resourceName,"The first")); + + Test( + !strcmp( + file.FindResourceDescription( + "The eleventh", + ResourceDescription::FirstNonListResourceType + )->resourceName, + "The eleventh" + ) + ); + + ATTRIB attrib12 = "data12"; + res = + file.AddResource( + "The twelfth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib12, + sizeof(ATTRIB), + 11 + ); + Test(res->resourceID == 11); + + + ATTRIB attrib8 = "data8"; + res = + file.AddResource( + "The eighth", + ResourceDescription::FirstNonListResourceType, + 1, + ResourceDescription::Preload, + attrib8, + sizeof(ATTRIB) + ); + Test(res->resourceID == 7); + + + // + //------------------------------------------------------------------------------ + // int + // Save(); + //------------------------------------------------------------------------------ + // + + file.Save(); + } + + { + StreamableResourceFile + file; + file.Open("temp.res"); + + file.FindResourceDescription(2)->Unlock(); + Unregister_Object(file.FindResourceDescription(2)); + file.DeleteResource(file.FindResourceDescription(2)); + file.FindResourceDescription(0)->Unlock(); + Unregister_Object(file.FindResourceDescription(0)); + file.DeleteResource(file.FindResourceDescription(0)); + file.Save(); + } + + { + StreamableResourceFile + file; + file.Open("temp.res"); + Test( + !file.FindResourceDescription( + "The first", + ResourceDescription::FirstNonListResourceType + ) + ); + Test(!file.FindResourceDescription(0)); + + // + //------------------------------------------------------------------------------ + // ResourceDescription* + // AddResourceDirectory( + // ResourceDescription::ResourceName name, + // int priority, + // ResourceDescription::PreloadRequest load_flag, + // ResourceDescription::ResourceID* address, + // int count, + // ResourceDescription::ResourceID index=-1 + // ); + //------------------------------------------------------------------------------ + // + + //-------------------------- + // Test resource descriptions before adding directory + // + + //---------------------------------------- + // One way of directory describing: + // + //ResourceDescription::ResourceID + // dir[] = { + // 0, + // 9, + // 11 + // }; + + //---------------------------------------- + // The other way : + + ResourceDescription::ResourceID + dirRes[10]; + + //------------------ + // test "The first" + // + res = + file.FindResourceDescription( + "The eighth", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + dirRes[0] = res->resourceID; + Test(dirRes[0]==7); + + //------------------ + // test "The tenth" + // + res = + file.FindResourceDescription( + "The tenth", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + dirRes[1] = res->resourceID; + Test(dirRes[1]==9); + + //------------------ + // test "The twelfth" + // + res = + file.FindResourceDescription( + "The twelfth", + ResourceDescription::FirstNonListResourceType + ); + Test(res); + dirRes[2] = res->resourceID; + Test(dirRes[2]==11); + + // + //---------------- + // Add Directory + // + Test(file.maxResourceID==11); + Test(!file.FindResourceDescription(file.maxResourceID+1)); + res = + file.AddResourceList( + "The first list", + ResourceDescription::ModelListResourceType, + 1, + ResourceDescription::Preload, + dirRes, + 3, + file.maxResourceID+1 + ); + Test(res); + + Test(res->resourceID == 12); + Test(res->resourceType == ResourceDescription::ModelListResourceType); + + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[0] == 3); + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[1] == 7); + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[2] == 9); + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[3] == 11); + file.Save(); + } + + { + StreamableResourceFile + file; + file.Open("temp.res"); + + res = + file.FindResourceDescription( + "The first list", + ResourceDescription::ModelListResourceType + ); + Test(res); + Test(res->resourceID == 12); + Test(res->resourceType == ResourceDescription::ModelListResourceType); + + res->Lock(); + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[0] == 3); + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[1] == 7); + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[2] == 9); + Test(((ResourceDescription::ResourceID*)res->resourceAddress)[3] == 11); + res->Unlock(); + } + + return True; +} + + diff --git a/CODE/RP/MUNGA/RESVER.HPP b/CODE/RP/MUNGA/RESVER.HPP new file mode 100644 index 0000000..702a834 --- /dev/null +++ b/CODE/RP/MUNGA/RESVER.HPP @@ -0,0 +1,7 @@ +#if !defined(RESVER_HPP) +# define RESVER_HPP + +# define RESOURCE_FORMAT_VERSION 1 + +#endif + diff --git a/CODE/RP/MUNGA/RETICLE.CPP b/CODE/RP/MUNGA/RETICLE.CPP new file mode 100644 index 0000000..ddf85d0 --- /dev/null +++ b/CODE/RP/MUNGA/RETICLE.CPP @@ -0,0 +1,120 @@ +//===========================================================================// +// File: reticle.cc // +// Project: MUNGA Brick: Model Manager // +// Contents: Reticle specification // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/21/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RETICLE_HPP) +# include +#endif + +//########################################################################## +//########################### Class Reticle ######################### +//########################################################################## + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Reticle::Reticle() +{ + // + // NOTE...most of these things should be initialization parameters to the constructor + // + reticleState = ReticleOn; + reticlePosition.x = 0.0f; + reticlePosition.y = 0.0f; + pickPointingOn = False; + rayIntersection.x = 0.0f; + rayIntersection.y = 0.0f; + rayIntersection.z = 0.0f; + targetEntity = 0; + targetDamageZone = -1; + reticleElementMask = AllEnabledGroup; // all reticle elements are on +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Reticle::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + Reticle::CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *model_file, + const ResourceDirectories *, + ModelResource *model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + if( + !model_file->GetEntry( + "gamedata", + "ReticleX", + &local_model->reticlePosition.x + ) + ) + { + local_model->reticlePosition.x = 0.0f; + } + if( + !model_file->GetEntry( + "gamedata", + "ReticleY", + &local_model->reticlePosition.y + ) + ) + { + local_model->reticlePosition.y = 0.0f; + } + // + //--------------------------- + // Write out the new resource + //--------------------------- + // + if(!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + return new_res->resourceID; + } + else + { + return 0; + } +} diff --git a/CODE/RP/MUNGA/RETICLE.HPP b/CODE/RP/MUNGA/RETICLE.HPP new file mode 100644 index 0000000..6f82b2d --- /dev/null +++ b/CODE/RP/MUNGA/RETICLE.HPP @@ -0,0 +1,91 @@ +//===========================================================================// +// File: reticle.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Reticle specification // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/21/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(RETICLE_HPP) +# define RETICLE_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + +# if !defined(VECTOR2D_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(NOTATION_HPP) +# include +# endif + + class Entity; + //########################################################################## + //##################### Reticle::ModelResource ####################### + //########################################################################## + + struct Reticle__ModelResource + { + Vector2DOf reticlePosition; + }; + //########################################################################## + //########################### Class Reticle ######################### + //########################################################################## + + class Reticle SIGNATURED + { + public: + enum ReticleState + { + ReticleOff, // Reticle is invisible + ReticleOn, // Reticle is visible (may be more than one "on" state added later) + }; + + enum ReticleElements // these are bits that turn parts of the reticle on and off + { + FrontFiringWeaponsOn = 0x00000001, // Display Front firing weapons + RearFiringWeaponsOn = 0x00000002, // Display rear firing weapons + LeftFiringWeaponsOn = 0x00000004, // Display left firing weapons + RightFiringWeaponsOn = 0x00000008, // Display right firing weapons + WeaponsControlGroup = 0x0000000F, // Mask defining the weapons group + TargetDesignatorOn = 0x00000010, // Display target designator box and direction arrows + PrimaryHudOn = 0x00000020, // if set, you get the full hud, if not just a simple x + AllEnabledGroup = 0xFFFFFFFF, // All bits on + }; + + Vector2DOf reticlePosition; // screen position -1.0 -> +1.0 + ReticleState reticleState; // current state of reticle, graphic to display + Logical pickPointingOn; // Pick point intersection testing on/off + Point3D rayIntersection; // Current pickpoint intersection in 3d world + Entity *targetEntity; // entity being targeted + int targetDamageZone; // damage zone on the entity + ReticleElements reticleElementMask; // controls what parts of the reticle are displayed + + Reticle(); + + Logical + TestInstance() const; + typedef Reticle__ModelResource ModelResource; + + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *map_file, + const ResourceDirectories *directories, + ModelResource *model = NULL + ); + }; + +#endif \ No newline at end of file diff --git a/CODE/RP/MUNGA/RNDORGN.CPP b/CODE/RP/MUNGA/RNDORGN.CPP new file mode 100644 index 0000000..77d9603 --- /dev/null +++ b/CODE/RP/MUNGA/RNDORGN.CPP @@ -0,0 +1,214 @@ +//===========================================================================// +// File: rndorgn.cc // +// Project: MUNGA Brick: Interest Manager // +// Contents: Interface specification Interest Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/18/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RNDORGN_HPP) +# include +#endif + +#if !defined(RENDERER_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +// +//############################################################################# +// RendererOrigin +//############################################################################# +// +RendererOrigin::RendererOrigin( + Renderer *the_renderer, + Entity *entity, + InterestType interest_type, + InterestDepth depth_calibration +): + InterestOrigin( + entity->GetInterestZoneID(), + interest_type, + depth_calibration + ), + interestingEntitySocket(NULL) +{ + Check(the_renderer); + renderer = the_renderer; +} + +// +//############################################################################# +// ~RendererOrigin +//############################################################################# +// +RendererOrigin::~RendererOrigin() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + RendererOrigin::TestInstance() const +{ + InterestOrigin::TestInstance(); + Check_Signature(renderer); + Check(&interestingEntitySocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + RendererOrigin::AddInterestingEntity(Entity *interesting_entity) +{ + Check(this); + Check(interesting_entity); + + // + // Add to the socket + // + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&interestingEntitySocket); + Check(&iterator); + Verify(iterator.IsPlugMember(interesting_entity) == False); + } + #endif + interestingEntitySocket.Add(interesting_entity); + + // + // Notify the renderer + // + #if 0 + Renderer::NotifyOfNewInterestingEntityMessage + message(interesting_entity); + + Check(&message); + Check(application); + Check(renderer); + application->PostInterestEvent(renderer, &message); + #else + Renderer::NotifyOfNewInterestingEntityMessage + message(interesting_entity); + + Check(&message); + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->PostRendererEvent( + interesting_entity, + renderer, + &message + ); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + RendererOrigin::RemoveUninterestingEntity(Entity *uninteresting_entity) +{ + Check(this); + Check(uninteresting_entity); + + // + // Notify the renderer + // + #if 1 + Check(renderer); + renderer->NotifyOfBecomingUninterestingEntity(uninteresting_entity); + #else + Renderer::NotifyOfBecomingUninterestingEntityMessage + message(uninteresting_entity); + + Check(&message); + Check(application); + Check(renderer); + application->PostInterestEvent(renderer, &message); + #endif + + // + // Remove from socket + // + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&interestingEntitySocket); + Verify(iterator.IsPlugMember(uninteresting_entity) == True); + } + #endif + PlugIterator remover(uninteresting_entity); + remover.RemoveSocket(&interestingEntitySocket); +} + +// +//############################################################################# +//############################################################################# +// +void + RendererOrigin::RemoveUninterestingEntities() +{ + Check(this); + + // + // Notify the renderer of uninteresting entities + // + SChainIteratorOf iterator(&interestingEntitySocket); + Entity *uninteresting_entity; + + Check(&iterator); + #if 0 + while ((uninteresting_entity = iterator.GetCurrent()) != NULL) + { + Check(uninteresting_entity); + Check(renderer); + renderer->NotifyOfBecomingUninterestingEntity(uninteresting_entity); + iterator.Remove(); + } + #else + while ((uninteresting_entity = iterator.GetCurrent()) != NULL) + { + Check(uninteresting_entity); + RemoveUninterestingEntity(uninteresting_entity); + } + #endif +} + +//~~~~~~~~~~~~~~~~~ RendererOrigin__InterestingEntityIterator ~~~~~~~~~~~~~~~~~ + +RendererOrigin__InterestingEntityIterator:: + RendererOrigin__InterestingEntityIterator( + RendererOrigin *renderer_origin + ): + SChainIteratorOf(&renderer_origin->interestingEntitySocket) +{ +} + +RendererOrigin__InterestingEntityIterator:: + ~RendererOrigin__InterestingEntityIterator() +{ +} + + diff --git a/CODE/RP/MUNGA/RNDORGN.HPP b/CODE/RP/MUNGA/RNDORGN.HPP new file mode 100644 index 0000000..276c226 --- /dev/null +++ b/CODE/RP/MUNGA/RNDORGN.HPP @@ -0,0 +1,144 @@ +//===========================================================================// +// File: rndorgn.hh // +// Project: MUNGA Brick: Interest Manager // +// Contents: Interface specifications for interest manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/18/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RNDORGN_HPP) +# define RNDORGN_HPP + +# if !defined(INTORGN_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + + //########################################################################## + //####################### RendererOrigin ############################# + //########################################################################## + + class Renderer; + class Entity; + + class RendererOrigin: + public InterestOrigin + { + friend class RendererOrigin__InterestingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + typedef RendererOrigin__InterestingEntityIterator + InterestingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + RendererOrigin( + Renderer *renderer, + Entity *entity, + InterestType interest_type, + InterestDepth depth_calibration + ); + ~RendererOrigin(); + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Manager support + // + private: + void + AddInterestingEntity(Entity *interesting_entity); + void + RemoveUninterestingEntity(Entity *uninteresting_entity); + void + RemoveUninterestingEntities(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + Renderer* + renderer; + SChainOf + interestingEntitySocket; + }; + + //~~~~~~~~~~~~~~~~~ RendererOrigin__InterestingEntityIterator ~~~~~~~~~~~~~~ + + class RendererOrigin__InterestingEntityIterator: + public SChainIteratorOf + { + public: + RendererOrigin__InterestingEntityIterator(RendererOrigin *renderer_origin); + ~RendererOrigin__InterestingEntityIterator(); + }; + +#if 0 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RendererOrigin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // + //-------------------------------------------------------------------- + // RendererOrigin + // + // Represent a renderers origin of interest. + //-------------------------------------------------------------------- + // + + class RendererOrigin: + public InterestOrigin + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, and Testing + //-------------------------------------------------------------------- + // + RendererOrigin( + const EntityID &entity_ID, + InterestType interest_type, + InterestDepth depth_calibration, + Renderer *renderer + ); + ~RendererOrigin(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Interest Manager support + //-------------------------------------------------------------------- + // + void + AddInterestingEntity(Entity *interesting_entity); + void + RemoveUninterestingEntity(Entity *uninteresting_entity); + void + RemoveUninterestingEntities(); + + protected: + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + SlotOf + rendererSocket; + }; +#endif + +#endif + diff --git a/CODE/RP/MUNGA/ROTATION.TCP b/CODE/RP/MUNGA/ROTATION.TCP new file mode 100644 index 0000000..696859f --- /dev/null +++ b/CODE/RP/MUNGA/ROTATION.TCP @@ -0,0 +1,202 @@ +//===========================================================================// +// File: rotation.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Test code for rotation classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/20/94 JMA Initial coding. // +// 12/01/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EulerAngles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + EulerAngles::TestClass() +{ + DEBUG_STREAM << "Starting EulerAngle test...\n"; + + const EulerAngles + a(Identity); + EulerAngles + b; + const EulerAngles + c(PI_OVER_4,PI_OVER_6,PI_OVER_3); + + Test(!a.pitch && !a.yaw && !a.roll); + Test(c.pitch == PI_OVER_4 && c.yaw == PI_OVER_6 && c.roll == PI_OVER_3); + + Test(!a); + b = c; + Test(b == c); + Test(b != a); + + Test(b[Y_Axis] == b.yaw); + Test(c[Z_Axis] == c.roll); + + b.Lerp(a,c,0.5f); + Test(b == EulerAngles(::Lerp(a.pitch,c.pitch,0.5f),::Lerp(a.yaw,c.yaw,0.5f),::Lerp(a.roll,c.roll,0.5f))); + + LinearMatrix m(True); + m = c; + b = m; + Test(b == c); + + Quaternion q; + q = Hinge(X_Axis, PI_OVER_4); + b = q; + Test(b == EulerAngles(PI_OVER_4,0.0f,0.0f)); + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Quaternion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +#define NUMBER_OF_MULTIPLICATIONS 30 +#include "random.hpp" +#include +class fstream; +Logical + Quaternion::TestClass() +{ + + Tell("Starting Quaternion Test...\n"); + +#if 0 +// ofstream testout("gene.tst",ios::app); //GY + + Vector3D + r_vec; + Quaternion +// q[2], + q[NUMBER_OF_MULTIPLICATIONS+1], + multiplied_q(Identity), + converted_q; + LinearMatrix +// lm[2], + lm[NUMBER_OF_MULTIPLICATIONS+1], + multiplied_lm(True); + Scalar r_float; + +//cerr<<"Starting Quaternion::TestClass()\n"; + for (int k=0; k +#pragma hdrstop + +#if !defined(SCALAR_HPP) + #include +#endif + + +int + Round(Scalar value) +{ + int whole_part = floor(value); + Scalar fractional_part = value - whole_part; + if (fractional_part >= 0.5) + { + return whole_part + 1; + } + else + { + return whole_part; + } +} + + + +void + Find_Roots( + Scalar a, // a*x*x + b*x + c = 0 + Scalar b, + Scalar c, + Scalar *center, + Scalar *range + ) +{ + + // + //--------------------------------- + // See if the quadratic is solvable + //--------------------------------- + // + *range = b*b - 4.0f*a*c; + if (*range < 0.0f || Small_Enough(a)) + { + *range = -1.0f; + } + + else + { + // + //--------------------------- + // Solve the single root case + //--------------------------- + // + a *= 2.0f; + *center = -b / a; + if (*range < SMALL) + { + *range = 0.0f; + } + + // + //-------------------------- + // Find the two-root extents + //-------------------------- + // + else + { + *range = Sqrt(*range); + *range /= a; + } + } +} + +static void + Verify_Arguments( + const char *str, + void *value + ) +{ + if (str == NULL) + { + Fail("Convert_From_Ascii - str == NULL"); + } + if (value == NULL) + { + Fail("Convert_From_Ascii - value == NULL"); + } + if (isalpha(*str)) + { + cout << "Convert_From_Ascii - str == " << str << "\n"; + Fail("Convert_From_Ascii - isalpha(*str)"); + } +} + +void + Convert_From_Ascii( + const char *str, + char *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = (char)atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + unsigned char *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = (unsigned char)atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + int *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + unsigned int *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atoi(str); +} + +void + Convert_From_Ascii( + const char *str, + long *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atol(str); +} + +void + Convert_From_Ascii( + const char *str, + unsigned long *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atol(str); +} + +void + Convert_From_Ascii( + const char *str, + Scalar *value + ) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atof(str); +} + + diff --git a/CODE/RP/MUNGA/SCALAR.HPP b/CODE/RP/MUNGA/SCALAR.HPP new file mode 100644 index 0000000..da47b36 --- /dev/null +++ b/CODE/RP/MUNGA/SCALAR.HPP @@ -0,0 +1,74 @@ +//===========================================================================// +// File: scalar.hpp // +// Project: MUNGA Brick: None assigned - coding styles, etc. // +// Contents: Base information used by all MUNGA source files // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SCALAR_HPP) +# define SCALAR_HPP + +# if !defined(MEMSTRM_HPP) +# include +# endif + +# if !defined(M_PI) +# define M_PI 3.14159265358979323846 +# endif + + typedef float Scalar; + +# define PI ((Scalar)(M_PI)) +# define PI_OVER_2 ((Scalar)(M_PI/2.0)) +# define PI_OVER_3 ((Scalar)(M_PI/3.0)) +# define PI_OVER_4 ((Scalar)(M_PI/4.0)) +# define PI_OVER_6 ((Scalar)(M_PI/6.0)) +# define TWO_PI ((Scalar)(2.0*M_PI)) +# define DEG_PER_RAD ((Scalar)(180.0/M_PI)) +# define RAD_PER_DEG ((Scalar)(M_PI/180.0)) + + inline Scalar Lerp(Scalar a, Scalar b, Scalar t) + {return a*(1.0f - t) + b*t;} + inline Logical Small_Enough(Scalar x,Scalar e=SMALL) + {return fabs(x) <= e;} + inline Logical Close_Enough(Scalar x,Scalar y,Scalar e=SMALL) + {return fabs(x-y) <= e;} + + int + Round(Scalar value); + + + + void + Find_Roots( + Scalar a, // a*x*x + b*x + c = 0 + Scalar b, + Scalar c, + Scalar *center, + Scalar *range + ); + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + Scalar *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const Scalar *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + void + Convert_From_Ascii(const char *str, Scalar *value); + + +#endif + diff --git a/CODE/RP/MUNGA/SCHAIN.CPP b/CODE/RP/MUNGA/SCHAIN.CPP new file mode 100644 index 0000000..c8d99f2 --- /dev/null +++ b/CODE/RP/MUNGA/SCHAIN.CPP @@ -0,0 +1,505 @@ +//===========================================================================// +// File: schain.cc // +// Contents: Implementation details of safe chains // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 11/01/94 JMA Made compatible with SGI CC, merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SCHAIN_HPP) + #include +#endif + +#if !defined(NODE_HPP) + #include +#endif + +// +//########################################################################### +// SCHAINLINK +//########################################################################### +// + +MemoryBlock + SChainLink::AllocatedMemory( + sizeof(SChainLink), + SCHAINLINK_MEMORYBLOCK_ALLOCATION, + SCHAINLINK_MEMORYBLOCK_ALLOCATION, + "SChainLink" + ); + +// +//########################################################################### +// SChainLink +//########################################################################### +// +SChainLink::SChainLink( + SChain *chain, + Plug *plug, + SChainLink *nextSChainLink, + SChainLink *prevSChainLink +): + Link(chain, plug) +{ + // + //------------------------- + // Link into existing chain + //------------------------- + // + if ((this->nextSChainLink = nextSChainLink) != NULL) + { + Check(nextSChainLink); + nextSChainLink->prevSChainLink = this; + } + if ((this->prevSChainLink = prevSChainLink) != NULL) + { + Check(prevSChainLink); + prevSChainLink->nextSChainLink = this; + } +} + +// +//########################################################################### +// ~SChainLink +//########################################################################### +// +SChainLink::~SChainLink() +{ + SChain *chain = Cast_Object(SChain*, socket); + + // + //--------------------------------------------- + // Notify iterators that the link is going away + //--------------------------------------------- + // + chain->SendIteratorMemo(PlugRemoved, this); + + // + //--------------------------- + // Remove from existing links + //--------------------------- + // + if (prevSChainLink != NULL) + { + Check(prevSChainLink); + prevSChainLink->nextSChainLink = nextSChainLink; + } + else + { + Check(chain); + chain->head = nextSChainLink; + } + if (nextSChainLink != NULL) + { + Check(nextSChainLink); + nextSChainLink->prevSChainLink = prevSChainLink; + } + else + { + Check(chain); + chain->tail = prevSChainLink; + } + prevSChainLink = nextSChainLink = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (chain->GetReleaseNode() != NULL) + { + Check(chain->GetReleaseNode()); + chain->GetReleaseNode()->ReleaseLinkHandler(chain, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SChainLink::TestInstance() const +{ + Link::TestInstance(); + + if (prevSChainLink != NULL) + { + Check_Signature(prevSChainLink); + } + if (nextSChainLink != NULL) + { + Check_Signature(nextSChainLink); + } + return True; +} + +// +//########################################################################### +// SCHAIN +//########################################################################### +// + +// +//########################################################################### +// SChain +//########################################################################### +// +SChain::SChain( + Node *node +) : +SafeSocket( + node +) +{ + head = NULL; + tail = NULL; +} + +// +//########################################################################### +// ~SChain +//########################################################################### +// +SChain::~SChain() +{ + SetReleaseNode(NULL); + while (head != NULL) + { + Unregister_Object(head); + delete head; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SChain::TestInstance() const +{ + SafeSocket::TestInstance(); + + if (head != NULL) + { + Check(head); + } + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + SChain::AddImplementation( + Plug *plug + ) +{ + tail = new SChainLink(this, plug, NULL, tail); + Register_Object(tail); + if (head == NULL) + { + head = tail; + } +} + +// +//########################################################################### +// InsertPlug +//########################################################################### +// +SChainLink* + SChain::InsertSChainLink( + Plug *plug, + SChainLink *link + ) +{ + Check(this); + Check(link); + Check(plug); + + SChainLink *new_link = + new SChainLink( + this, + plug, + link, + link->prevSChainLink + ); + Register_Object(new_link); + + Check(head); + if (head == link) + { + head = new_link; + } + return new_link; +} + +// +//########################################################################### +// SChainIterator +//########################################################################### +// +SChainIterator::SChainIterator(SChain *chain): + SafeIterator(chain) +{ + Check(chain); + currentLink = chain->head; +} + +SChainIterator::SChainIterator(const SChainIterator &iterator): + SafeIterator(Cast_Object(SChain*, iterator.socket)) +{ + Check(&iterator); + currentLink = iterator.currentLink; +} + +SChainIterator::~SChainIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SChainIterator::TestInstance() const +{ + SafeIterator::TestInstance(); + + if (currentLink != NULL) + { + Check(currentLink); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + SChainIterator::First() +{ + currentLink = Cast_Object(SChain*, socket)->head; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + SChainIterator::Last() +{ + currentLink = Cast_Object(SChain*, socket)->tail; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + SChainIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->nextSChainLink; +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + SChainIterator::Previous() +{ + Check(currentLink); + currentLink = currentLink->prevSChainLink; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void* + SChainIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->GetPlug(); + currentLink = currentLink->nextSChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void* + SChainIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->prevSChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + SChainIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + return currentLink->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + SChainIterator::GetSize() +{ + SChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(SChain*, socket)->head; + link != NULL; + link = link->nextSChainLink + ) + { + Check(link); + count++; + } + return count; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void* + SChainIterator::GetNthImplementation( + CollectionSize index + ) +{ + SChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(SChain*, socket)->head; + link != NULL; + link = link->nextSChainLink + ) + { + Check(link); + if (count == index) + { + currentLink = link; + return currentLink->GetPlug(); + } + count++; + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + SChainIterator::Remove() +{ + Check(currentLink); + Unregister_Object(currentLink); + delete currentLink; +} + +// +//############################################################################# +// InsertImplementation +//############################################################################# +// +void + SChainIterator::InsertImplementation(Plug *plug) +{ + currentLink = + Cast_Object(SChain*, socket)->InsertSChainLink(plug, currentLink); + Check(currentLink); +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + SChainIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + if (memo == PlugRemoved) + { + if (content == currentLink) + { + Next(); + } + } +} + +#ifdef TEST_CLASS +# include "schain.tcp" +#endif diff --git a/CODE/RP/MUNGA/SCHAIN.HPP b/CODE/RP/MUNGA/SCHAIN.HPP new file mode 100644 index 0000000..ee0d1cb --- /dev/null +++ b/CODE/RP/MUNGA/SCHAIN.HPP @@ -0,0 +1,324 @@ +//===========================================================================// +// File: schain.hh // +// Project: MUGNA Brick: Connection engine // +// Contents: Interface definition for safe chains // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 11/01/94 JMA Made compatible with SGI CC, merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release mechanism // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SCHAIN_HPP) +# define SCHAIN_HPP + +# if !defined(SFESKT_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define SCHAINLINK_MEMORYBLOCK_ALLOCATION (100) + + class SChainLink: + public Link + { + friend class SChain; + friend class SChainIterator; + + public: + ~SChainLink(); + Logical + TestInstance() const; + + private: + SChainLink( + SChain *chain, + Plug *plug, + SChainLink *nextSChainLink, + SChainLink *prevSChainLink + ); + + SChainLink *nextSChainLink; + SChainLink *prevSChainLink; + + private: + static MemoryBlock + AllocatedMemory; + + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SChain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SChain: + public SafeSocket + { + friend class SChainLink; + friend class SChainIterator; + + public: + // + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // Public interface + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // + SChain(Node *node); + ~SChain(); + + Logical + TestInstance() const; + static void + TestClass(); + static void + ProfileClass(); + + protected: + // + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // Protected interface + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // + void + AddImplementation(Plug *plug); + + private: + // + //----------------------------------------------------------------------- + // Private utilities + //----------------------------------------------------------------------- + // + SChainLink* + InsertSChainLink( + Plug *plug, + SChainLink *link + ); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + SChainLink *head; + SChainLink *tail; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SChainOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class SChainOf: + public SChain + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + SChainOf(Node *node); + ~SChainOf(); + + // + //-------------------------------------------------------------------- + // Socket methods (see Socket for full listing) + //-------------------------------------------------------------------- + // + void + Add(T plug) + {AddImplementation(Cast_Object(Plug*,plug));} + }; + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SChainOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + SChainOf::SChainOf(Node *node): + SChain(node) + { + } + + template + SChainOf::~SChainOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SChainIterator: + public SafeIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors, Destructor and testing + //-------------------------------------------------------------------- + // + SChainIterator(SChain *chain); + SChainIterator(const SChainIterator &iterator); + ~SChainIterator(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + void + First(); + void + Last(); + void + Next(); + void + Previous(); + CollectionSize + GetSize(); + void + Remove(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void* + ReadAndNextImplementation(); + void* + ReadAndPreviousImplementation(); + void* + GetCurrentImplementation(); + void* + GetNthImplementation( + CollectionSize index + ); + void + InsertImplementation(Plug *plug); + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + ReceiveMemo( + IteratorMemo memo, + void *content + ); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SChainLink *currentLink; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SChainIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class SChainIteratorOf: + public SChainIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors and Destructor + //-------------------------------------------------------------------- + // + SChainIteratorOf(SChainOf *chain); + SChainIteratorOf(SChainOf &chain); + SChainIteratorOf(const SChainIteratorOf &iterator); + + ~SChainIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T + ReadAndNext() + {return (T)ReadAndNextImplementation();} + T + ReadAndPrevious() + {return (T)ReadAndPreviousImplementation();} + T + GetCurrent() + {return (T)GetCurrentImplementation();} + T + GetNth(CollectionSize index) + {return (T)GetNthImplementation(index);} + void + Insert(T plug) + {InsertImplementation(Cast_Object(Plug*,plug));} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~ SChainIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~ + + template + SChainIteratorOf::SChainIteratorOf(SChainOf *chain): + SChainIterator(chain) + { + } + + template + SChainIteratorOf::SChainIteratorOf(SChainOf &chain): + SChainIterator(&chain) + { + } + + template + SChainIteratorOf::SChainIteratorOf(const SChainIteratorOf &iterator): + SChainIterator(iterator) + { + } + + template + SChainIteratorOf::~SChainIteratorOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/SCHAIN.TCP b/CODE/RP/MUNGA/SCHAIN.TCP new file mode 100644 index 0000000..7ba54c0 --- /dev/null +++ b/CODE/RP/MUNGA/SCHAIN.TCP @@ -0,0 +1,526 @@ +//======================================================================= +// File: SCHNTST.CPP +// +// Created: Thursday, September 29, 1994, 2:37 PM +// Author: Eric Huffman +// Project: Node.Û +// Compiler: 7.0, Û Symantec Corporation 1994 +//----------------------------------------------------------------------- +// 11/03/94 ECH Made compatible with BC4.0 +//----------------------------------------------------------------------- +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved +// PROPRIETARY AND CONFIDENTIAL +//======================================================================= + +#include "time.hpp" + +class SChainTestPlug: + public Plug +{ +public: + long value; + + SChainTestPlug(long value); + ~SChainTestPlug(); +}; + +class SChainTestNode: + public Node +{ +public: + SChainOf + chain1, + chain2; + + SChainTestNode(); + ~SChainTestNode(); + + void RunProfile(); + void RunTest(); +}; + +SChainTestPlug::SChainTestPlug(long value): + Plug() +{ + this->value = value; +} + +SChainTestPlug::~SChainTestPlug() +{ +} + +SChainTestNode::SChainTestNode(): + Node(), chain1(this), chain2(this) +{ +} + +SChainTestNode::~SChainTestNode() +{ +} + +#define RandInt(x) (rand() % x + 1) + +// +//########################################################################### +// ProfileClass +//########################################################################### +// + +void + SChain::ProfileClass() +{ + SChainTestNode testNode; + Time startTicks = Now(); + + Test_Message("SChain::ProfileClass\n"); + + testNode.RunProfile(); + + Test_Message("SChain::ProfileClass elapsed = " << (Now() - startTicks) << endl); +} + +// +//########################################################################### +// TestClass +//########################################################################### +// + +void + SChain::TestClass() +{ + DEBUG_STREAM << "Starting SChain test...\n"; + + SChainTestNode testNode; + + testNode.RunTest(); +} + +void + SChainTestNode::RunProfile() +{ + SChainTestPlug *testPlug1; + int i; + Time startTicks; + + // + //-------------------------------------------------------------------- + // Run timing tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + startTicks = Now(); + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new SChainTestPlug(i); + Register_Object( testPlug1 ); + chain1.Add(testPlug1); + chain2.Add(testPlug1); + } + Test_Message("SChainTestNode::RunTest Create = " << (Now() - startTicks) << endl); + + /* + * Iterate over both sockets + */ + startTicks = Now(); + { + SChainIteratorOf iterator1(&chain1); + SChainIteratorOf iterator2(&chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator2.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + } + Test_Message("SChainTestNode::RunTest Iterate = " << (Now() - startTicks) << endl); + + /* + * Destroy from chain1, verify with chain2 + */ + startTicks = Now(); + { + SChainIteratorOf iterator1(&chain1); + SChainIteratorOf iterator2(&chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + + Unregister_Object( testPlug1 ); + delete(testPlug1); + } + Verify( i == TEST_CLASS ); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + Test_Message("SChainTestNode::RunTest Destroy = " << (Now() - startTicks) << endl); +} + +void + SChainTestNode::RunTest() +{ + SChainTestPlug *testPlug1, *testPlug2; + int i, j; +// Time startTicks; + + // + //-------------------------------------------------------------------- + // Stress tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new SChainTestPlug(i); + Register_Object( testPlug1 ); + chain1.Add(testPlug1); + chain2.Add(testPlug1); + } + + /* + * Test first and last + */ + { + SChainIteratorOf iterator1(&chain1); + SChainIteratorOf iterator2(&chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + iterator1.First(); + iterator2.First(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + Verify( testPlug1 == iterator1.GetNth(0) ); + Verify( testPlug1 == iterator2.GetNth(0) ); + + iterator1.Last(); + iterator2.Last(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + Verify( testPlug1 == iterator1.GetNth(TEST_CLASS - 1) ); + Verify( testPlug1 == iterator2.GetNth(TEST_CLASS - 1) ); + } + + /* + * Test next and prev + */ + { + SChainIteratorOf iterator1(&chain1); + SChainIteratorOf iterator2(&chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + iterator1.Next(); + iterator2.Next(); + + i++; + } + Verify( i == TEST_CLASS ); + + iterator1.Last(); + iterator2.Last(); + + i = TEST_CLASS - 1; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + iterator1.Previous(); + iterator2.Previous(); + + i--; + } + Verify( i == -1 ); + } + + /* + * Test read next and read prev + */ + { + SChainIteratorOf iterator1(&chain1); + SChainIteratorOf iterator2(&chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + testPlug2 = iterator2.ReadAndNext(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + i++; + } + Verify( i == TEST_CLASS ); + + iterator1.Last(); + iterator2.Last(); + + i = TEST_CLASS - 1; + while ((testPlug1 = iterator1.ReadAndPrevious()) != NULL) + { + testPlug2 = iterator2.ReadAndPrevious(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + i--; + } + Verify( i == -1 ); + } + + /* + * Test nth + */ + { + SChainIteratorOf iterator1(&chain1); + SChainIteratorOf iterator2(&chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = iterator1.GetNth(i); + testPlug2 = iterator2.GetNth(i); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + } + } + + /* + * Test Remove + */ + { + SChainIteratorOf iterator1(&chain1); + SChainIteratorOf iterator2(&chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(0); + + Check( testPlug2 ); + Verify( testPlug2->value == i ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + i++; + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + + /* + * Test random deletion + */ + { + /* + * Add plugs to both sockets + */ + SChainIteratorOf iterator1(chain1); + SChainIteratorOf iterator2(chain2); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new SChainTestPlug(i); + Register_Object( testPlug1 ); + chain1.Add(testPlug1); + chain2.Add(testPlug1); + } + } + + { + /* + * Perform random deletion + */ + int size, index; + SChainIteratorOf iterator1(chain1); + SChainIteratorOf iterator2(chain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while((size = iterator1.GetSize()) != 0) + { + index = RandInt(size) - 1; + testPlug1 = iterator1.GetNth(index); + Check( testPlug1 ); + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(index); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + i++; + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + + /* + * Test insertion + */ + { + SChainIteratorOf iterator1(chain1); + + Verify(iterator1.GetSize() == 0); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new SChainTestPlug(i); + Register_Object(testPlug1); + + if (i == 0) + { + chain1.Add(testPlug1); + } + else + { + iterator1.First(); + iterator1.Insert(testPlug1); + } + } + + for (i = 0, j = TEST_CLASS-1; i < TEST_CLASS; i++, j--) + { + testPlug1 = iterator1.GetNth(i); + Check(testPlug1); + Verify(testPlug1->value == j); + } + + iterator1.DeletePlugs(); + } + { + SChainIteratorOf iterator1(chain1); + + Verify(iterator1.GetSize() == 0); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new SChainTestPlug(i); + Register_Object(testPlug1); + + if (i == 0) + { + chain1.Add(testPlug1); + } + else + { + iterator1.Last(); + iterator1.Insert(testPlug1); + } + } + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = iterator1.GetNth(i); + Check(testPlug1); + if (i == TEST_CLASS-1) + { + Verify(testPlug1->value == 0); + } + else + { + Verify(testPlug1->value == i+1); + } + } + + iterator1.DeletePlugs(); + } + +} + diff --git a/CODE/RP/MUNGA/SCNROLE.HPP b/CODE/RP/MUNGA/SCNROLE.HPP new file mode 100644 index 0000000..6685803 --- /dev/null +++ b/CODE/RP/MUNGA/SCNROLE.HPP @@ -0,0 +1,162 @@ +//===========================================================================// +// File: scnrole.hpp // +// Project: MUNGA // +// Contents: Scenario Mission Specific Data // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/9/96 JM initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined (SCNROLE_HPP) +# define SCNROLE_HPP + +# if !defined (NODE_HPP) +# include +# endif + +# if !defined (CSTR_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(SCALAR_HPP) +# include +# endif + + class NotationFile; + +//############################################################################## +//##################### ScenarioRole::ModelResource ###################### +//############################################################################## + + struct ScenarioRole__ModelResource + { + Scalar + killBonus, + damageReceivedModifier, + damageInflictedModifier, + damageBias, + friendlyFirePenalty; + + int + returnFromDeath; + }; + +//########################################################################### +//##################### Class ScenarioRole ############################# +//########################################################################### + +class ScenarioRole : + public Node +{ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Score Support + // + public: + + Scalar + CalcDamageReceivedScore(const Scalar &damage_received); + + protected: + + Scalar + damageInflictedModifier, + damageReceivedModifier, + friendlyFirePenalty, + damageBias, + killBonus; + + CString + roleName; + + int + returnFromDeath; + + public: + + const int + GetReturnFromDeath() + { Check(this); return returnFromDeath; } + + Scalar + GetDamageInflictedModifier() const + { Check(this); return damageInflictedModifier; } + + Scalar + GetDamageReceivedModifier() const + { Check(this); return damageReceivedModifier; } + + Scalar + GetFriendlyFirePenalty() const + { Check(this); return friendlyFirePenalty; } + + Scalar + GetDamageBias() const + { Check(this); return damageBias; } + + Scalar + GetKillBonus() const + { Check(this); return killBonus; } + + CString + GetRoleName() const + {Check(this); return roleName; } + + void + SetDamageInflictedModifier(const Scalar &value) + { Check(this); damageInflictedModifier = value; } + + void + SetDamageReceivedModifier(const Scalar value) + { Check(this); damageReceivedModifier = value; } + + void + SetFriendlyFirePenalty(const Scalar &value) + { Check(this); friendlyFirePenalty = value; } + + void + SetDamageBias(const Scalar &value) + { Check(this); damageBias = value; } + + void + SetKillBonus(const Scalar &value) + { Check(this); killBonus = value; } + + void + SetReturnFromDeath(const int &value) + { Check(this); returnFromDeath = value ; } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction + + public: + + typedef ScenarioRole__ModelResource ModelResource; + + ScenarioRole( + const CString &role_name, + const CString &model_file + ); + + ScenarioRole(const CString &role_name); + + ~ScenarioRole(); + + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model = NULL + ); +}; +#endif diff --git a/CODE/RP/MUNGA/SEGMENT.CPP b/CODE/RP/MUNGA/SEGMENT.CPP new file mode 100644 index 0000000..6a46475 --- /dev/null +++ b/CODE/RP/MUNGA/SEGMENT.CPP @@ -0,0 +1,294 @@ +//===========================================================================// +// File: segment.cc // +// Project: MUNGA Brick: Model Manager // +// Contents: Skeleton Heirachical element // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/11/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SEGMENT_HPP) +# include +#endif + +#if !defined(JOINT_HPP) +# include +#endif + +//############################################################################# +// Segment::VideoObjectNames Support +// + +CString* + EntitySegment::VideoObjectNames::GetVideoObjectName( + Enumeration damage_graphic_state + ) +{ + Check(this); + CStringPlug *my_plug = videoObjectNames.Find(damage_graphic_state); + if (my_plug) + { + Check(my_plug); + return my_plug->GetPointer(); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment::VideoObjectNames::VideoObjectNames() : + videoObjectNames(NULL, False) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment::VideoObjectNames::~VideoObjectNames() +{ + VChainIteratorOf iterator(videoObjectNames); + iterator.DeletePlugs(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::VideoObjectNames::AddVideoObjectName( + const CString &new_name, + Enumeration damage_graphic_state + ) +{ + Check(this); + CStringPlug *new_string = new CStringPlug(new_name); + Register_Object(new_string); + + videoObjectNames.AddValue(new_string, damage_graphic_state); +} + + +//############################################################################# +// Segment Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment::EntitySegment( + CString segment_name, + int this_index, + int parent_index, + int joint_index, + Joint *joint_ptr, + LinearMatrix &lin_matrix, + EntitySegment *parent_segment, + Logical is_site, + int primary_damage_zone +) : + baseOffset(LinearMatrix::Identity), + childIndexTable(NULL, True), + damageZoneTable(NULL,True), + videoObjectTable(NULL,True), + childPointerTable(NULL,True) +{ + segmentModified = True; + thisIndex = this_index; + parentIndex = parent_index; + jointIndex = joint_index; + jointPointer = joint_ptr; + baseOffset = lin_matrix; + parentSegment =parent_segment; + segmentName = segment_name; + siteSegment = is_site; + primaryDamageZone = primary_damage_zone; // Add To constructor Call + + segmentToParent = baseOffset; + segmentToEntity = baseOffset; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CString* + EntitySegment::GetVideoObjectName( + SkeletonType skl_type, + Enumeration damage_graphic_state + ) +{ + Check(this); + VideoObjectNames *video_names = videoObjectTable.Find(skl_type); + if(video_names) + { + return video_names->GetVideoObjectName(damage_graphic_state); + } + else + { + return NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment::~EntitySegment() +{ + IntegerTableIterator iterator_child( childIndexTable); + iterator_child.DeletePlugs(); + + IntegerTableIterator iterator_damage(damageZoneTable); + iterator_damage.DeletePlugs(); + + VideoTableIterator iterator_video(videoObjectTable); + iterator_video.DeletePlugs(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddChildIndex(int child_index, int index) +{ + Check(this); + IntegerPlug *child_plug = new IntegerPlug(child_index); + Register_Object(child_plug); + childIndexTable.AddValue(child_plug, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddChildPointer(EntitySegment* child_ptr, int index) +{ + Check(this); + childPointerTable.AddValue(child_ptr, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddDamageZone(int damage_index, int index) +{ + Check(this); + Check_Pointer(&damageZoneTable); + IntegerPlug *damage_plug = new IntegerPlug(damage_index); + Register_Object(damage_plug); + damageZoneTable.AddValue(damage_plug, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddVideoObjectName( + CString video_object_name, + Enumeration skl_type, + Enumeration damage_graphic_state + ) +{ + Check(this); + Check_Pointer(&videoObjectTable); + VideoTableIterator iterator(videoObjectTable); + + VideoObjectNames *names_plug = iterator.Find(skl_type); + if(!names_plug) + { + names_plug = new VideoObjectNames(); + Register_Object(names_plug); + videoObjectTable.AddValue(names_plug, skl_type); + } + names_plug->AddVideoObjectName(video_object_name, damage_graphic_state); + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const LinearMatrix& + EntitySegment::GetSegmentToParent() +{ + Check(this); + + // + //----------------------------------------------------------------------- + // Recalculate the segment to parent matrix if we have a joint and it has + // changed + //----------------------------------------------------------------------- + // + if (jointPointer) + { + Check(jointPointer); + if (jointPointer->IsJointModified()) + { + jointPointer->JointModified(False); + LinearMatrix + t1 = baseOffset, + t2; + + switch(jointPointer->GetJointType()) + { + case Joint::BallJointType: + { + LinearMatrix euler_angles = LinearMatrix::Identity; + euler_angles = jointPointer->GetEulerAngles(); + t2.Invert(euler_angles); + segmentToParent.Multiply(t1,t2); + } + break; + + case Joint::HingeXJointType: + case Joint::HingeYJointType: + case Joint::HingeZJointType: + { + LinearMatrix hinge_joint = LinearMatrix::Identity; + hinge_joint = jointPointer->GetHinge(); + t2.Invert(hinge_joint); + segmentToParent.Multiply(t1,t2); + } + break; + + case Joint::BallTranslationJointType: + { + // + //------------------------------------- + // We only want to invert the rotations + //------------------------------------- + // + LinearMatrix euler_angles = LinearMatrix::Identity; + euler_angles = jointPointer->GetEulerAngles(); + segmentToParent.Invert(euler_angles); + t2.Multiply(t1,segmentToParent); + t1 = LinearMatrix::Identity; + t1 = jointPointer->GetTranslation(); + segmentToParent.Multiply(t2,t1); + } + break; + } + } + } + return segmentToParent; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const LinearMatrix& + EntitySegment::GetSegmentToEntity() +{ + Check(this); + + // + //--------------------------------------------------------------------- + // Recalculate the segment to entity transform if something has changed + //--------------------------------------------------------------------- + // + if (segmentModified && parentSegment) + { + Check(parentSegment); + segmentToEntity.Multiply( + GetSegmentToParent(), + parentSegment->GetSegmentToEntity() + ); + ModifySegment(False); + } + return segmentToEntity; +} + diff --git a/CODE/RP/MUNGA/SEGMENT.HPP b/CODE/RP/MUNGA/SEGMENT.HPP new file mode 100644 index 0000000..38448f3 --- /dev/null +++ b/CODE/RP/MUNGA/SEGMENT.HPP @@ -0,0 +1,266 @@ +//===========================================================================// +// File: segment.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Skeleton Heirachical element // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/11/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(SEGMENT_HPP) +# define SEGMENT_HPP + +# if !defined(TABLE_HPP) +# include +# endif + +# if !defined(LINMTRX_HPP) +# include +# endif + +# if !defined(CSTR_HPP) +# include +# endif + +# if !defined(VCHAIN_HPP) +# include +# endif + + class DamageZone; + class Joint; + class JointedMover; + +//########################################################################## +//##################### Segment::VideoObjectNames ########################## +//########################################################################## + + class EntitySegment__VideoObjectNames : + public Plug + { + public: + CString* + GetVideoObjectName(Enumeration damage_graphic_state); + + void + AddVideoObjectName( + const CString &new_name, + Enumeration damage_graphic_state + ); + + + EntitySegment__VideoObjectNames(); + ~EntitySegment__VideoObjectNames(); + + protected: + + typedef PlugOf CStringPlug; + + typedef VChainOf + VideoObjectNamesSocket; + + VideoObjectNamesSocket videoObjectNames; + }; + +//########################################################################## +//########################## Segment ############################### +//########################################################################## + + class EntitySegment : + public Plug + { + friend class JointedMover; + + public: + typedef EntitySegment__VideoObjectNames VideoObjectNames; + typedef TableOf SegmentTable; + typedef TableIteratorOf SegmentTableIterator; + typedef PlugOf IntegerPlug; + typedef TableOf IntegerTable; + typedef TableIteratorOf IntegerTableIterator; + + enum SkeletonType { + SkeletonType_N, // Exterior + SkeletonType_S, // Interior + SkeletonType_T, + SkeletonType_O, + SkeletonType_A, + SkeletonType_B, + SkeletonType_C, + SkeletonType_D, + SkeletonTypeCount + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Segment Data + // + protected: + Logical + segmentModified, + siteSegment; + + LinearMatrix + segmentToParent, + segmentToEntity, + baseOffset; + + typedef PlugOf CStringPlug; + typedef TableOf VideoObjectTable; + typedef TableIteratorOf VideoTableIterator; + + VideoObjectTable + videoObjectTable; + + Joint + *jointPointer; + int + jointIndex; + EntitySegment + *parentSegment; + int + parentIndex; + int + thisIndex; + + IntegerTable + damageZoneTable, + childIndexTable; + int + primaryDamageZone; + + SegmentTable + childPointerTable; + + CString + segmentName; + + const LinearMatrix& + GetSegmentToParent(); + + void + SetSegmentToEntity(LinearMatrix& new_matrix) + {Check(this); segmentToEntity = new_matrix;} + void + SetSegmentToParent(LinearMatrix& new_matrix) + {Check(this); segmentToParent = new_matrix;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Accessors + // + public: + void + ModifySegment(Logical modified = True) + {Check(this); segmentModified = modified;} + + const LinearMatrix& + GetBaseOffset() const + {Check(this); return baseOffset;} + + const LinearMatrix& + GetSegmentToEntity(); + + int + GetPrimaryDamageZone() const + {Check(this); return primaryDamageZone;} + int + GetParentIndex() const + {Check(this); return parentIndex;} + + const EntitySegment* + GetParent() const + {Check(this); return parentSegment;} + + int + GetIndex() const + {Check(this); return thisIndex;} + + int + IsSiteSegment() + {Check(this); return siteSegment;} + + CString + GetName() const + {Check(this); return segmentName;} + + int + GetJointIndex() const + {Check(this); return jointIndex;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Children of Segments Support + // + public: + CString* + GetVideoObjectName( + SkeletonType skl_type = SkeletonType_N, + Enumeration damage_graphic_state = 0 + ); + + void + AddChildIndex(int child_index, int index); + + void + AddChildPointer(EntitySegment *child_pointer, int index); + + void + AddDamageZone(int damage_index, int index); + + void + AddVideoObjectName( + CString video_object_name, + Enumeration skl_type, + Enumeration damage_graphic_state = 0 + ); + + IntegerTableIterator* + MakeChildIndexTable() + { + Check(this); + Check_Pointer(&childIndexTable); + IntegerTableIterator *iterator = new + IntegerTableIterator(&childIndexTable); + return iterator; + } + + IntegerTableIterator* + MakeDamageZoneIndexTable() + { + Check(this); + Check_Pointer(&damageZoneTable); + IntegerTableIterator *iterator = new + IntegerTableIterator(&damageZoneTable); + return iterator; + } + + EntitySegment( + CString segment_name, + int this_index, + int parent_index, + int joint_index, + Joint *joint_ptr, + LinearMatrix &lin_matrix, + EntitySegment *parent_segment, + Logical is_site, + int primary_damage_zone + + ); + ~EntitySegment(); + }; + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + EntitySegment::SkeletonType *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const EntitySegment::SkeletonType *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + +#endif diff --git a/CODE/RP/MUNGA/SET.CPP b/CODE/RP/MUNGA/SET.CPP new file mode 100644 index 0000000..024a321 --- /dev/null +++ b/CODE/RP/MUNGA/SET.CPP @@ -0,0 +1,162 @@ +//===========================================================================// +// File: set.cpp // +// Project: MUNGA Brick: Connection Engine // +// Contents: Implementation of Sets and useful set operations // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 GDU Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996 Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "munga.hpp" + +#include "set.hpp" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Set +//############################################################################# +// +Set::Set(Node *node): + Socket(node), + contents(NULL) +{ + +} + + + + +// +//############################################################################# +// ~Set +//############################################################################# +// +Set::~Set() +{ + SetReleaseNode(NULL); + if (contents) + { + delete contents; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Set::TestInstance() const +{ + Socket::TestInstance(); + Check(contents); + return True; +} + + +// +//############################################################################# +// Union +// +// Merge contents of this with rhs. Items that occur in either set are placed +// in the resulting set, with no duplication. It is assumed that both operands +// are proper sets, ie. they contain no duplicates. +//############################################################################# +// + +Set + Set::Union(const Set &) const +{ + Check(this); + + + Set result(NULL); + + return result; +} + + +// +//############################################################################# +// Intersection +// +// Merge contents of this with rhs. Items that occur in both sets are placed +// only once in the resulting set. It is assumed that both operands are proper +// sets, ie. they contain no duplicates. +// +// This implementation of set intersection is dumb and slow. +//############################################################################# +// + +Set + Set::Intersection(const Set &rhs) const +{ + Check(this); + Check(rhs); + + // Contents iterator is a SetIterator and not a ChainIterator in order to + // have access to the ChainIterator::ReadAndNextImplentation. + // We circumvent encapsulation protections by declaring Set a friend of SetIterator + // (which derives from ChainIterator). Set is not a friend of ChainIterator. + + SetIterator contents_iterator(contents); + + // Casting away const is safe since our local iterator is not going to insert or + // remove items from rhs. + SetIterator rhs_iterator((Set *) &rhs); + Plug *lhs_plug; + Plug *rhs_plug; + Set result(NULL); + + + while ((lhs_plug = Cast_Object(Plug *, contents_iterator.ReadAndNextImplementation())) != NULL) + { + while ((rhs_plug = Cast_Object(Plug *,rhs_iterator.ReadAndNextImplementation())) != NULL) + { + if (lhs_plug == rhs_plug) + { + result.AddImplementation(lhs_plug); + } + } + } + return result; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// SetIterator +//############################################################################# +// +SetIterator::SetIterator(Set *set): + ChainIterator(set->contents) +{ + Check(set); +} + +SetIterator::SetIterator(const SetIterator &iterator): + ChainIterator(Cast_Object(Chain*, (Cast_Object(Set *,iterator.socket)->contents))) +{ + Check(&iterator); +} + +SetIterator::SetIterator(Chain *chain): + ChainIterator(chain) +{ + Check(chain); +} + +SetIterator::~SetIterator() +{ +} + + + + diff --git a/CODE/RP/MUNGA/SFESKT.CPP b/CODE/RP/MUNGA/SFESKT.CPP new file mode 100644 index 0000000..f069834 --- /dev/null +++ b/CODE/RP/MUNGA/SFESKT.CPP @@ -0,0 +1,169 @@ +//===========================================================================// +// File: sfeskt.cc // +// Project: MUNGA Brick: Connection Engine // +// Contents: Implementation details for safe socket class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC and merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release mechanism // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SFESKT_HPP) + #include +#endif + +// +//########################################################################### +// SafeSocket +//########################################################################### +// +SafeSocket::SafeSocket(Node *node): + Socket(node) +{ + iteratorHead = NULL; +} + +// +//########################################################################### +// ~SafeSocket +//########################################################################### +// +SafeSocket::~SafeSocket() +{ + Verify(iteratorHead == NULL); +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SafeSocket::TestInstance() const +{ + Socket::TestInstance(); + + if (iteratorHead != NULL) + { + Check_Signature(iteratorHead); + } + return True; +} + +// +//########################################################################### +// SendIteratorMemo +//########################################################################### +// +void + SafeSocket::SendIteratorMemo( + IteratorMemo memo, + void *content + ) +{ + SafeIterator *iterator; + + for ( + iterator = iteratorHead; + iterator != NULL; + iterator = iterator->nextIterator + ) { + Check(iterator); + iterator->ReceiveMemo(memo, content); + } +} + +// +//########################################################################### +// SafeIterator +//########################################################################### +// +SafeIterator::SafeIterator(SafeSocket *safeSocket): + SocketIterator(safeSocket) +{ + // + // Link iterator into sockets set of iterators + // + Check(safeSocket); + if ((nextIterator = safeSocket->iteratorHead) != NULL) + { + Check(nextIterator); + nextIterator->prevIterator = this; + } + prevIterator = NULL; + safeSocket->iteratorHead = this; +} + +// +//########################################################################### +// ~SafeIterator +//########################################################################### +// +SafeIterator::~SafeIterator() +{ + SafeSocket *safeSocket = Cast_Object(SafeSocket*, socket); + + // + // Remove iterator from sockets set of iterators + // + Check(safeSocket); + if (safeSocket->iteratorHead == this) + { + safeSocket->iteratorHead = nextIterator; + } + if (prevIterator != NULL) + { + Check(prevIterator); + prevIterator->nextIterator = nextIterator; + } + if (nextIterator != NULL) + { + Check(nextIterator); + nextIterator->prevIterator = prevIterator; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SafeIterator::TestInstance() const +{ + SocketIterator::TestInstance(); + + if (prevIterator != NULL) + { + Check_Signature(prevIterator); + } + if (nextIterator != NULL) + { + Check_Signature(nextIterator); + } + return True; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + SafeIterator::ReceiveMemo( + IteratorMemo, + void* + ) +{ + Fail("SafeIterator::ReceiveMemo - Should never reach here"); +} + diff --git a/CODE/RP/MUNGA/SFESKT.HPP b/CODE/RP/MUNGA/SFESKT.HPP new file mode 100644 index 0000000..a68a0b5 --- /dev/null +++ b/CODE/RP/MUNGA/SFESKT.HPP @@ -0,0 +1,86 @@ +//===========================================================================// +// File: sfeskt.hh // +// Project: MUNGA Brick: Connection Engine // +// Contents: Interface definition for safe socket class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 ECH Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC and merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release mechanism // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SFESKT_HPP) +# define SFESKT_HPP + +# if !defined(SOCKET_HPP) +# include +# endif + + class SafeIterator; + + typedef int IteratorMemo; + + enum + { + PlugAdded = 0, + PlugRemoved, + NextSafeSocketMemo + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SafeSocket ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SafeSocket: + public Socket + { + friend class SafeIterator; + + public: + ~SafeSocket(); + Logical + TestInstance() const; + + protected: + SafeSocket(Node *node); + + void + SendIteratorMemo( + IteratorMemo memo, + void *content + ); + + private: + SafeIterator *iteratorHead; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SafeIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SafeIterator: + public SocketIterator + { + friend class SafeSocket; + + public: + ~SafeIterator(); + Logical + TestInstance() const; + + protected: + SafeIterator(SafeSocket *safeSocket); + + private: + virtual void + ReceiveMemo( + IteratorMemo memo, + void *content + ); + + SafeIterator *nextIterator; + SafeIterator *prevIterator; + }; + +#endif diff --git a/CODE/RP/MUNGA/SIMULATE.CPP b/CODE/RP/MUNGA/SIMULATE.CPP new file mode 100644 index 0000000..d530c4f --- /dev/null +++ b/CODE/RP/MUNGA/SIMULATE.CPP @@ -0,0 +1,733 @@ +//===========================================================================// +// File: simulate.cc // +// Project: MUNGA Brick: Model Manager // +// Contents: Implementation details of model class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/25/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SIMULATE_HPP) +# include +#endif + +#if !defined(UPDATE_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if defined(TRACE_EXECUTE_WATCHERS) + static BitTrace Execute_Watchers("Execute Watchers"); + #define SET_EXECUTE_WATCHERS() Execute_Watchers.Set() + #define CLEAR_EXECUTE_WATCHERS() Execute_Watchers.Clear() +#else + #define SET_EXECUTE_WATCHERS() + #define CLEAR_EXECUTE_WATCHERS() +#endif + +//############################################################################# +//######################## StateIndicator ############################### +//############################################################################# + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::StateIndicator(): + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL) +{ + Check_Pointer(this); + stateCount = 0; + oldState = 0; + currentState = 0; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::StateIndicator(unsigned max_states): + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL) +{ + Check_Pointer(this); + stateCount = max_states; + oldState = max_states; + currentState = max_states; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::StateIndicator(const StateIndicator &state_indicator): + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL) +{ + Check_Pointer(this); + + // Do not perform deep copy of watchers + stateCount = state_indicator.stateCount; + oldState = state_indicator.oldState; + currentState = state_indicator.currentState; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::~StateIndicator() +{ + Check(this); + + // + // Manual deletion of existing watchers + // + { + SChainIteratorOf iterator(&audioWatcherSocket); + #if DEBUG_LEVEL>2 + Component *component; + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + Dump(component->GetClassID()); + } + Warn(iterator.GetSize() != 0); + #endif + iterator.DeletePlugs(); + } + { + SChainIteratorOf iterator(&videoWatcherSocket); + #if DEBUG_LEVEL>2 + Component *component; + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + Dump(component->GetClassID()); + } + Warn(iterator.GetSize() != 0); + #endif + iterator.DeletePlugs(); + } + { + SChainIteratorOf iterator(&gaugeWatcherSocket); + #if DEBUG_LEVEL>2 + Component *component; + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + Dump(component->GetClassID()); + } + Warn(iterator.GetSize() != 0); + #endif + iterator.DeletePlugs(); + } + Check_Fpu(); +} + +//############################################################################# +// State stuff +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator& + StateIndicator::operator=(const StateIndicator &state_indicator) +{ + // Do not perform assignment of watchers + stateCount = state_indicator.stateCount; + oldState = state_indicator.oldState; + currentState = state_indicator.currentState; + + Check_Fpu(); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + StateIndicator::operator==(const StateIndicator &state_indicator) const +{ + Check_Fpu(); + return + ( + stateCount == state_indicator.stateCount && + oldState == state_indicator.oldState && + currentState == state_indicator.currentState + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + StateIndicator::SetState(unsigned new_state) +{ + Check(this); + Verify(new_state < stateCount); + + // + //-------------------------------------------------------------------------- + // See if the state really changes + // + // NOTE - the old state does change to the current state, simulating a loop + // in the state engine. If it turns out that someone is watching the + // level of the state indicator and doing their own edge detection, + // this might possibly maybe screw something up + //-------------------------------------------------------------------------- + // + oldState = currentState; + if (new_state == currentState) + { + return; + } + + // + //------------------------------------------------------------------- + // If the state has changed, update the state values and then run any + // watchers + //------------------------------------------------------------------- + // + currentState = new_state; + Component *watcher; + + SET_EXECUTE_WATCHERS(); + + // Audio + { + SChainIteratorOf iterator(audioWatcherSocket); + Check(&iterator); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Video + { + SChainIteratorOf iterator(videoWatcherSocket); + Check(&iterator); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Gauge + { + SChainIteratorOf iterator(gaugeWatcherSocket); + Check(&iterator); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + CLEAR_EXECUTE_WATCHERS(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ostream& + operator << (ostream &strm, const StateIndicator &state_indicator) +{ + Check(&state_indicator); + + strm << "[" << state_indicator.stateCount << ","; + strm << state_indicator.oldState << ","; + strm << state_indicator.currentState << "]"; + + return strm; +} + +//############################################################################# +// Test Support +// +Logical + StateIndicator::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################## Simulation ################################# +//############################################################################# + +//############################################################################# +// Virtual Data support +// +Derivation + Simulation::ClassDerivations(Receiver::ClassDerivations,"Simulation"); + +Simulation::SharedData + Simulation::DefaultData( + Simulation::ClassDerivations, + Simulation::MessageHandlers, + Simulation::AttributeIndex, + Simulation::StateCount + ); + +//############################################################################# +// Model support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::ReadUpdateRecord(UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + + lastUpdate = Now(); // HACK - should be based upon message->timeStamp + SetSimulationState(message->simulationState); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::WriteUpdateRecord( + UpdateRecord *message, + int update_model + ) +{ + Check(this); + Check_Pointer(message); + + message->timeStamp = lastPerformance; + message->simulationState = GetSimulationState(); + message->recordLength = sizeof(*message); + message->recordID = (Word)update_model; + lastUpdate = lastPerformance; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::WriteSimulationUpdate(MemoryStream *update_stream) +{ + Check(this); + Check(update_stream); + + // + //----------------- + // Write the update + //----------------- + // + int bit=0; + int update_model = updateModel; + updateModel = 0; + while (update_model) + { + + if (update_model & 1) + { + UpdateRecord* update = (UpdateRecord*)update_stream->GetPointer(); + WriteUpdateRecord(update, bit); + update_stream->AdvancePointer(update->recordLength); + } + update_model >>= 1; + ++bit; + } + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation::Simulation( + Simulation::ClassID class_ID, + Simulation::SharedData &virtual_data +): + Receiver(class_ID, virtual_data), + simulationState(GetSharedData()->stateCount), + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL), + effectWatcherSocket(NULL) +{ + Check_Pointer(this); + + SetSimulationState(DefaultState); + lastPerformance = Now(); + lastUpdate = lastPerformance; + activePerformance = &Simulation::DoNothingOnce; + updateModel = 0; + simulationFlags = 0; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation::~Simulation() +{ + Check(this); + + // + // Watchers should be deleted by renderers by now + // + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&audioWatcherSocket); + Verify(iterator.GetSize() == 0); + } + { + SChainIteratorOf iterator(&videoWatcherSocket); + Verify(iterator.GetSize() == 0); + } + { + SChainIteratorOf iterator(&gaugeWatcherSocket); + Verify(iterator.GetSize() == 0); + } + #endif + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const Simulation::AttributePointer + Simulation::NullAttribute = NULL; + +const Simulation::IndexEntry + Simulation::AttributePointers[]= +{ + { + Simulation::SimulationStateAttributeID, + "SimulationState", + (Simulation::AttributePointer)&Simulation::simulationState + } +}; + +Simulation::AttributeIndexSet + Simulation::AttributeIndex( + ELEMENTS(Simulation::AttributePointers), + Simulation::AttributePointers + ); + +void* + Simulation::GetAttributePointer(Simulation::AttributeID attribute) +{ + Check(this); + + AttributePointer attr = + GetSharedData()->activeAttributeIndex->Find(attribute); + Check_Fpu(); + if (attr == NullAttribute) + { + return NULL; + } + else + { + return &(this->*attr); + } +} + +void* + Simulation::GetAttributePointer(const char* attribute_name) +{ + Check(this); + + AttributePointer attr = + GetSharedData()->activeAttributeIndex->Find(attribute_name); + Check_Fpu(); + if (attr == NullAttribute) + { + return NULL; + } + else + { + return &(this->*attr); + } +} + +//############################################################################# +// Simulation Support +// +void + Simulation::PerformAndWatch( + const Time& till, + MemoryStream *update_stream + ) +{ + Check(this); + Check(&till); + + Scalar slice = till - lastPerformance; + lastPerformance = till; + + Perform(slice); + if (!AreWatchersDelayed()) + { + ExecuteWatchers(); + } + WriteSimulationUpdate(update_stream); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::DoNothingOnce(Scalar) +{ + NeverExecute(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::DoNothing(Scalar) +{ + Check_Fpu(); +} + +//############################################################################# +// Watcher Support +// +void + Simulation::ExecuteWatchers() +{ + SET_EXECUTE_WATCHERS(); + + Component *watcher; + + // Audio + { + SChainIteratorOf iterator(audioWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Video + { + SChainIteratorOf iterator(videoWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Gauge + { + SChainIteratorOf iterator(gaugeWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Effect + { + SChainIteratorOf iterator(effectWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + CLEAR_EXECUTE_WATCHERS(); +} + +//############################################################################# +// Test Support +// + +Logical + Simulation::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +//############################################################################# +//################### Simulation::AttributeIndexSet ##################### +//############################################################################# + +const Simulation::AttributeIndexSet + Simulation::AttributeIndexSet::NullSet; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation__AttributeIndexSet::~Simulation__AttributeIndexSet() +{ + if (attributeIndex) + { + Unregister_Pointer(attributeIndex); + delete[] attributeIndex; + } +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::AttributeIndexSet::Build( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[], + const Simulation::AttributeIndexSet *inheritance + ) +{ + // + //------------------------------------------------------- + // Find out the highest message type we have to deal with + //------------------------------------------------------- + // + Check(this); + Check_Pointer(index_table); + entryCount = 0; + Simulation::AttributeID i; + for (i=0; i entryCount) + { + entryCount = index_table[i].entryID; + } + } + if (inheritance) + { + Check(inheritance); + if (entryCountentryCount) + { + entryCount = inheritance->entryCount; + } + #if DEBUG_LEVEL>0 + else if (entryCount > inheritance->entryCount) + { + i = inheritance->entryCount+1; + goto Check_Table; + } + #endif + } + else + { + Verify(entryCount == count); + #if DEBUG_LEVEL>0 + i = 1; +Check_Table: + while (i <= entryCount) + { + int j; + for (j=0; j count); + #endif + } + + // + //----------------------------------------------------------------------- + // Allocate the memory for the new handler set, and copy the inherited + // handlers to the new table. We are guaranteed to have enough space for + // the inherited table + //----------------------------------------------------------------------- + // + attributeIndex = new Simulation::IndexEntry[entryCount]; + Check_Pointer(attributeIndex); + Register_Pointer(attributeIndex); + i = 0; + if (inheritance) + { + for (; ientryCount; ++i) + { + attributeIndex[i] = inheritance->attributeIndex[i]; + } + } + + // + //---------------------------------------------------------------------- + // Step through the new table supplied, placing each handler in the slot + // determined by the message type + //---------------------------------------------------------------------- + // + for (i=0; i inheritance->entryCount); + attributeIndex[index_table[i].entryID-1] = index_table[i]; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation::AttributePointer + Simulation::AttributeIndexSet::Find(const char* attribute_name) const +{ + Check(this); + Check_Pointer(attribute_name); + + for (int attribute=0; attributeGetUpdateManager(); + Check(updater); + updater->RequestEncore(this, encore); +} + +#if defined(TEST_CLASS) && 0 +# include "model.tcp" +#endif + diff --git a/CODE/RP/MUNGA/SIMULATE.HPP b/CODE/RP/MUNGA/SIMULATE.HPP new file mode 100644 index 0000000..45452ed --- /dev/null +++ b/CODE/RP/MUNGA/SIMULATE.HPP @@ -0,0 +1,413 @@ +//===========================================================================// +// File: model.hpp // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification of model class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/25/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SIMULATE_HPP) +# define SIMULATE_HPP + +# if !defined(STATE_HPP) +# include +# endif + +# if !defined(RECEIVER_HPP) +# include +# endif + +# if !defined(TIME_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + + class Simulation__SharedData; + class Simulation__IndexData; + class Simulation__IndexEntry; + class Simulation__AttributeIndexSet; + class MemoryStream; + + //########################################################################## + //################# Simulation::UpdateRecord ######################### + //########################################################################## + + struct Simulation__UpdateRecord + { + public: + size_t recordLength; + Word subsystemID; + Word recordID; + Time timeStamp; + Enumeration simulationState; + }; + + //########################################################################## + //####################### Simulation ################################# + //########################################################################## + + class Simulation: + public Receiver + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + typedef Simulation__SharedData SharedData; + SharedData* + GetSharedData(); + + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + protected: + Simulation( + ClassID class_ID, + SharedData &shared_data + ); + + public: + ~Simulation(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + typedef Enumeration AttributeID; + typedef Simulation__IndexData IndexData; + typedef Simulation__IndexEntry IndexEntry; + typedef Simulation__AttributeIndexSet AttributeIndexSet; + typedef int Simulation::*AttributePointer; + + enum { + AnyAttributeID = 0, + SimulationStateAttributeID, + NextAttributeID + }; + + static const AttributePointer NullAttribute; + + void* + GetAttributePointer(AttributeID attribute); + void* + GetAttributePointer(const char* attribute_name); + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Simulation Support + // + public: + typedef void + (Simulation::*Performance)(Scalar time_slice); + typedef void + (Simulation::*Encore)(); + typedef Simulation__UpdateRecord UpdateRecord; + + void + SetPerformance(Performance performance) + {Check(this); activePerformance = performance;} + void + Perform(Scalar time_slice) + { + Check(this); + (this->*activePerformance)(time_slice); + } + + virtual void + PerformAndWatch( + const Time& till, + MemoryStream *update_stream + ); + + void + DoNothingOnce(Scalar time_slice); + void + DoNothing(Scalar time_slice); + + void + SetLastPerformance(const Time& when) + {Check(this); Check(&when); lastPerformance = when;} + void + RequestEncore(Encore encore); + + virtual void + ReadUpdateRecord(UpdateRecord *message); + virtual void + WriteUpdateRecord( + UpdateRecord *message, + int update_model + ); + void + WriteSimulationUpdate(MemoryStream *update_stream); + + enum { + DefaultUpdateModelBit=0, + NextUpdateModelBit + }; + + enum { + DefaultUpdateModelFlag = 1<= lastPerformance; + } + Logical + IsNonReplicantExecutable() + {Check(this); return (simulationFlags&DontExecuteFlag) == 0;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State support + // + public: + enum { + DefaultState = 0, + StateCount + }; + + unsigned + GetSimulationState() + {Check(this); return simulationState.GetState();} + unsigned + GetOldSimulationState() + {Check(this); return simulationState.GetOldState();} + void + SetSimulationState(unsigned new_state) + {Check(this); simulationState.SetState(new_state);} + + StateIndicator + simulationState; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Watcher Support + // + public: + void + AddAudioWatcher(Component *watcher) + {Check(&audioWatcherSocket);audioWatcherSocket.Add(watcher);} + void + AddVideoWatcher(Component *watcher) + {Check(&videoWatcherSocket);videoWatcherSocket.Add(watcher);} + void + AddGaugeWatcher(Component *watcher) + {Check(&gaugeWatcherSocket);gaugeWatcherSocket.Add(watcher);} + + void + AddEffectWatcher(Component *watcher) + {Check(&effectWatcherSocket); effectWatcherSocket.Add(watcher);} + + void + ExecuteWatchers(); + + private: + SChainOf + audioWatcherSocket; + SChainOf + videoWatcherSocket; + SChainOf + gaugeWatcherSocket; + SChainOf + effectWatcherSocket; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test Support + // + public: + Logical + TestInstance() const; + static Logical + TestClass(); + }; + + //########################################################################## + //################### Simulation::IndexEntry ######################### + //########################################################################## + + struct Simulation__IndexEntry + { + Enumeration + entryID; + const char * + entryName; + Simulation::AttributePointer + entryAddress; + }; + + #define ATTRIBUTE_ENTRY(class,name,attribute)\ + {\ + class::name##AttributeID,\ + #name,\ + (Simulation::AttributePointer) &class::attribute\ + } + + //########################################################################## + //################# Simulation::AttributeIndexSet #################### + //########################################################################## + + class Simulation__AttributeIndexSet: + public Receiver::InheritanceSet + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + Simulation__AttributeIndexSet( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[], + const Simulation::AttributeIndexSet &inheritance + ) + {Build(count, index_table, &inheritance);} + + Simulation__AttributeIndexSet( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[] + ) + {Build(count, index_table, NULL);} + + Simulation__AttributeIndexSet() + {attributeIndex = NULL; entryCount = 0;} + + ~Simulation__AttributeIndexSet(); + + protected: + void + Build( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[], + const Simulation::AttributeIndexSet *inheritance + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // AttributeIndexSet Functionality + // + protected: + Simulation::IndexEntry + *attributeIndex; + + public: + Simulation::AttributePointer + Find(Simulation::AttributeID attribute) const + { + Check(this); + Verify(attribute > 0); + if (attribute<=entryCount) + return attributeIndex[attribute-1].entryAddress; + else + return Simulation::NullAttribute; + } + Simulation::AttributePointer + Find(const char* attribute_name) const; + const Simulation::IndexEntry* + FindEntry(const char* attribute_name) const; + + static const Simulation::AttributeIndexSet + NullSet; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test Support + // + public: + static Logical + TestClass(); + }; + + //########################################################################## + //################### Simulation::SharedData ######################### + //########################################################################## + + class Simulation__SharedData: + public Receiver::SharedData + { + public: + Simulation__SharedData( + Derivation& derivation, + Receiver::MessageHandlerSet &message_handlers, + Simulation::AttributeIndexSet &attribute_index, + int state_count + ): + Receiver::SharedData(derivation, message_handlers), + activeAttributeIndex(&attribute_index), + stateCount(state_count) + {} + + Simulation::AttributeIndexSet* activeAttributeIndex; + int stateCount; + }; + + inline Simulation::SharedData* + Simulation::GetSharedData() + {return Cast_Object(SharedData*,sharedData);} + +#endif diff --git a/CODE/RP/MUNGA/SIMULATE.TCP b/CODE/RP/MUNGA/SIMULATE.TCP new file mode 100644 index 0000000..188e26d --- /dev/null +++ b/CODE/RP/MUNGA/SIMULATE.TCP @@ -0,0 +1,201 @@ +//===========================================================================// +// File: model.tst // +// Project: MUNGA Brick: Entity Manager // +// Contents: Implementation details of the entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/28/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "model.thh" + +//############################################################################# +// Shared Data Support +// +Derivation + TestEntity::ClassDerivations(Entity::ClassDerivations,"TestEntity"); + +TestEntity::SharedData + TestEntity::DefaultData( + TestEntity::ClassDerivations, + TestEntity::MessageHandlers, + TestEntity::AttributeIndex, + (Entity::MakeHandler)TestEntity::Make + ); + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + TestEntity::MessageHandlerEntries[]= +{ + { + TestEntity::TestMessageID, + (TestEntity::Handler)&TestEntity::TestMessageHandler + } +}; + +TestEntity::MessageHandlerSet + TestEntity::MessageHandlers( + ELEMENTS(TestEntity::MessageHandlerEntries), + TestEntity::MessageHandlerEntries, + Entity::MessageHandlers + ); + +void + TestEntity::TestMessageHandler(TestEntity::Message *) +{ + localOrigin = Point3D(2.0,2.0,2.0); +}; + +void + TestEntity::Tester() +{ + TestEntity::Message message( + TestEntity::TestMessageID, + sizeof(TestEntity::Message) + ); + Dispatch(&message); +} + +//############################################################################# +// Attribute Support +// +const TestEntity::IndexEntry + TestEntity::AttributePointers[]= +{ + { + TestEntity::VelocityVectorAttributeID, + (Entity::AttributePointer)&TestEntity::velocityVector + } +}; + +TestEntity::AttributeIndexSet + TestEntity::AttributeIndex( + ELEMENTS(TestEntity::AttributePointers), + TestEntity::AttributePointers, + Entity::AttributeIndex + ); + +//############################################################################# +// Model Support +// +Logical + TestEntity::Model(Scalar time_slice) +{ + Vector3D diff; + diff.Multiply(velocityVector,time_slice); + localOrigin.translation += diff; + localToWorld = localOrigin.translation; + return diff.LengthSquared() >= 0.009f; +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestEntity::TestEntity( + TestEntity::MakeMessage *creation_message, + TestEntity::SharedData &virtual_data +): + Entity(creation_message,virtual_data) +{ + SetValidFlag(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestEntity* + TestEntity::Make(TestEntity::MakeMessage *creation_message) +{ + return new TestEntity(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TestEntity::~TestEntity() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Entity::TestClass() +{ + DEBUG_STREAM << "Starting Entity test...\n"; + + // + //------------------ + // Test construction + //------------------ + // + TestEntity::MakeMessage + message1( + TestEntity::MakeMessageID, + sizeof(TestEntity::MakeMessage), + TestEntity::TrivialEntityClassID, + 0, + TestEntity::DefaultFlags, + LinearOrigin::Identity + ); + TestEntity *test_entity = TestEntity::Make(&message1); + Register_Object(test_entity); + + // + //------------------------ + // Test attribute pointers + //------------------------ + // + test_entity->localOrigin = Point3D(1.0f,1.0f,1.0f); + LinearOrigin *origin = + (LinearOrigin*)test_entity->GetAttributePointer(LocalOriginAttributeID); + Test(origin->translation == Point3D(1.0f,1.0f,1.0f)); + + test_entity->velocityVector = Vector3D(0.0f,0.0f,1.0f); + Vector3D *velocity = + (Vector3D*)test_entity-> + GetAttributePointer(TestEntity::VelocityVectorAttributeID); + Test(*velocity == Vector3D(0.0f,0.0f,1.0f)); + + // + //--------------------- + // Test Model execution + //--------------------- + // + test_entity->RunSimulation(0.1f); + Test(origin->translation == Point3D(1.0f,1.0f,1.0f)); + test_entity->SetSimulation((Model::Simulation)&TestEntity::Model); + Test(!test_entity->RunSimulation(0.05f)); + Test(origin->translation == Point3D(1.0f,1.0f,1.05f)); + + // + //------------------------------- + // Test Update message generation + //------------------------------- + // + t = test_entity->creationTime; + t += 0.1f; + UpdateMessage *update = test_entity->Execute(t); + Test(update); + Test(update->localOrigin.translation == Point3D(1.0f,1.0f,1.15f)); + Unregister_Object(update); + delete update; + + // + //----------------- + // Test destruction + //----------------- + // + Unregister_Object(test_entity); + delete test_entity; + + return True; +} + diff --git a/CODE/RP/MUNGA/SLOT.CPP b/CODE/RP/MUNGA/SLOT.CPP new file mode 100644 index 0000000..703099e --- /dev/null +++ b/CODE/RP/MUNGA/SLOT.CPP @@ -0,0 +1,192 @@ +//===========================================================================// +// File: slot.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details for the slot class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/20/94 ECH Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SLOT_HPP) + #include +#endif + +#if !defined(NODE_HPP) + #include +#endif + +MemoryBlock + SlotLink::AllocatedMemory( + sizeof(SlotLink), + SLOTLINK_MEMORYBLOCK_ALLOCATION, + SLOTLINK_MEMORYBLOCK_ALLOCATION, + "SlotLink" + ); + +// +//########################################################################### +// SlotLink +//########################################################################### +// +SlotLink::SlotLink( + Slot *slot, + Plug *plug +): + Link(slot, plug) +{ +} + +// +//########################################################################### +// ~SlotLink +//########################################################################### +// +SlotLink::~SlotLink() +{ + Slot *slot = Cast_Object(Slot*, socket); + + // + //------------------------------------------------- + // Make sure the link is not referenced by the slot + //------------------------------------------------- + // + Check(slot); + Verify(slot->slotLink == this); + slot->slotLink = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the slot at this point in + // time. + //------------------------------------------------------------- + // + if (slot->GetReleaseNode() != NULL) + { + Check(slot->GetReleaseNode()); + slot->GetReleaseNode()->ReleaseLinkHandler(slot, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SlotLink::TestInstance() const +{ + Link::TestInstance(); + return True; +} + +// +//########################################################################### +// Slot +//########################################################################### +// +Slot::Slot( + Node *node +): + Socket(node) +{ + slotLink = NULL; +} + +// +//########################################################################### +// ~Slot +//########################################################################### +// +Slot::~Slot() +{ + SetReleaseNode(NULL); + if (slotLink != NULL) + { + Unregister_Object(slotLink); + delete slotLink; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Slot::TestInstance() const +{ + Socket::TestInstance(); + + if (slotLink != NULL) + { + Check(slotLink); + } + return True; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + Slot::Remove() +{ + if (slotLink != NULL) + { + Unregister_Object(slotLink); + delete slotLink; + slotLink = NULL; + } +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Slot::AddImplementation( + Plug *plug + ) +{ + Verify(slotLink == NULL); + slotLink = new SlotLink(this, plug); + Register_Object(slotLink); +} + +// +//########################################################################### +// GetCurrentPlug +//########################################################################### +// +Plug* + Slot::GetCurrentPlug() const +{ + if (slotLink != NULL) + { + Check(slotLink); + return slotLink->GetPlug(); + } + return NULL; +} + diff --git a/CODE/RP/MUNGA/SLOT.HPP b/CODE/RP/MUNGA/SLOT.HPP new file mode 100644 index 0000000..cb78606 --- /dev/null +++ b/CODE/RP/MUNGA/SLOT.HPP @@ -0,0 +1,166 @@ +//===========================================================================// +// File: slot.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for slot class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/20/94 ECH Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(SLOT_HPP) +# define SLOT_HPP + +# if !defined(SOCKET_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + + class Slot; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SlotLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define SLOTLINK_MEMORYBLOCK_ALLOCATION (100) + + class SlotLink: + public Link + { + friend class Slot; + + public: + ~SlotLink(); + Logical + TestInstance() const; + + private: + SlotLink( + Slot *slot, + Plug *plug + ); + + private: + static MemoryBlock + AllocatedMemory; + + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Slot ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Slot : public Socket + { + friend class SlotLink; + + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructor and testing + //-------------------------------------------------------------------- + // + Slot(Node *node); + ~Slot(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Remove - Remove the link + //-------------------------------------------------------------------- + // + void + Remove(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + AddImplementation(Plug *plug); + Plug* + GetCurrentPlug() const; + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotLink + *slotLink; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SlotOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class SlotOf: + public Slot + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + SlotOf(Node *node); + ~SlotOf(); + + // + //-------------------------------------------------------------------- + // Socket methods (see Socket for full listing) + //-------------------------------------------------------------------- + // + void + Add(T plug) + {AddImplementation(Cast_Object(Plug*,plug));} + + T + GetCurrent() const + {return (T)GetCurrentPlug();} + }; + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SlotOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + SlotOf::SlotOf(Node *node): + Slot(node) + { + } + + template + SlotOf::~SlotOf() + { + } + +#endif + diff --git a/CODE/RP/MUNGA/SOCKET.CPP b/CODE/RP/MUNGA/SOCKET.CPP new file mode 100644 index 0000000..f8464e9 --- /dev/null +++ b/CODE/RP/MUNGA/SOCKET.CPP @@ -0,0 +1,280 @@ +//===========================================================================// +// File: socket.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details for Socket and its iterator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff, merged with SKTITR.CPP // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release mechanism // +// 02/16/95 ECH Removed plug commands, added node command // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SOCKET_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Socket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Socket +//############################################################################# +// +Socket::Socket(Node *node) +{ + socketsNode = node; + // Warn(socketsNode == NULL); +} + +// +//############################################################################# +// ~Socket +//############################################################################# +// +Socket::~Socket() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Socket::TestInstance() const +{ + return True; +} + +// +//############################################################################# +// AddImplementation +//############################################################################# +// +void + Socket::AddImplementation(Plug*) +{ + Fail("Socket::AddImplementation - Should never reach here"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SocketIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +SocketIterator::SocketIterator(Socket *socket) +{ + this->socket = socket; +} + +// +//############################################################################# +//############################################################################# +// +SocketIterator::~SocketIterator() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + SocketIterator::TestInstance() const +{ + return True; +} + +// +//############################################################################# +// Remove +//############################################################################# +// +void + SocketIterator::Remove() +{ + Fail("SocketIterator::Remove - Should never reach here"); +} + +// +//############################################################################# +// IsPlugMember +//############################################################################# +// +Logical + SocketIterator::IsPlugMember( + Plug *find_plug + ) +{ + Plug *plug; + + First(); + while ((plug = ReadAndNextPlug()) != NULL) + { + Check(plug); + if (plug == find_plug) + return True; + } + return False; +} + +// +//############################################################################# +// RemovePlug +//############################################################################# +// +void + SocketIterator::RemovePlug( + Plug *find_plug + ) +{ + Plug *plug; + + Check(find_plug); + First(); + while ((plug = GetCurrentPlug()) != NULL) + { + Check(plug); + if (plug == find_plug) + { + Remove(); + return; + } + Next(); + } +} + +// +//############################################################################# +// DeletePlugs +//############################################################################# +// +void + SocketIterator::DeletePlugs(Logical defeat_release_node) +{ + Plug *plug; + Node *save_release_node; + + if (defeat_release_node) + { + Check(socket); + save_release_node = socket->GetReleaseNode(); + socket->SetReleaseNode(NULL); + } + + First(); + while ((plug = ReadAndNextPlug()) != NULL) + { + Unregister_Object(plug); + delete plug; + } + #if 0 + while ((plug = GetCurrentPlug()) != NULL) + { + Unregister_Object(plug); + delete plug; + } + #endif + + if (defeat_release_node) + { + Check(socket); + socket->SetReleaseNode(save_release_node); + } +} + +// +//############################################################################# +// SendPlugCommand +//############################################################################# +// + +// Considering removal +#if 0 +int + SocketIterator::SendPlugCommand( + Plug::CommandID plugCommand, + void *info + ) +{ + int ret; + Plug *plug; + + First(); + while ((plug = GetCurrentPlug()) != NULL) + { + Check(plug); + if ( + (ret = plug->ReceivePlugCommand(plugCommand, info)) != + IteratorFunctionNullReturn + ) + return ret; + Next(); + } + return IteratorFunctionNullReturn; +} +#endif + +// +//############################################################################# +// RunIteratorFunction +//############################################################################# +// + +// Considering removal +#if 0 +int + SocketIterator::RunIteratorFunction( + IteratorFunction iteratorFunction, + void *info + ) +{ + int ret; + Plug *plug; + + Check_Pointer(iteratorFunction); + + First(); + while ((plug = GetCurrentPlug()) != NULL) + { + Check(plug); + if ( + (ret = (*iteratorFunction)(plug, info)) != + IteratorFunctionNullReturn + ) + return ret; + Next(); + } + return IteratorFunctionNullReturn; +} +#endif + +// +//############################################################################# +// InsertImplementation +//############################################################################# +// +void + SocketIterator::InsertImplementation(Plug*) +{ + // + // Should never reach here + // + Fail("SocketIterator::InsertImplementation - Should never reach here"); +} + diff --git a/CODE/RP/MUNGA/SOCKET.HPP b/CODE/RP/MUNGA/SOCKET.HPP new file mode 100644 index 0000000..8cd9175 --- /dev/null +++ b/CODE/RP/MUNGA/SOCKET.HPP @@ -0,0 +1,256 @@ +//===========================================================================// +// File: socket.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specifications for base socket and its iterator // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 ECH Initial coding. // +// 10/20/94 JMA Fixed style stuff, merged with SKTITR.HPP // +// 10/23/94 ECH Added greater deletion safety // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/03/94 ECH Fixed InsertImplementation warning // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release mechanism // +// 02/16/95 ECH Removed plug commands, added node command // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(SOCKET_HPP) +# define SOCKET_HPP + +# if !defined(PLUG_HPP) +# include +# endif + + class Node; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Socket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Socket SIGNATURED + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + // + // NOTE: All unsafe, untyped public methods are named XXXPlug or + // XXXIterator. The safe, typed public methods are named XXX and are + // declared in the template sub-classes. + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Destructor and instance testing + //-------------------------------------------------------------------- + // + virtual + ~Socket(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // AddPlug - Add a plug to this socket, untyped access + //-------------------------------------------------------------------- + // + void + AddPlug(Plug *plug) + {AddImplementation(plug);} + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Node* + GetReleaseNode() + {return socketsNode;} + void + SetReleaseNode(Node *release_node) + {socketsNode = release_node;} + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Socket(Node *node); + + // + //-------------------------------------------------------------------- + // Protected untyped implementations + //-------------------------------------------------------------------- + // + virtual void + AddImplementation(Plug *plug); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + Node + *socketsNode; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SocketIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // Considering removal + #if 0 + typedef int + (*IteratorFunction)( + Plug *plug, + void *info + ); + + const int IteratorFunctionNullReturn = 0; + #endif + + class SocketIterator: + public Iterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + // + // NOTE: All unsafe, untyped public methods are named XXXPlug. The + // safe, typed public methods are named XXX and are declared in the + // template sub-classes. + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Destructor and testing + //-------------------------------------------------------------------- + // + ~SocketIterator(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + Plug* + ReadAndNextPlug() + {return (Plug*)ReadAndNextImplementation();} + Plug* + ReadAndPreviousPlug() + {return (Plug*)ReadAndPreviousImplementation();} + Plug* + GetCurrentPlug() + {return (Plug*)GetCurrentImplementation();} + Plug* + GetNthPlug(CollectionSize index) + {return (Plug*)GetNthImplementation(index);} + + // + //-------------------------------------------------------------------- + // InsertPlug - Inserts plug at current location + //-------------------------------------------------------------------- + // + void + InsertPlug(Plug *plug) + {InsertImplementation(plug);} + + // + //-------------------------------------------------------------------- + // Remove - Removes the link at the current location, + // does not remove the plug + //-------------------------------------------------------------------- + // + virtual void + Remove(); + + // + //-------------------------------------------------------------------- + // IsPlugMember - Determines if the plug is a member of the + // sockets collection. + //-------------------------------------------------------------------- + // + Logical + IsPlugMember( + Plug *plug + ); + + // + //-------------------------------------------------------------------- + // RemovePlug - If the plug is a member of the sockets + // collection then the link to that plug will be + // removed + //-------------------------------------------------------------------- + // + void + RemovePlug( + Plug *plug + ); + + // + //-------------------------------------------------------------------- + // DeletePlugs - Unregisters and class delete for connected plugs. + //-------------------------------------------------------------------- + // + void + DeletePlugs(Logical defeat_release_node = True); + + // + //-------------------------------------------------------------------- + // SendPlugCommand - Send a command and related info to all plugs, + // returns when all plugs receive command or until + // receive method returns non-zero. If the receive + // returns non-zero, then the iterator will remain + // at that plug. + //-------------------------------------------------------------------- + // + + // Considering removal + #if 0 + int + SendPlugCommand( + Plug::CommandID plugCommand, + void *info + ); + #endif + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + SocketIterator(Socket *socket); + + + // Considering removal + #if 0 + int + RunIteratorFunction( + IteratorFunction iteratorFunction, + void *info + ); + #endif + + virtual void + InsertImplementation(Plug*); + + Socket + *socket; + }; + +#endif diff --git a/CODE/RP/MUNGA/SPHERE.CPP b/CODE/RP/MUNGA/SPHERE.CPP new file mode 100644 index 0000000..5546312 --- /dev/null +++ b/CODE/RP/MUNGA/SPHERE.CPP @@ -0,0 +1,55 @@ +//=======================================================================// +// File: sphere.cpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#include +#pragma hdrstop + +#if !defined(SPHERE_HPP) +# include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + Sphere::Contains(const Point3D &A_Point) const +{ + Vector3D + diff; + + diff.Subtract(center,A_Point); + return radius*radius >= diff.LengthSquared(); +} + +// +//########################################################################### +//########################################################################### +// +Logical + Sphere::Intersects(const Sphere &sphere) const +{ + Vector3D temp; + Scalar r; + + r = radius + sphere.radius; + temp.Subtract(center, sphere.center); + return temp.LengthSquared() <= r*r; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator<<(ostream& Stream, const Sphere &A_Sphere) +{ + Stream << "\n\tSphere Centerpoint: " << A_Sphere.center; + return Stream << "\n\tRadius: " << A_Sphere.radius; +} diff --git a/CODE/RP/MUNGA/SPHERE.HPP b/CODE/RP/MUNGA/SPHERE.HPP new file mode 100644 index 0000000..f8db86d --- /dev/null +++ b/CODE/RP/MUNGA/SPHERE.HPP @@ -0,0 +1,62 @@ +//=======================================================================// +// File: sphere.hpp // +// Project: Architecture // +// Author: J.M. Albertson // +//-----------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainments, // +// PROPRIETARY AND CONFIDENTIAL // +//=======================================================================// + +#if !defined(SPHERE_HPP) +# define SPHERE_HPP + +# if !defined(POINT3D_HPP) +# include +# endif + + class Plane; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sphere ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Sphere SIGNATURED + { + public: + Point3D + center; + Scalar + radius; + + Sphere() + {} + Sphere( + const Point3D &A_Point, + Scalar Radius + ): + center(A_Point), + radius(Radius) + {} + Sphere( + Scalar X, + Scalar Y, + Scalar Z, + Scalar Radius + ): + center(X,Y,Z), + radius(Radius) + {} + + // + // Intersection functions + // + Logical + Contains(const Point3D &point) const; + Logical + Intersects(const Sphere &sphere) const; + Logical + Intersects(const Plane &plane) const; + + friend ostream& + operator<<(ostream& Stream, const Sphere &A_Sphere); + }; + +#endif diff --git a/CODE/RP/MUNGA/SPLINE.CPP b/CODE/RP/MUNGA/SPLINE.CPP new file mode 100644 index 0000000..119a85e --- /dev/null +++ b/CODE/RP/MUNGA/SPLINE.CPP @@ -0,0 +1,117 @@ +#include +#pragma hdrstop + +#if !defined(SPLINE_HPP) +# include +#endif + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile CubicCurve *) + {return False;} +#endif + +Logical + CubicCurve::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CubicCurve::CubicCurve( + const Point3D& p1, + const Vector3D& r1, + const Point3D& p4, + const Vector3D& r4 +) +{ + Check_Pointer(this); + Check(&p1); + Check(&r1); + Check(&p4); + Check(&r4); + + // + //---------------------------------- + // Generate the hermite basis matrix + //---------------------------------- + // + basisMatrix(0,0) = 2.0f*(p1.x - p4.x) + r1.x + r4.x; + basisMatrix(0,1) = 2.0f*(p1.y - p4.y) + r1.y + r4.y; + basisMatrix(0,2) = 2.0f*(p1.z - p4.z) + r1.z + r4.z; + + basisMatrix(1,0) = 3.0f*(p4.x - p1.x) - 2.0f*r1.x - r4.x; + basisMatrix(1,1) = 3.0f*(p4.y - p1.y) - 2.0f*r1.y - r4.y; + basisMatrix(1,2) = 3.0f*(p4.z - p1.z) - 2.0f*r1.z - r4.z; + + basisMatrix(2,0) = r1.x; + basisMatrix(2,1) = r1.y; + basisMatrix(2,2) = r1.z; + + basisMatrix(3,0) = p1.x; + basisMatrix(3,1) = p1.y; + basisMatrix(3,2) = p1.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CubicCurve::CubicCurve( + const Point3D& p1, + const Point3D& p2, + const Point3D& p3, + const Point3D& p4 +) +{ + Check_Pointer(this); + Check(&p1); + Check(&p2); + Check(&p3); + Check(&p4); + + // + //--------------------------------- + // Generate the bezier basis matrix + //--------------------------------- + // + basisMatrix(0,0) = p4.x - p1.x + 3.0f*(p2.x - p3.x); + basisMatrix(0,1) = p4.y - p1.y + 3.0f*(p2.y - p3.y); + basisMatrix(0,2) = p4.z - p1.z + 3.0f*(p2.z - p3.z); + + basisMatrix(1,0) = 3.0f*(p1.x + p3.x) - 6.0f*p2.x; + basisMatrix(1,1) = 3.0f*(p1.y + p3.y) - 6.0f*p2.y; + basisMatrix(1,2) = 3.0f*(p1.z + p3.z) - 6.0f*p2.z; + + basisMatrix(2,0) = 3.0f*(p2.x - p1.x); + basisMatrix(2,1) = 3.0f*(p2.y - p1.y); + basisMatrix(2,2) = 3.0f*(p2.z - p1.z); + + basisMatrix(3,0) = p1.x; + basisMatrix(3,1) = p1.y; + basisMatrix(3,2) = p1.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CubicCurve::Evaluate( + Scalar t, + Point3D *p, + Vector3D *v + ) +{ + Check(this); + Check_Pointer(p); + Check_Pointer(v); + Verify(t >= 0.0f && t <= 1.0f); + + Point3D t_pos; + t_pos.z = t; + t_pos.y = t_pos.z * t; + t_pos.x = t_pos.y * t; + p->Multiply(t_pos, basisMatrix); + + Vector3D t_vec(3.0f*t*t, 2.0f*t, 1.0f); + v->Multiply(t_vec, basisMatrix); +} + diff --git a/CODE/RP/MUNGA/SPLINE.HPP b/CODE/RP/MUNGA/SPLINE.HPP new file mode 100644 index 0000000..e3a0def --- /dev/null +++ b/CODE/RP/MUNGA/SPLINE.HPP @@ -0,0 +1,43 @@ +#if !defined(SPLINE_HPP) +# define SPLINE_HPP + +# if !defined(AFFNMTRX_HPP) +# include +# endif + + class CubicCurve { + public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile CubicCurve *); + #endif + + CubicCurve( // Hermite form + const Point3D& p1, + const Vector3D& r1, + const Point3D& p4, + const Vector3D& r4 + ); + CubicCurve( // Bezier form + const Point3D& p1, + const Point3D& p2, + const Point3D& p3, + const Point3D& p4 + ); + + void + Evaluate( + Scalar t, + Point3D *p, + Vector3D *v + ); + + Logical + TestInstance() const; + + protected: + AffineMatrix + basisMatrix; + }; + +#endif \ No newline at end of file diff --git a/CODE/RP/MUNGA/SPOOLER.CPP b/CODE/RP/MUNGA/SPOOLER.CPP new file mode 100644 index 0000000..61a2dd7 --- /dev/null +++ b/CODE/RP/MUNGA/SPOOLER.CPP @@ -0,0 +1,297 @@ +#include +#pragma hdrstop + +#if !defined(SPOOLER_HPP) +# include +#endif + +#if !defined(FILESTRM_HPP) +# include +#endif + +//############################################################################# +//############################## SpoolFile ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile::SpoolFile( + void *stream_start, + size_t stream_size, + size_t initial_offset +): + MemoryStream(stream_start, stream_size, initial_offset) +{ + spoolState = Empty; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile::SpoolFile(SpoolFile& spool): + MemoryStream( + spool.streamStart, + spool.streamSize, + spool.GetBytesUsed() + ) +{ + spoolState = spool.spoolState; + Verify(spoolState == Playing); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile::~SpoolFile() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolFile::SaveAs(const char *file_name) +{ + FileStream output(file_name, True); + size_t length = GetBytesUsed(); + output << length; + Rewind(); + output.WriteBytes(GetPointer(), length); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolFile::Read(const char *file_name) +{ + FileStream input(file_name); + if (!input.IsFileOpened()) + { + spoolState = Empty; + return; + } + + // + //------------------------------- + // Figure out how big the file is + //------------------------------- + // + size_t spool_size = 0; + input >> spool_size; + if (spool_size > GetBytesRemaining() || !spool_size) + { + spoolState = Empty; + } + + // + //----------- + // Read it in + //----------- + // + else + { + input.ReadBytes(streamStart, spool_size); + streamSize = spool_size; + Rewind(); + spoolState = Stored; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolFile::SpoolPacket(NetworkPacket *packet) +{ + Check(this); + Check_Pointer(packet); + + // + //------------------------------------------------------------------------- + // Check to see if we are out of spool space. For now, if it happens, just + // die + //------------------------------------------------------------------------- + // + int length = + packet->messageData.messageLength + sizeof(NetworkPacketHeader); + int remaining = GetBytesRemaining(); + if (remaining < length) + { + DEBUG_STREAM << "Error: Spool file ran out of memory!\n"; + Exit(AbortExitCodeID); + } + + // + //----------------------------------------------------- + // Copy into the memory stream, and advance the pointer + //----------------------------------------------------- + // + Mem_Copy(GetPointer(), packet, length, remaining); + AdvancePointer(length); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkPacket* + SpoolFile::NextPacket() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Check to see if anything is left in the spool. If only a partial message + // remains, die from an error + //------------------------------------------------------------------------- + // + if (!GetBytesRemaining()) + { + return NULL; + } + NetworkPacket *packet = (NetworkPacket*)GetPointer(); + int length = + packet->messageData.messageLength + sizeof(NetworkPacketHeader); + if (GetBytesRemaining() < length) + { + DEBUG_STREAM << "Error: Partial packet in spool file!\n"; + Exit(AbortExitCodeID); + return NULL; + } + + // + //----------------------------------------------------- + // Copy into the memory stream, and advance the pointer + //----------------------------------------------------- + // + AdvancePointer(length); + return (NetworkPacket*)GetPointer(); +} + +//############################################################################# +//################# MissionReviewApplicationManager ##################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MissionReviewApplicationManager::MissionReviewApplicationManager( + Scalar frame_rate, + int spool_count, + size_t spool_size +): + ApplicationManager(frame_rate) +{ + // + //-------------------------------------------------------- + // Allocate the space for the spool files and buffer table + //-------------------------------------------------------- + // + spoolCount = spool_count; + spoolSize = spool_size; + spoolBuffers = new char* [spoolCount]; + Register_Pointer(spoolBuffers); + spoolFiles = new SpoolFile* [spoolCount]; + Register_Pointer(spoolFiles); + + // + //-------------------------------------------------------- + // Allocate each spool buffer, and initial the spool files to none + //-------------------------------------------------------- + // + for (int i=0; ispoolState == SpoolFile::Empty) + { + spoolFiles[i]->spoolState = SpoolFile::Spooling; + return spoolFiles[i]; + } + } + + Fail("No spool files available!"); + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile* + MissionReviewApplicationManager::GetStoredSpoolFile() +{ + for (int i=0; ispoolState == SpoolFile::Empty) + { + spoolFiles[i]->Read("last.spl"); + if (spoolFiles[i]->spoolState == SpoolFile::Stored) + { + spoolFiles[i]->spoolState = SpoolFile::Playing; + return spoolFiles[i]; + } + return NULL; + } + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + MissionReviewApplicationManager::StoreSpoolFile(SpoolFile *spool_file) +{ + for (int i=0; ispoolState == SpoolFile::Spooling); + spoolFiles[i]->spoolState = SpoolFile::Stored; + spoolFiles[i]->SaveAs("last.spl"); + spoolFiles[i]->Rewind(); + return; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + MissionReviewApplicationManager::ReleaseSpoolFile(SpoolFile *spool_file) +{ + for (int i=0; ispoolState != SpoolFile::Spooling); + spoolFiles[i]->spoolState = SpoolFile::Empty; + spoolFiles[i]->Rewind(); + return; + } + } +} + diff --git a/CODE/RP/MUNGA/SPOOLER.HPP b/CODE/RP/MUNGA/SPOOLER.HPP new file mode 100644 index 0000000..976f8c7 --- /dev/null +++ b/CODE/RP/MUNGA/SPOOLER.HPP @@ -0,0 +1,76 @@ +#if !defined(SPOOLER_HPP) +# define SPOOLER_HPP + +# if !defined(APPMGR_HPP) +# include +# endif + + //########################################################################## + //########################### SpoolFile ################################ + //########################################################################## + + class SpoolFile: + public MemoryStream + { + public: + SpoolFile( + void *stream_start, + size_t stream_size, + size_t initial_offset=0 + ); + SpoolFile(SpoolFile& spool); + ~SpoolFile(); + + enum SpoolState { + Empty, + Spooling, + Stored, + Playing + }; + SpoolState + spoolState; + + void + SaveAs(const char *name); + void + Read(const char *name); + + void + SpoolPacket(NetworkPacket *packet); + NetworkPacket* + NextPacket(); + }; + + //########################################################################## + //############## MissionReviewApplicationManager ##################### + //########################################################################## + + class MissionReviewApplicationManager: + public ApplicationManager + { + public: + MissionReviewApplicationManager( + Scalar frame_rate, + int spool_count, + size_t spool_size + ); + ~MissionReviewApplicationManager(); + + SpoolFile* + GetEmptySpoolFile(); + SpoolFile* + GetStoredSpoolFile(); + void + StoreSpoolFile(SpoolFile *spool_file); + void + ReleaseSpoolFile(SpoolFile *spool_file); + + protected: + int spoolCount; + SpoolFile **spoolFiles; + char **spoolBuffers; + size_t spoolSize; + }; + +#endif + diff --git a/CODE/RP/MUNGA/SRTSKT.CPP b/CODE/RP/MUNGA/SRTSKT.CPP new file mode 100644 index 0000000..76c0305 --- /dev/null +++ b/CODE/RP/MUNGA/SRTSKT.CPP @@ -0,0 +1,75 @@ +//===========================================================================// +// File: srtskt.cc // +// Project: MUNGA Brick: Connection Engine // +// Contents: Implementation of sorted socket class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/02/94 ECH Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(SRTSKT_HPP) + #include +#endif + +SortedSocket::SortedSocket( + Node *node, + Logical has_unique_entries +): + SafeSocket(node) +{ + hasUniqueEntries = has_unique_entries; +} + +SortedSocket::~SortedSocket() +{ +} + +void + SortedSocket::AddValueImplementation( + Plug*, + const void* + ) +{ + Fail("SortedSocket::AddValueImplementation - Should never reach here"); +} + +Plug* + SortedSocket::FindImplementation(const void*) +{ + Fail("SortedSocket::FindImplementation - Should never reach here"); + return NULL; +} + +SortedIterator::SortedIterator(SortedSocket *sortedSocket): + SafeIterator(sortedSocket) +{ +} + +SortedIterator::~SortedIterator() +{ +} + +Plug* + SortedIterator::FindImplementation(const void*) +{ + Fail("SortedIterator::FindImplementation - Should never reach here"); + return NULL; +} + +void* + SortedIterator::GetValueImplementation() +{ + Fail("SortedIterator::GetValueImplementation - Should never reach here"); + return NULL; +} + diff --git a/CODE/RP/MUNGA/SRTSKT.HPP b/CODE/RP/MUNGA/SRTSKT.HPP new file mode 100644 index 0000000..6ad2169 --- /dev/null +++ b/CODE/RP/MUNGA/SRTSKT.HPP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: srtskt.hh // +// Project: MUNGA Brick: Connection Engine // +// Contents: Interface definition for sorted socket class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/02/94 ECH Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SRTSKT_HPP) +# define SRTSKT_HPP + +# if !defined(SFESKT_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedSocket ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SortedSocket: + public SafeSocket + { + public: + ~SortedSocket(); + + void + AddValuePlug( + Plug *plug, + const void *value + ) + {AddValueImplementation(plug, value);} + + Plug* + FindPlug(const void *value) + {return FindImplementation(value);} + + protected: + SortedSocket( + Logical has_unique_entries = True + ); + SortedSocket( + Node *node, + Logical has_unique_entries = True + ); + + Logical + HasUniqueEntries() + {return hasUniqueEntries;} + + virtual void + AddValueImplementation( + Plug *plug, + const void *value + ); + + virtual Plug* + FindImplementation(const void *value); + + private: + Logical + hasUniqueEntries; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SortedIterator: + public SafeIterator + { + public: + ~SortedIterator(); + + virtual Plug* + FindImplementation(const void *value); + + virtual void* + GetValueImplementation(); + + protected: + SortedIterator(SortedSocket *sortedSocket); + }; + +#endif diff --git a/CODE/RP/MUNGA/STATE.HPP b/CODE/RP/MUNGA/STATE.HPP new file mode 100644 index 0000000..4ab7ba7 --- /dev/null +++ b/CODE/RP/MUNGA/STATE.HPP @@ -0,0 +1,108 @@ +//===========================================================================// +// File: model.hpp // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification of model class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/25/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(STATE_HPP) +# define STATE_HPP + +# if !defined(CMPNNT__HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + + //########################################################################## + //##################### StateIndicator ############################### + //########################################################################## + + class StateIndicator: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + StateIndicator(); + StateIndicator(unsigned max_states); + StateIndicator(const StateIndicator &state_indicator); + ~StateIndicator(); + + StateIndicator& + operator=(const StateIndicator&); + + Logical + operator==(const StateIndicator&) const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State stuff + // + public: + unsigned + GetState() + {Check(this); return currentState;} + unsigned + GetOldState() + {Check(this); return oldState;} + void + SetState(unsigned new_state); + + protected: + unsigned + stateCount, + oldState, + currentState; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Watcher stuff + // + public: + void + AddAudioWatcher(Component *watcher) + {Check(&audioWatcherSocket);audioWatcherSocket.Add(watcher);} + void + AddVideoWatcher(Component *watcher) + {Check(&videoWatcherSocket);videoWatcherSocket.Add(watcher);} + void + AddGaugeWatcher(Component *watcher) + {Check(&gaugeWatcherSocket);gaugeWatcherSocket.Add(watcher);} + + private: + SChainOf + audioWatcherSocket; + SChainOf + videoWatcherSocket; + SChainOf + gaugeWatcherSocket; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Stream input/output methods + // + public: + friend ostream& + operator << ( + ostream &strm, + const StateIndicator &state_indicator + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test Support + // + public: + Logical + TestInstance() const; + static Logical + TestClass(); + }; + +#endif diff --git a/CODE/RP/MUNGA/STYLE.HPP b/CODE/RP/MUNGA/STYLE.HPP new file mode 100644 index 0000000..04f009f --- /dev/null +++ b/CODE/RP/MUNGA/STYLE.HPP @@ -0,0 +1,166 @@ +//===========================================================================// +// File: style.hh // +// Project: MUNGA Brick: None assigned - coding styles, etc. // +// Contents: Base information used by all MUNGA source files // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/14/94 JMA Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(STYLE_HPP) +# define STYLE_HPP + +# if !defined(DEBUG_STREAM) +# define DEBUG_STREAM cout +# endif + +# if !defined(Verify) +# if !defined(DEBUG_LEVEL) +# define DEBUG_LEVEL 0 +# endif +# if DEBUG_LEVEL<1 +# include +# elif DEBUG_LEVEL<2 +# include +# elif DEBUG_LEVEL<3 +# include +# else +# include +# endif +# endif + +# if defined(__BCPLUSPLUS__) + extern int + _matherr(struct exception *a); +# endif + + extern int + Fpu_Ok(); + extern void + Verify_Failed(char *message, char *file, int line); + extern void + Fail_To_Debugger(char *message, char *file, int line); + extern void + Exit(int exit_code); + + class Signature + { + private: +# if DEBUG_LEVEL>0 + enum Mark + { + ok, + destroyed, + corrupted, + noMagic=(int)0xAB135795L, + magic=(int)0xFFED1231L + } mark; +# endif + + protected: + Signature(); + ~Signature(); + + public: + friend int + Is_Signature_Bad(const volatile Signature *p); + }; + +# if defined(USE_SIGNATURE) +# define SIGNATURED : public Signature +# else +# define SIGNATURED +# define Is_Signature_Bad(p) (False) +# endif + +//##########~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//# MACROS # +//########## + +# define ELEMENTS(Array) (sizeof(Array)/sizeof(*Array)) + +# if defined(TEST_CLASS) +# define Test(c)\ + if (!(c)) {\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#c" failed!\07\n";\ + return False;\ + } + +# define Test_And_Dump(c,v)\ + if (!(c)) {\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#c" failed!\07\n";\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#v" = " << (v) << '\n';\ + return False;\ + } + +# define Test_Message(m)\ + (DEBUG_STREAM << m) + +# define Test_Branch_On()\ + Fail("First visit of branch") +# define Test_Branch_Off() + +# else +# define Test(c) +# define Test_And_Dump(c,v) +# define Test_Message(m) +# endif + +# if defined(__sgi__) +# define stricmp(s1, s2) (strcasecmp(s1, s2)) +# define strnicmp(s1, s2, n) (strncasecmp(s1, s2, n)) +# endif + + //################~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //# ENUMERATIONS # + //################ + + enum { + False = 0, + True = 1 + }; + + //###########~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //# CASTING # + //########### + +# define SKIPPY_CAST(Type,var) (*((Type*)&(var))) + + //#############~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //# TEMPLATES # + //############# + +# define SMALL (1e-4f) + +# define Abs(value) ((value>0) ? value : -value) +# define Clamp(v,f,c) (v = ((vc) ? c : v))) +# define Max_Clamp(v,c) (v = ((v>c) ? c : v)) +# define Is_Many_Bits(value) (Lowbit(value)^value) +# define Low_Bit(value) (value & (-value)) +# define Min_Clamp(v,f) (v = ((vb) ? a : b) +# define Min(a,b) ((aSMALL) + + //############~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //# TYPEDEFS # + //############ + + typedef int Logical; // machine dependant zero/not-zero + typedef unsigned char Byte; // 8 bits unsigned + typedef unsigned short Word; // 16 bits unsigned + typedef unsigned long LWord; // 32 bits unsigned + + typedef int Enumeration; + +# if !defined(HEAP_HPP) +# include +# endif + +#endif + diff --git a/CODE/RP/MUNGA/SUBSYSTM.HPP b/CODE/RP/MUNGA/SUBSYSTM.HPP new file mode 100644 index 0000000..9a792da --- /dev/null +++ b/CODE/RP/MUNGA/SUBSYSTM.HPP @@ -0,0 +1,202 @@ +//===========================================================================// +// File: subsystm.hh // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification of entity subsystem class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/24/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(SUBSYSTM_HPP) +# define SUBSYSTM_HPP + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(DAMAGE_HPP) +# include +# endif + + class Entity; + class NotationFile; + + //########################################################################## + //#################### Subsystem::ModelResource ###################### + //########################################################################## + + struct Subsystem__SubsystemResource + { + char + subsystemName[32]; + RegisteredClass::ClassID + classID; + size_t + subsystemModelSize; + int + segmentIndex; + LWord + subsystemFlags; + }; + + //########################################################################## + //######################## Subsystem ################################# + //########################################################################## + + class Subsystem: + public Simulation + { + //########################################################################## + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //########################################################################## + // Construction and Destruction Support + // + public: + typedef Subsystem__SubsystemResource SubsystemResource; + + ~Subsystem(); + + static ResourceDescription::ResourceID + CreateStreamedSubsystem( + NotationFile *model_file, + const char* model_name, + const char* subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ); + + protected: + Subsystem( + Entity *entity, + int subsystem_id, + SubsystemResource *model, + SharedData &shared_data + ); + + Subsystem( + Entity *entity, + int subsystem_id, + const char *subsystem_name, + RegisteredClass::ClassID class_id, + SharedData &shared_data + ); + + //########################################################################## + // Flag Support + // + public: + enum { + DontReplicateBit = Simulation::NextBit, + NextBit + }; + enum { + DontReplicateFlag = 1<TakeDamage(damage); + } + + DamageZone *damageZone; + + virtual void + DeathReset(int /*reset_command*/) + {} + + virtual void + DeathShutdown(int /*shutdown_command*/) + {} +}; + +//########################################################################## +// Tool support +// +int + Get_Segment_Index( + NotationFile *model_file, + const char* model_name, + const ResourceDirectories *directories, + const char *desired_page + ); +#endif diff --git a/CODE/RP/MUNGA/TABLE.CPP b/CODE/RP/MUNGA/TABLE.CPP new file mode 100644 index 0000000..651a4c9 --- /dev/null +++ b/CODE/RP/MUNGA/TABLE.CPP @@ -0,0 +1,813 @@ +//===========================================================================// +// File: table.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of Table class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/30/94 ECH Initial coding. // +// 11/02/94 JMA Made compatible with SGI CC, merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(TABLE_HPP) + #include +#endif + +#if !defined(NODE_HPP) + #include +#endif + +#define VERIFY_INDEX(x) Verify(0 <= (x) && (x) < numItems) + +// +//########################################################################### +// TABLEENTRY +//########################################################################### +// + +TableEntry::TableEntry( + Table *table, + Plug *plug +): + Link(table, plug) +{ +} + +TableEntry::~TableEntry() +{ + Table *table = Cast_Object(Table*, socket); + IteratorPosition index; + + // + //-------------------------------------- + // Find the link in the table and remove + //-------------------------------------- + // + index = table->SearchForTableEntry(this); + table->RemoveNthTableEntry(index); + + // + //-------------------------------------------- + // Notify iterators that link is being deleted + //-------------------------------------------- + // + table->SendIteratorMemo(PlugRemoved, &index); + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (table->GetReleaseNode() != NULL) + { + Check(table->GetReleaseNode()); + table->GetReleaseNode()->ReleaseLinkHandler(table, plug); + } +} + +// +//########################################################################### +// TABLE +//########################################################################### +// + +// +//########################################################################### +// Table +//########################################################################### +// +Table::Table( + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + array = NULL; + numItems = 0; +} + +// +//########################################################################### +// ~Table +//########################################################################### +// +Table::~Table() +{ + SetReleaseNode(NULL); + while (numItems > 0) + { + Check_Pointer(array); + Check(array[0]); + + Unregister_Object(array[0]); + delete array[0]; + } + Verify(numItems == 0); + Verify(array == NULL); +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Table::TestInstance() const +{ + SortedSocket::TestInstance(); + + if (numItems > 0 || array != NULL) + { + Verify(numItems > 0); + Check_Pointer(array); + } + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Table::AddImplementation(Plug *plug) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + Table::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + TableEntry *link; + + /* + * Verify that value has not been added + */ + Verify(HasUniqueEntries() ? (SearchForValue(value) == TableNullIndex) : (Logical)True); + + /* + * Make new table entry + */ + link = MakeTableEntry(plug, value); + Register_Object(link); + + /* + * Add, sort and send memo to iterators to update references + */ + AddTableEntry(link); + SortTableEntries(); + SendIteratorMemo(PlugAdded, link); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + Table::FindImplementation( + const void *value + ) +{ + IteratorPosition index; + + if ((index = SearchForValue(value)) != TableNullIndex) + { + Check_Pointer(array); + VERIFY_INDEX(index); + Check(array[index]); + + return array[index]->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// MakeTableEntry +//########################################################################### +// +TableEntry* + Table::MakeTableEntry( + Plug*, + const void* + ) +{ + Fail("Table::MakeTableEntry - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// CompareTableEntries +//########################################################################### +// +int + Table::CompareTableEntries( + TableEntry*, + TableEntry* + ) +{ + Fail("Table::CompareTableEntries - Should never reach here"); + return 0; +} + +// +//########################################################################### +// CompareValueToTableEntry +//########################################################################### +// +int + Table::CompareValueToTableEntry( + const void*, + TableEntry* + ) +{ + Fail("Table::CompareValueToTableEntry - Should never reach here"); + return 0; +} + +// +//########################################################################### +// AddTableEntry +//########################################################################### +// +void + Table::AddTableEntry( + TableEntry *link + ) +{ + Check(link); + +#if 0 + numItems++; + if (array == NULL) + { + array = (TableEntry**)malloc(sizeof(TableEntry*)); + Register_Pointer(array); + } + else + { + Unregister_Pointer(array); + array = (TableEntry**)realloc(array, numItems * sizeof(TableEntry*)); + Register_Pointer(array); + } +#else + CollectionSize new_num_items = numItems+1; + if (array == NULL) + { + Verify(new_num_items == 1); + array = new TableEntry*[new_num_items]; + Register_Pointer(array); + } + else + { + TableEntry **new_array = new TableEntry*[new_num_items]; + Register_Pointer(new_array); + + Mem_Copy( + new_array, + array, + numItems * sizeof(TableEntry*), + new_num_items * sizeof(TableEntry*) + ); + Unregister_Pointer(array); + delete[] array; + array = new_array; + } + numItems = new_num_items; +#endif + Check_Pointer(array); + + array[numItems - 1] = link; +} + +// +//########################################################################### +// SortTableEntries +//########################################################################### +// +void + Table::SortTableEntries() +{ + size_t i, j; + TableEntry *temp; + + for (i = 1; i < numItems; i++) + { + Check_Pointer(array); + Verify(i < numItems); + + temp = array[i]; + j = i; + + Verify(j-1 < numItems); + + while (CompareTableEntries(array[j-1], temp) > 0) + { + Verify(j < numItems); + Verify(j-1 < numItems); + + array[j] = array[j-1]; + j--; + if (j < 1) + break; + } + + Verify(j < numItems); + array[j] = temp; + } +} + +// +//########################################################################### +// SearchForValue +//########################################################################### +// +IteratorPosition + Table::SearchForValue( + const void *value + ) +{ + size_t n = numItems; + size_t i = 0, j; + IteratorPosition k; + + while (i < n) + { + j = (i + n - 1) >> 1; + + Check_Pointer(array); + Verify(j < numItems); + + if ((k = CompareValueToTableEntry(value, array[j])) == 0) + return j; + + if (k < 0) + n = j; + else + i = j + 1; + } + return TableNullIndex; +} + +// +//########################################################################### +// SearchForTableEntry +//########################################################################### +// +IteratorPosition + Table::SearchForTableEntry( + TableEntry *link + ) +{ + CollectionSize i; + + for (i = 0; i < numItems; i++) + { + Check_Pointer(array); + VERIFY_INDEX(i); + + if (array[i] == link) + return i; + } + return TableNullIndex; +} + +// +//########################################################################### +// RemoveNthTableEntry +//########################################################################### +// +void + Table::RemoveNthTableEntry( + CollectionSize index + ) +{ + char *itemPtr, *lastItem; + size_t width; + + Check_Pointer(array); + VERIFY_INDEX(index); + + /* + * Find the location of the item + */ + itemPtr = (char*)&array[index]; + Check_Pointer(itemPtr); + + /* + * Remove the item from the array + */ + width = sizeof(void*); + lastItem = (char*)array + (numItems - 1) * width; + + if (itemPtr < lastItem) + { + memmove(itemPtr, itemPtr + width, (size_t)(lastItem - itemPtr)); + } + + /* + * Resize the array + */ +#if 0 + numItems--; + if (numItems == 0) + { + Unregister_Pointer(array); + free(array); + array = NULL; + } + else + { + Unregister_Pointer(array); + array = (TableEntry**)realloc(array, numItems * sizeof(TableEntry*)); + Register_Pointer(array); + } +#else + CollectionSize new_num_items = numItems-1; + if (new_num_items == 0) + { + Unregister_Pointer(array); + delete[] array; + array = NULL; + } + else + { + TableEntry **new_array = new TableEntry*[new_num_items]; + Register_Pointer(new_array); + + Mem_Copy( + new_array, + array, + new_num_items * sizeof(TableEntry*), + new_num_items * sizeof(TableEntry*) + ); + Unregister_Pointer(array); + delete[] array; + array = new_array; + } + numItems = new_num_items; +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableIterator inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if DEBUG_LEVEL>0 + TableEntry* + TableIterator::NthEntry( + CollectionSize index + ) + { + Check_Pointer(array); + Verify(0 <= index && index < numItems); + Check(array[index]); + + return array[index]; + } +#endif + +// +//########################################################################### +// TableIterator +//########################################################################### +// +TableIterator::TableIterator(Table *table): + SortedIterator(table) +{ + array = table->array; + numItems = table->numItems; + + if (array != NULL) + currentPosition = 0; + else + currentPosition = TableNullIndex; +} + +// +//########################################################################### +//########################################################################### +// +TableIterator::~TableIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + TableIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + if (array != NULL) + { + Check_Pointer(array); + Verify(0 < numItems); + Verify(currentPosition < numItems); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + TableIterator::First() +{ + if (array != NULL) + currentPosition = 0; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + TableIterator::Last() +{ + if (array != NULL) + currentPosition = numItems - 1; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + TableIterator::Next() +{ + IncrementPosition(); +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + TableIterator::Previous() +{ + DecrementPosition(); +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *TableIterator::ReadAndNextImplementation() +{ + if (currentPosition != TableNullIndex) + { + Plug *plug; + + plug = NthEntry(currentPosition)->GetPlug(); + IncrementPosition(); + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *TableIterator::ReadAndPreviousImplementation() +{ + if (currentPosition != TableNullIndex) + { + Plug *plug; + + plug = NthEntry(currentPosition)->GetPlug(); + DecrementPosition(); + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *TableIterator::GetCurrentImplementation() +{ + if (currentPosition != TableNullIndex) + { + return NthEntry(currentPosition)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + TableIterator::GetSize() +{ + return numItems; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *TableIterator::GetNthImplementation( + CollectionSize index + ) +{ + if (index < numItems) + { + return NthEntry(currentPosition = index)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + TableIterator::Remove() +{ + if (currentPosition != TableNullIndex) + { + Unregister_Object(NthEntry(currentPosition)); + delete NthEntry(currentPosition); + } +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug + *TableIterator::FindImplementation( + const void *value + ) +{ + IteratorPosition index; + Table *table = Cast_Object(Table*, socket); + + if ((index = table->SearchForValue(value)) != TableNullIndex) + { + if (!table->HasUniqueEntries()) + { + while ( + index-1 >= 0 && + table->CompareTableEntries(NthEntry(index-1), NthEntry(index)) == 0 + ) + { + index--; + } + } + return (NthEntry(currentPosition = index)->GetPlug()); + } + currentPosition = TableNullIndex; + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + TableIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + switch (memo) + { + case PlugAdded: + { + Table *table = Cast_Object(Table*, socket); + + Check(table); + array = table->array; + numItems = table->numItems; + + // + // If a plug is added before or at the current position then + // the current position should be incremented one forward, + // otherwise, no action is necessary + // + TableEntry *link; + IteratorPosition index; + + link = Cast_Object(TableEntry*, content); + index = table->SearchForTableEntry(link); + VERIFY_INDEX(index); + if (index <= currentPosition) + { + currentPosition++; + } + Verify(TableNullIndex <= currentPosition && currentPosition < numItems); + } + break; + + case PlugRemoved: + { + Table *table = Cast_Object(Table*, socket); + + Check(table); + array = table->array; + numItems = table->numItems; + + // + // If a plug is removed before the current position then decrement + // the current position, else if the current position is at the end + // of the table then decrement the counter + // + IteratorPosition index; + + Check_Pointer(content); + index = *(IteratorPosition*)content; + if (index < currentPosition) + { + currentPosition--; + } + else if (numItems <= currentPosition) + { + currentPosition--; + } + Verify(TableNullIndex <= currentPosition && currentPosition < numItems); + } + break; + #if 0 + { + IteratorPosition index; + + Check_Pointer(content); + index = *(IteratorPosition*)content; + + array = Cast_Object(Table*, socket)->array; + numItems = Cast_Object(Table*, socket)->numItems; + + /* + * Decrement counter, if at 0 this will automatically become + * TableNullIndex + */ + if (index < currentPosition) + { + currentPosition--; + } + else if (numItems <= currentPosition) + { + currentPosition--; + } + + Verify(TableNullIndex <= currentPosition && currentPosition < numItems); + break; + } + #endif + } +} + +#if defined(TEST_CLASS) +# include "table.tcp" +#endif diff --git a/CODE/RP/MUNGA/TABLE.HPP b/CODE/RP/MUNGA/TABLE.HPP new file mode 100644 index 0000000..091793a --- /dev/null +++ b/CODE/RP/MUNGA/TABLE.HPP @@ -0,0 +1,559 @@ +//===========================================================================// +// File: table.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification for Tables // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/30/94 ECH Initial coding. // +// 11/02/94 JMA Made compatible with SGI CC, merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(TABLE_HPP) +# define TABLE_HPP + +# if !defined(SRTSKT_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableEntry ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Table; + + class TableEntry: + public Link + { + public: + TableEntry( + Table *table, + Plug *plug + ); + ~TableEntry(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableEntryOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define TABLEENTRY_MEMORYBLOCK_ALLOCATION (100) + + template class TableEntryOf: + public TableEntry + { + public: + TableEntryOf( + Table *table, + Plug *plug, + const V &value + ); + ~TableEntryOf(); + + void* + operator new(size_t); + void + operator delete(void *where); + + V + GetValue() + {return value;} + V* + GetValuePointer() + {return &value;} + + private: + static MemoryBlock + *allocatedMemory; + static CollectionSize + allocationCount; + + V value; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableEntryOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template MemoryBlock* + TableEntryOf::allocatedMemory = NULL; + template CollectionSize + TableEntryOf::allocationCount = 0; + + template + TableEntryOf::TableEntryOf( + Table *table, + Plug *plug, + const V &value + ): + TableEntry(table, plug) + { + this->value = value; + } + + template + TableEntryOf::~TableEntryOf() + { + } + + template void* + TableEntryOf::operator new(size_t) + { + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = + new MemoryBlock( + sizeof(TableEntryOf), + TABLEENTRY_MEMORYBLOCK_ALLOCATION, + TABLEENTRY_MEMORYBLOCK_ALLOCATION, + "TableEntryOf" + ); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void + TableEntryOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Table ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const IteratorPosition TableNullIndex = -1; + + class Table: + public SortedSocket + { + friend class TableEntry; + friend class TableIterator; + + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructor and testing + //-------------------------------------------------------------------- + // + Table( + Node *node, + Logical has_unique_entries + ); + ~Table(); + + Logical + TestInstance() const; + static Logical + TestClass(); + static Logical + ProfileClass(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + AddImplementation(Plug *plug); + void + AddValueImplementation( + Plug *plug, + const void *value + ); + Plug + *FindImplementation(const void *value); + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + virtual TableEntry + *MakeTableEntry( + Plug *plug, + const void *value + ); + + virtual int + CompareTableEntries( + TableEntry *entry1, + TableEntry *entry2 + ); + + virtual int + CompareValueToTableEntry( + const void *value, + TableEntry *entry + ); + + void + AddTableEntry(TableEntry *entry); + void + SortTableEntries(); + IteratorPosition + SearchForValue(const void *value); + IteratorPosition + SearchForTableEntry(TableEntry *entry); + void + RemoveNthTableEntry(CollectionSize index); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + TableEntry **array; + CollectionSize numItems; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class TableOf: + public Table + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + TableOf( + Node *node, + Logical has_unique_entries + ); + ~TableOf(); + + // + //-------------------------------------------------------------------- + // Socket methods (see Socket for full listing) + //-------------------------------------------------------------------- + // + void + AddValue( + T plug, + const V &value + ) + {AddValueImplementation(plug, &value);} + + T + Find(const V &value) + {return (T)FindImplementation(&value);} + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + TableEntry* + MakeTableEntry( + Plug *plug, + const void *value + ) + {return new TableEntryOf(this, plug, *(V*)value);} + int + CompareTableEntries( + TableEntry *entry1, + TableEntry *entry2 + ); + int + CompareValueToTableEntry( + const void *value, + TableEntry *entry + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + TableOf::TableOf( + Node *node, + Logical has_unique_entries + ): + Table( + node, + has_unique_entries + ) + { + } + + template + TableOf::~TableOf() + { + } + + #if 0 + template int + TableOf::CompareTableEntries( + TableEntry *entry1, + TableEntry *entry2 + ) + { + V result = + (V)(Cast_Object(TableEntryOf*, entry1)->GetValue() - + Cast_Object(TableEntryOf*, entry2)->GetValue()); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } + #else + template int + TableOf::CompareTableEntries( + TableEntry *entry1, + TableEntry *entry2 + ) + { + V *ptr1 = Cast_Object(TableEntryOf*, entry1)->GetValuePointer(); + V *ptr2 = Cast_Object(TableEntryOf*, entry2)->GetValuePointer(); + + Check_Pointer(ptr1); + Check_Pointer(ptr2); + + if (*ptr1 == *ptr2) + return 0; + else + return ((*ptr1 > *ptr2) ? 1 : -1); + } + #endif + + #if 0 + template int + TableOf::CompareValueToTableEntry( + const void *value, + TableEntry *link + ) + { + Check_Pointer(value); + + V result = + (V)(*(V*)value - Cast_Object(TableEntryOf*, link)->GetValue()); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } + #else + template int + TableOf::CompareValueToTableEntry( + const void *value, + TableEntry *link + ) + { + Check_Pointer(value); + + V *ptr = Cast_Object(TableEntryOf*, link)->GetValuePointer(); + Check_Pointer(ptr); + + if (*(V*)value == *ptr) + return 0; + else + return (*(V*)value > *ptr) ? 1 : -1; + } + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class TableIterator: + public SortedIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors, Destructor and testing + //-------------------------------------------------------------------- + // + TableIterator(Table *table); + ~TableIterator(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + void + First(); + void + Last(); + void + Next(); + void + Previous(); + CollectionSize + GetSize(); + void + Remove(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void* + ReadAndNextImplementation(); + void* + ReadAndPreviousImplementation(); + void* + GetCurrentImplementation(); + void* + GetNthImplementation(CollectionSize index); + Plug* + FindImplementation(const void *value); + + TableEntry* + GetCurrentEntry() + {return NthEntry(currentPosition);} + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + ReceiveMemo( + IteratorMemo memo, + void *content + ); + + TableEntry* + NthEntry(CollectionSize index) + #if DEBUG_LEVEL>0 + ; + #else + {return array[index];} + #endif + + void + IncrementPosition() + {if (++currentPosition >= numItems) currentPosition = TableNullIndex;} + void + DecrementPosition() + {if (--currentPosition < 0) currentPosition = TableNullIndex;} + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + TableEntry **array; + CollectionSize numItems; + IteratorPosition currentPosition; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class TableIteratorOf: + public TableIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors and Destructor + //-------------------------------------------------------------------- + // + TableIteratorOf(TableOf *table); + TableIteratorOf(TableOf &table); + ~TableIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T + ReadAndNext() + {return (T)ReadAndNextImplementation();} + T + ReadAndPrevious() + {return (T)ReadAndPreviousImplementation();} + T + GetCurrent() + {return (T)GetCurrentImplementation();} + T + GetNth(CollectionSize index) + {return (T)GetNthImplementation(index);} + T + Find(const V &value) + {return (T)FindImplementation(&value);} + V + GetValue() + {return Cast_Object(TableEntryOf*, GetCurrentEntry())->GetValue();} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + TableIteratorOf::TableIteratorOf(TableOf *table): + TableIterator(table) + { + } + + template + TableIteratorOf::TableIteratorOf(TableOf &table): + TableIterator(&table) + { + } + + template + TableIteratorOf::~TableIteratorOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/TABLE.TCP b/CODE/RP/MUNGA/TABLE.TCP new file mode 100644 index 0000000..8562662 --- /dev/null +++ b/CODE/RP/MUNGA/TABLE.TCP @@ -0,0 +1,532 @@ +//===========================================================================// +// File: table.tst // +// Project: MUNGA Brick: Connection Library // +// Contents: test routines for Table class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/01/94 ECH Initial coding. // +// 11/02/94 JMA Made compatible with SGI CC, used Time class instead of // +// clock_t // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "time.hpp" + +class TableTestPlug: + public Plug +{ +public: + int value; + + TableTestPlug(int value); + ~TableTestPlug(); +}; + +class TableTestNode: + public Node +{ +public: + TableOf table1; + TableOf table2; + + TableTestNode(); + ~TableTestNode(); + + void RunProfile(); + void RunTest(); +}; + +#define RandInt(x) (rand() % x + 1) + +TableTestPlug::TableTestPlug(int value): + Plug() +{ + this->value = value; +} + +TableTestPlug::~TableTestPlug() +{ +} + +TableTestNode::TableTestNode(): + Node(), table1(this, True), table2(this, True) +{ +} + +TableTestNode::~TableTestNode() +{ +} + +// +//########################################################################### +// ProfileClass +//########################################################################### +// + +Logical + Table::ProfileClass() +{ + TableTestNode testNode; + Time startTicks = Now(); + + Test_Message("Table::ProfileClass\n"); + + testNode.RunProfile(); + + Test_Message("Table::ProfileClass elapsed = " << (Now() - startTicks) << endl); + return True; +} + +// +//########################################################################### +// TestClass +//########################################################################### +// + +Logical + Table::TestClass() +{ + DEBUG_STREAM << "Starting Table test...\n"; + + TableTestNode testNode; + + testNode.RunTest(); + return True; +} + +void + TableTestNode::RunProfile() +{ + TableTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; + Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Run timing tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + startTicks = Now(); + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new TableTestPlug(values[i]); + Register_Object( testPlug1 ); + table1.AddValue(testPlug1, values[i]); + table2.AddValue(testPlug1, values[i]); + } + Test_Message("TableTestNode::RunTest Create = " << (Now() - startTicks) << endl); + + /* + * Iterate over both sockets + */ + startTicks = Now(); + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator2.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + } + Test_Message("TableTestNode::RunTest Iterate = " << (Now() - startTicks) << endl); + + /* + * Find + */ + startTicks = Now(); + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = iterator1.Find(i); + testPlug2 = iterator2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + Verify( testPlug1 == testPlug2 ); + } + } + Test_Message("TableTestNode::RunTest Find = " << (Now() - startTicks) << endl); + + /* + * Destroy from table1, verify with table2 + */ + startTicks = Now(); + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + + Unregister_Object( testPlug1 ); + delete(testPlug1); + } + Verify( i == TEST_CLASS ); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + Test_Message("TableTestNode::RunTest Destroy = " << (Now() - startTicks) << endl); +} + +void + TableTestNode::RunTest() +{ + TableTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; +// Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Stress tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new TableTestPlug(values[i]); + Register_Object( testPlug1 ); + table1.AddValue(testPlug1, values[i]); + table2.AddValue(testPlug1, values[i]); + } + + /* + * Find + */ + { + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = table1.Find(i); + testPlug2 = table2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + Verify( testPlug1 == testPlug2 ); + } + } + + /* + * Test first and last + */ + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + iterator1.First(); + iterator2.First(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + Verify( testPlug1 == iterator1.GetNth(0) ); + Verify( testPlug1 == iterator2.GetNth(0) ); + + iterator1.Last(); + iterator2.Last(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + Verify( testPlug1 == iterator1.GetNth(TEST_CLASS - 1) ); + Verify( testPlug1 == iterator2.GetNth(TEST_CLASS - 1) ); + } + + /* + * Test next and prev + */ + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + iterator1.Next(); + iterator2.Next(); + + i++; + } + Verify( i == TEST_CLASS ); + + iterator1.Last(); + iterator2.Last(); + + i = TEST_CLASS - 1; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + iterator1.Previous(); + iterator2.Previous(); + + i--; + } + Verify( i == -1 ); + } + + /* + * Test read next and read prev + */ + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + testPlug2 = iterator2.ReadAndNext(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + i++; + } + Verify( i == TEST_CLASS ); + + iterator1.Last(); + iterator2.Last(); + + i = TEST_CLASS - 1; + while ((testPlug1 = iterator1.ReadAndPrevious()) != NULL) + { + testPlug2 = iterator2.ReadAndPrevious(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + i--; + } + Verify( i == -1 ); + } + + /* + * Test nth + */ + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = iterator1.GetNth((int)i); + testPlug2 = iterator2.GetNth((int)i); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + } + } + + /* + * Test Remove + */ + { + TableIteratorOf iterator1(&table1); + TableIteratorOf iterator2(&table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(0); + + Check( testPlug2 ); + Verify( testPlug2->value == i ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + i++; + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + + /* + * Test random deletion + */ + { + /* + * Add plugs to both sockets + */ + TableIteratorOf iterator1(table1); + TableIteratorOf iterator2(table2); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new TableTestPlug(values[i]); + Register_Object( testPlug1 ); + table1.AddValue(testPlug1, values[i]); + table2.AddValue(testPlug1, values[i]); + } + } + + { + /* + * Perform random deletion + */ + int size, index; + TableIteratorOf iterator1(table1); + TableIteratorOf iterator2(table2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while((size = iterator1.GetSize()) != 0) + { + index = RandInt(size) - 1; + testPlug1 = iterator1.GetNth(index); + Check( testPlug1 ); + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(index); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + i++; + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } +} diff --git a/CODE/RP/MUNGA/TEAM.HPP b/CODE/RP/MUNGA/TEAM.HPP new file mode 100644 index 0000000..2e8c4fd --- /dev/null +++ b/CODE/RP/MUNGA/TEAM.HPP @@ -0,0 +1,197 @@ +//===========================================================================// +// File: team.hpp // +// Project: MUNGA // +// Contents: Team Specifications // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/96 JM initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined (TEAM_HPP) +# define TEAM_HPP + +# if !defined (ENTITY_HPP) +# include "entity.hpp" +# endif + + //########################################################################## + //################# Team__MakeMessage ########################## + //########################################################################## + + class Team__MakeMessage : + public Entity::MakeMessage + { + public: + + char + teamName[64]; + + int + initialScore; + + + + Team__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + char *team_name + ) : + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ) + { + Str_Copy(teamName, team_name, sizeof(teamName)); + } + + }; + //########################################################################## + //################# Team__ScoreMessage ########################## + //########################################################################## + + class Team__ScoreMessage : + public Entity::Message + { + public: + + Scalar + scoreAward; + + Team__ScoreMessage( + Receiver::MessageID message_ID, + size_t length, + Scalar score + ): + Entity::Message(message_ID, length), + scoreAward(score) + {} + }; + //########################################################################## + //######################## CLASS Team ################################ + //########################################################################## + class Team : + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation + ClassDerivations; + + static SharedData + DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + + public: + + enum { + ScoreMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef Team__ScoreMessage ScoreMessage; + + void + ScoreMessageHandler(ScoreMessage *message); + + private: + + static const HandlerEntry MessageHandlerEntries[]; + + protected: + + static MessageHandlerSet MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + private: + + static const IndexEntry + AttributePointers[]; + + protected: + + static AttributeIndexSet + AttributeIndex; + + public: + + enum { + TeamNameAttributeID = Entity::NextAttributeID, + TeamScoreAttributeID, + NextAttributeID + }; + + char + teamName[64]; + + Scalar + teamScore; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + typedef void + (Team::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + virtual void + TeamSimulation(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction / Destruction Support + // + public: + + typedef Team__MakeMessage MakeMessage; + + Team( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + + ~Team(); + + Logical + TestInstance() const; + + static Team* + Make(MakeMessage *creation_message); + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + }; +#endif diff --git a/CODE/RP/MUNGA/TERRAIN.HPP b/CODE/RP/MUNGA/TERRAIN.HPP new file mode 100644 index 0000000..bec9a53 --- /dev/null +++ b/CODE/RP/MUNGA/TERRAIN.HPP @@ -0,0 +1,182 @@ +//===========================================================================// +// File: mover.hh // +// Project: MUNGA Brick: Model Manager // +// Contents: Interface specification for moving entity class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(TERRAIN_HPP) +# define TERRAIN_HPP + +# if !defined(ENTITY_HPP) +# include +# endif + + class BoxedSolid; + + //########################################################################## + //##################### Terrain::MakeMessage ########################## + //########################################################################## + + class Terrain__MakeMessage: + public Entity::MakeMessage + { + public: + Scalar + localScale; + + Terrain__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + Scalar scale + ): + Entity::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + EntityID::Null, + resource_ID, + instance_flags, + origin + ), + localScale(scale) + {} + }; + + //########################################################################## + //########################### Terrain ################################ + //########################################################################## + + class Terrain: + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + typedef Terrain__MakeMessage MakeMessage; + + #if 0 + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + LocalScaleAttributeID = Entity::NextAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Scalar localScale; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + static Terrain* + Make(MakeMessage *creation_message); + // + // Warning... This function requires a properly set up strtok!!!! + // + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + Terrain( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~Terrain(); + + Logical + TestInstance() const; + + protected: + BoxedSolid *collisionVolumes; + }; + + //########################################################################## + //###################### UnscalableTerrain ########################### + //########################################################################## + + class UnscalableTerrain: + public Entity + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + static UnscalableTerrain* + Make(MakeMessage *creation_message); + + // + // Warning... This function requires a properly set up strtok!!!! + // + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + UnscalableTerrain( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~UnscalableTerrain(); + + Logical + TestInstance() const; + + protected: + BoxedSolid *collisionVolumes; + }; + +#endif diff --git a/CODE/RP/MUNGA/TESTALL.CPP b/CODE/RP/MUNGA/TESTALL.CPP new file mode 100644 index 0000000..e9dd3ad --- /dev/null +++ b/CODE/RP/MUNGA/TESTALL.CPP @@ -0,0 +1,244 @@ +//===========================================================================// +// File: testall.cc // +// Contents: Program to test all the classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/20/94 ECH Initial coding. // +// 11/01/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +// +//------------------------------------------------- +// Utilities +//------------------------------------------------- +// +#include +#pragma hdrstop + +#if !defined(NAMELIST_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +// +//------------------------------------------------- +// Math +//------------------------------------------------- +// +#if !defined(RECT2D_HPP) +# include +#endif + +#if !defined(ANGLE_HPP) +# include +#endif + +#if !defined(RANDOM_HPP) +# include +#endif + +#if !defined(VECTOR4D_HPP) +# include +#endif + +#if !defined(ROTATION_HPP) +# include +#endif + +#if !defined(ORIGIN_HPP) +# include +#endif + +#if !defined(LINMTRX_HPP) +# include +#endif + +#if !defined(MATRIX_HPP) +# include +#endif + +#if !defined(UNITVEC_HPP) +# include +#endif + +#if !defined(RAY_HPP) +# include +#endif + +#if !defined(NORMAL_HPP) +# include +#endif + +// +//---------------- +// Spatial library +//---------------- +// +#if !defined(BOXSOLID_HPP) +# include +#endif + +// +//------------------ +// Connection Engine +//------------------ +// +#if !defined(VCHAIN_HPP) +# include +#endif + +#if !defined(TREE_HPP) +# include +#endif + +#if !defined(TABLE_HPP) +# include +#endif + +#if !defined(HASH_HPP) +# include +#endif + +#if !defined(TIME_HPP) +# include +#endif + +#if !defined(RECEIVER_HPP) +# include +#endif + +// #define RUN_APPLICATION + +char GlobalEggFileName[80]; + +int main() +{ + #if defined(TEST_CLASS) + // + //----------------------- + // Test NameList classes + //----------------------- + // + #if 1 + #if 1 + ObjectNameList::TestClass(); + NameList::TestClass(); + AlphaNameList::TestClass(); + NotationFile::TestClass(); + #endif + + #if 1 + ResourceFile::TestClass(); + StreamableResourceFile::TestClass(); + #endif + + // + //------------------ + // Test string class + //------------------ + // + #if 1 + CString::TestClass(); + #endif + + // + //---------------- + // Test Math brick + //---------------- + // + #if 1 + RandomGenerator::TestClass(); + Radian::TestClass(); + Degree::TestClass(); + SinCosPair::TestClass(); + Vector3D::TestClass(); + LBE3Vector3D::TestClass(); + TIVector3D::TestClass(); + Vector4D::TestClass(); + Point3D::TestClass(); + UnitVector::TestClass(); + Ray::TestClass(); + EulerAngles::TestClass(); + Quaternion::TestClass(); + Origin::TestClass(); + AffineMatrix::TestClass(); + LinearMatrix::TestClass(); + Matrix4x4::TestClass(); + Normal::TestClass(); + Rectangle2D::TestClass(); + #endif + + // + //----------------- + // Test spatializer + //----------------- + // + #if 1 + BoundingBox::TestClass(); + BoxedSolid::TestClass(); + #endif + + // + //------------------ + // Test time manager + //------------------ + // + #if 1 + Time::TestClass(); + #endif + + // + //------------------------ + // Test connection library + //------------------------ + // + #if 1 + Chain::TestClass(); + SChain::TestClass(); + VChain::TestClass(); + Tree::TestClass(); + Table::TestClass(); + Hash::TestClass(); + #endif + + // + //------------------ + // Test Memory brick + //------------------ + // + #if 1 + MemoryBlock::TestClass(); + MemoryStack::TestClass(); + #endif + + // + //---------------------------- + // Test dynamic dispatch brick + //---------------------------- + // + #if 1 + MessageTap::TestClass(); + Receiver::MessageHandlerSet::TestClass(); + Derivation::TestClass(); + Receiver::TestClass(); + #endif + #endif + + // + //-------------------------------------------- + // Stop registering, and tell us about its use + //-------------------------------------------- + // + Tell("Exiting\n"); + #endif + + return 0; +} diff --git a/CODE/RP/MUNGA/TESTCLAS.HPP b/CODE/RP/MUNGA/TESTCLAS.HPP new file mode 100644 index 0000000..a6cc689 --- /dev/null +++ b/CODE/RP/MUNGA/TESTCLAS.HPP @@ -0,0 +1,137 @@ +//===========================================================================// +// File: testclas.hh // +// Project: MUNGA Brick: Dynamic Dispatch, Event and Journalling // +// Contents: defines test classes for use by Dispatch and Events // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/03/94 JMA Initial coding. // +// 11/05/94 JMA Made compatible with GNU C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(TESTCLAS_HPP) +# define TESTCLAS_HPP) + +# if !defined(RECEIVER_HPP) +# include "receiver.hpp" +# endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Alpha ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Alpha: + public Receiver +{ +protected: + static SharedData + DefaultData; + +public: + int + x; + + enum { + message0ID = Receiver::NextMessageID, + message1ID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Alpha( + ClassID class_ID = TrivialReceiverClassID, + SharedData &vdata = DefaultData); + ~Alpha(); + + void + Method0Handler(Message*); + void + Method1Handler(Message*); + + inline void Method0() + {Message m(message0ID,sizeof(Message)); Dispatch(&m);} + inline void Method1() + {Message m(message1ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Beta ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Beta: + public Alpha +{ +protected: + static SharedData + DefaultData; + +public: + enum { + message2ID=Alpha::NextMessageID, + message3ID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Beta( + ClassID class_id = TrivialReceiverClassID, + SharedData &vdata = DefaultData + ); + ~Beta(); + + void + Method1aHandler(Message*); + void + Method2Handler(Message*); + void + Method3Handler(Message*); + + inline void Method1() + {Message m(message1ID,sizeof(Message)); Dispatch(&m);} + inline void Method2() + {Message m(message2ID,sizeof(Message)); Dispatch(&m);} + inline void Method3() + {Message m(message3ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Gamma ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Gamma: + public Beta +{ +public: + enum { + message4ID=Beta::NextMessageID, + NextMessageID + }; + + static Derivation + ClassDerivations; + + Gamma(); + ~Gamma(); + + void + Method4Handler(Message*); + + inline void Method4() + {Message m(message4ID,sizeof(Message)); Dispatch(&m);} + + static MessageHandlerSet + handlerSet; + +protected: + static SharedData + DefaultData; +}; + +#endif diff --git a/CODE/RP/MUNGA/TIME.CPP b/CODE/RP/MUNGA/TIME.CPP new file mode 100644 index 0000000..7fbddd5 --- /dev/null +++ b/CODE/RP/MUNGA/TIME.CPP @@ -0,0 +1,137 @@ +//===========================================================================// +// File: time.cc // +// Project: MUNGA Brick: Time Manager // +// Contents: Implementation details of the Time Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 10/24/94 JMA Added Lester's IBM RTC code in as SystemClock class // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(TIME_HPP) + #include +#endif + +//############################################################################# +//########################### System Clock ############################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SystemClock::TogglePause() +{ + // + //-------------------------------------------------------------------- + // If the clock is currently paused, figure out how long it was paused + // and add that to the pause delay + //-------------------------------------------------------------------- + // + if (timer.pauseStart) + { + timer.pauseTime += GetRTC() - timer.pauseStart; + timer.pauseStart = 0L; + } + + // + //-------------------------------------------------------- + // Otherwise, start pausing by marking what time it is now + //-------------------------------------------------------- + // + else + { + timer.pauseStart = GetRTC(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +volatile Time& + Now() +{ + static Time + result; + + // + //------------------------------------------------- + // If we are in pause mode, return the paused clock + //------------------------------------------------- + // + if (SystemClock::timer.pauseStart) + { + result = SystemClock::timer.pauseStart; + } + + // + //---------------------------------------------------------------- + // Otherwise, return the timer minus the amount of pause time lost + //---------------------------------------------------------------- + // + else + { + result = SystemClock::GetRTC() - SystemClock::timer.pauseTime; + } + + return result; +} + +//############################################################################# +//############################### Time ################################## +//############################################################################# + +Time + Time::Null(SystemClock::timer); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Time *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +Logical + Time::TestInstance() const volatile +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +void + Convert_From_Ascii( + const char *str, + Time *time + ) +{ + Check_Pointer(str); + Check_Signature(time); + + Scalar seconds; + + seconds = atof(str); + *time = seconds; + Check(time); +} + +#if defined(TEST_CLASS) +# include "time.tcp" +#endif + diff --git a/CODE/RP/MUNGA/TIME.HPP b/CODE/RP/MUNGA/TIME.HPP new file mode 100644 index 0000000..2c25081 --- /dev/null +++ b/CODE/RP/MUNGA/TIME.HPP @@ -0,0 +1,164 @@ +//===========================================================================// +// File: time.hh // +// Project: MUNGA Brick: Time Manager // +// Contents: Interface declarations for Time Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 10/24/94 JMA Reduced operator set to minimum // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(TIME_HPP) +# define TIME_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + + class Time; + + //########################################################################## + //######################## System Clock ############################## + //########################################################################## + + class SystemClock SIGNATURED + { + friend class Time; + + public: + friend float + Get_Frame_Percent_Used(); + friend volatile Time& + Now(); + static void + TogglePause(); + + SystemClock(); + ~SystemClock() + {Shutdown();} + static SystemClock + timer; + void + Shutdown(); + friend Scalar + GetTicksPerSecond() + {return ticksPerSecond;} + + protected: + long + pauseStart; + long + pauseTime; + static Scalar + ticksPerSecond; + + static long + GetRTC(); + }; + + //########################################################################## + //############################ Time ################################## + //########################################################################## + + class Time + { + public: + long ticks; + static Time Null; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Time *p); + #endif + + Time() + {} + Time(const volatile Time &t): + ticks(t.ticks) + {} + Time(SystemClock&): + ticks(0) + {} + + Time& + operator=(const volatile Time &t) + {Check_Pointer(this); Check(&t); ticks = t.ticks; return *this;} + Time& + operator=(long t) + {Check_Pointer(this); ticks = t; return *this;} + Time& + operator=(Scalar t) + {Check_Pointer(this); ticks = Float_To_Time(t); return *this;} + + operator Scalar() const volatile + {Check(this); return Time_To_Float(ticks);} + operator long() const volatile + {Check(this); return ticks;} + + Scalar + operator-(const volatile Time &t) const volatile + {Check(this); Check(&t); return Time_To_Float(ticks - t.ticks);} + + Time& + operator+=(const volatile Time &t) + {Check(this); Check(&t); ticks += t.ticks; return *this;} + Time& + operator+=(Scalar t) + {Check(this); ticks += Float_To_Time(t); return *this;} + Time& + operator-=(const volatile Time &t) + {Check(this); Check(&t); ticks -= t.ticks; return *this;} + Time& + operator-=(Scalar t) + {Check(this); ticks -= Float_To_Time(t); return *this;} + + Logical + operator<(const volatile Time &t) const volatile + {Check(this); Check(&t); return ticks < t.ticks;} + Logical + operator<=(const volatile Time &t) const volatile + {Check(this); Check(&t); return ticks <= t.ticks;} + Logical + operator>(const volatile Time &t) const volatile + {Check(this); Check(&t); return ticks > t.ticks;} + Logical + operator>=(const volatile Time &t) const volatile + {Check(this); Check(&t); return ticks >= t.ticks;} + + friend ostream& + operator <<( + ostream& stream, + const volatile Time& t + ) + {Check(&t); return stream << t.ticks;} + + Logical + TestInstance() const volatile; + static Logical + TestClass(); + + private: + static long + Float_To_Time(Scalar t) + {return (long)(t * SystemClock::ticksPerSecond + 0.5f);} + + static Scalar + Time_To_Float(long t) + {return (Scalar)t / SystemClock::ticksPerSecond;} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + Time *time + ); + +#endif diff --git a/CODE/RP/MUNGA/TIME.TCP b/CODE/RP/MUNGA/TIME.TCP new file mode 100644 index 0000000..6fcba5b --- /dev/null +++ b/CODE/RP/MUNGA/TIME.TCP @@ -0,0 +1,100 @@ +//===========================================================================// +// File: time.tst // +// Project: MUNGA Brick: Time Manager // +// Contents: Test stuff for time // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/24/94 JMA Initial coding. // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +Logical + Time::TestClass() +{ + DEBUG_STREAM << "Starting Time test...\n"; + + Time + a, + b, + c; + Scalar f; + long + t; + + // + //---------------- + // Test assignment + //---------------- + // + a = 1.0f; + b = 2.0f; + c = Null; + + c = a; + Test(a <= c); + Test(a >= c); + + c = 1.0f; + Test(c <= a); + Test(c >= a); + + c = b.ticks; + Test(c <= b); + Test(c >= b); + + // + //---------------------- + // Test time comparators + //---------------------- + // + Test(a < b); + Test(a <= b); + Test(b > a); + Test(b >= a); + + // + //------------- + // Test casting + //------------- + // + f = c; + Test(Close_Enough(f,2.0f)); + t = a; + Test(t == a.ticks); + + // + //-------------------- + // Test math functions + //-------------------- + // + c = a; + c += 1.0f; + Test(c.ticks == b.ticks); + c -= a; + Test(c.ticks == a.ticks); + + c = b; + c -= 1.0f; + Test(c.ticks == a.ticks); + c += a; + Test(c.ticks == b.ticks); + + // + // This test checks to see if the Scalar value is within the resolution + // of half a tick + // + f = b - a; + Test(Close_Enough(f, 1.0f, 0.5f * (1.0f / SystemClock::ticksPerSecond))); + return True; +} diff --git a/CODE/RP/MUNGA/TIMESTUB.CPP b/CODE/RP/MUNGA/TIMESTUB.CPP new file mode 100644 index 0000000..056db60 --- /dev/null +++ b/CODE/RP/MUNGA/TIMESTUB.CPP @@ -0,0 +1,56 @@ +//===========================================================================// +// File: time.cc // +// Project: MUNGA Brick: Time Manager // +// Contents: Implementation details of the Time Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/19/94 JMA Initial coding. // +// 10/24/94 JMA Added Lester's IBM RTC code in as SystemClock class // +// 10/28/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(TIME_HPP) + #include +#endif + +//############################################################################# +//########################### System Clock ############################## +//############################################################################# + +SystemClock + SystemClock::timer; +Scalar + SystemClock::ticksPerSecond = 1000.0f; + +long + SystemClock::GetRTC() +{ + static long time=0L; + return time++; +} + +SystemClock::SystemClock() +{ + pauseStart = 0L; + pauseTime = 0L; +} + +void + SystemClock::Shutdown() +{ +} + +float + Get_Frame_Percent_Used() +{ + return 0.5f; +} + diff --git a/CODE/RP/MUNGA/TOOL.CPP b/CODE/RP/MUNGA/TOOL.CPP new file mode 100644 index 0000000..435020f --- /dev/null +++ b/CODE/RP/MUNGA/TOOL.CPP @@ -0,0 +1,891 @@ +//===========================================================================// +// File: txttores.cpp // +// Project: Resource Tools // +// Author: Jerry Edsall // +// Purpose: Program to convert Notation files to MUNGA .res files. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(TOOL_HPP) +# include +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(AUDTOOLS_HPP) +# include +#endif + +#if !defined(REGISTRY_HPP) +# include +#endif + +#if !defined(BOXSOLID_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + GetId(char *string) +{ + int id; + + char *number = strstr( string, "/id:"); + if (number != NULL) + { + number += 4; + id = atoi(number); + return id; + } + else + { + return -1; + } +} + +Logical + PlatformTool::ConvertStringToModeMask( + const char */*string*/, + ModeMask */*returned_value_ptr*/ + ) +{ + Fail("PlatformTool::ConvertStringToModeMask method not overridden!"); + return False; +} + +Logical + PlatformTool::ConvertStringToTechStatus( + const char */*string*/, + int */*returned_value_ptr*/ + ) +{ + Fail("PlatformTool::ConvertStringToTechStatus method not overridden!"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + ApplicationTool::BuildResources( + int argc, + char **argv, + AudioCreateSymbols &create_symbols, + Byte minor_version + ) +{ + char temp_name[200]; + const char *Res_Name; + char *resfilename; + char ops_filename[150]; + char dirgauge[150]; + char dircollision[150]; + char dirmodel[150]; + char dirmap[150]; + char diraudio[150]; + char dirvideo[150]; + char diranim[150]; + + char short_name[100]; + char long_name[200]; + char id_name[100]; + + const char *tempdir; + + ResourceDirectories + resource_directories; + + NotationFile *ops_file = new NotationFile(); + Register_Object(ops_file); + + StreamableResourceFile file; + + if (argc < 2) + { + DEBUG_STREAM << "Usage: buildXX resource.bld [res2.bld ...]\n"; + return 1; + } + + verboseMode = False; + labOnly = False; + + // + // Write audio symbols, add static audio resources + // + create_symbols.Execute(); + platformTool->CreateStaticAudioStreamResource(&file); + + // + //------------------------------------ + // Arguments are only build files, + // so step thru them + //------------------------------------ + // + for(int arg_number = 1; arg_number < argc; ++arg_number) + { + + strcpy(temp_name,argv[arg_number]); + NotationFile *notation_file; + + WorkingDirectory = MakeWorkingDirectory(temp_name); + Register_Pointer(WorkingDirectory); + + char *filename = MakePathedFilename(WorkingDirectory, temp_name); + Register_Pointer(filename); + + notation_file = new NotationFile(filename); + Register_Object(notation_file); + + labOnly |= notation_file->IsMarkedLabOnly(); + + if (!notation_file->PageCount()) + { + DEBUG_STREAM << filename << " does not exist! " << endl; + Unregister_Object(notation_file); + delete notation_file; + Stop_Registering(); + Exit(AbortExitCodeID); + } + + if (!notation_file->PageExists("resource")) + { + DEBUG_STREAM << filename << " Not a valid resource list" << endl; + Unregister_Object(notation_file); + delete notation_file; + Stop_Registering(); + Exit(AbortExitCodeID); + } + + Unregister_Pointer(filename); + delete filename; + + // + //----------------------------------------------- + // If this is the first file check + // for required info, if not skip this + // section so required info isn't overwritten + //----------------------------------------------- + // + + if(arg_number == 1) + { + + + // + // Check verboseMode + // + + const char *verb_string; + + if(notation_file->GetEntry("resource","verbose",&verb_string)) + { + if(!stricmp(verb_string, "true")) + { + verboseMode = True; + } + } + + //--------------------------------- + // Set up directories + //-------------------------------- + + if(!notation_file->GetEntry("resource","dirmap",&tempdir)) + { + DEBUG_STREAM << "No map directory specified!!!" << endl; + Exit(AbortExitCodeID); + } + + strcpy(dirmap, tempdir); + + if(!notation_file->GetEntry("resource","dirmodel", &tempdir)) + { + DEBUG_STREAM << "No model directory specified!!!" << endl; + Exit(AbortExitCodeID); + } + + strcpy(dirmodel, tempdir); + + if(!notation_file->GetEntry("resource","dircollision", &tempdir)) + { + DEBUG_STREAM << "No collision directory specified!!!" << endl; + Exit(AbortExitCodeID); + } + + strcpy(dircollision, tempdir); + + + const char + *vp, + *version_string; + Byte version[2] = {0,0}; + + notation_file->GetEntry("resource","diraudio", &tempdir); + if (tempdir) + { + strcpy(diraudio, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'diraudio'!\n"; + Exit(AbortExitCodeID); + } + + notation_file->GetEntry("resource","dirvideo", &tempdir); + if (tempdir) + { + strcpy(dirvideo, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'dirvideo'!\n"; + Exit(AbortExitCodeID); + } + + notation_file->GetEntry("resource","diranimation", &tempdir); + if (tempdir) + { + strcpy(diranim, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'diranimation'!\n"; + Exit(AbortExitCodeID); + } + + notation_file->GetEntry("resource","dirgauge", &tempdir); + if (tempdir) + { + strcpy(dirgauge, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'gauge'!\n"; + Exit(AbortExitCodeID); + } + resource_directories.collisionDirectory = dircollision; + resource_directories.modelDirectory = dirmodel; + resource_directories.mapDirectory = dirmap; + resource_directories.audioDirectory = diraudio; + resource_directories.videoDirectory = dirvideo; + resource_directories.animationDirectory = diranim; + resource_directories.gaugeDirectory = dirgauge; + + //------------------------- + // Get version info + //------------------------- + + + if (!notation_file->GetEntry("release","version", &version_string)) + { + DEBUG_STREAM << "No version number in build!!!!" << endl; + Exit(AbortExitCodeID); + } + + version[0] = (Byte)atoi(version_string); + + vp = strchr(version_string, '.'); + + if (vp) + { + vp++; + version[1] = (Byte)atoi(vp); + } + + //------------------------- + // Get Resource Name + //------------------------- + + if(!notation_file->GetEntry("resource","name",&Res_Name)) + { + DEBUG_STREAM << "No resource file specified!!!" << endl; + Exit(AbortExitCodeID); + } + + resfilename = MakePathedFilename(WorkingDirectory, Res_Name); + Register_Pointer(resfilename); + + strcpy(ops_filename, Res_Name); + char *p = ops_filename; + + p += strlen(ops_filename); + p -= 4; + *p = '\0'; + + + + //================================ + // Set ops_file "res name" + // write maps and write models + // can use this for ops file + // format. + //================================ + + ops_file->SetEntry("resource", "res name", ops_filename); + ops_file->AppendEntry("resource", NULL, (char *)NULL); + + strcat(ops_filename, ".ops"); + + file.versionArray[1] = version[0]; + file.versionArray[2] = version[1]; + file.versionArray[3] = minor_version; + } + + // + //--------------------------- + // Now step thru each entry + // in every build file + //--------------------------- + // + + NameList *entry_list = + notation_file->MakeEntryList("resource"); + Register_Object(entry_list); + NameList::Entry *entry = entry_list->GetFirstEntry(); + + const char *entry_data; + + int pre_allocated = 0; + + while (entry != NULL) + { + + entry_data = entry->GetName(); + if (entry_data == NULL) + { + entry = entry->GetNextEntry(); + continue; + } + + entry_data = entry->GetChar(); + if (entry_data == NULL) + { + entry = entry->GetNextEntry(); + continue; + } + + strcpy(id_name, entry_data); + int id = GetId(id_name); + if ( id != -1) + { + if(arg_number > 1) + { + + Fail("Manual ResourceID's not allowed in second build files!"); + + } + + if (id > pre_allocated) + { + pre_allocated = id; + } + } + + entry = entry->GetNextEntry(); + } + + // + // pre_allocated number.... + // + file.PreAllocateIDs(pre_allocated); + + + + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + + entry_data = entry->GetName(); + + if (entry_data == NULL) + { + entry = entry->GetNextEntry(); + continue; + } + + if (!stricmp(entry_data, "LAB_ONLY")) + { + labOnly = True; + entry = entry->GetNextEntry(); + continue; + } + else if (!stricmp(entry_data, "map")) + { + + const char *q = entry->GetChar(); + strcpy(long_name, q); + + + int id = GetId(long_name); + if (id != -1) + { + + // + // Strip id number off + // + + char *p = strchr(long_name, '\t'); + if (p) + { + *p = '\0'; + } + else + { + char *p = strchr(long_name, ' '); + *p = '\0'; + } + } + + + // + // open mapname + // + + char *filename = MakePathedFilename(resource_directories.mapDirectory, long_name); + Register_Pointer(filename); + + DEBUG_STREAM << "Opening Map " << filename << endl; + + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + StripDirectory(long_name); + strcpy(short_name, long_name); + + + if (new_notation_file->PageCount()) + { + if ( + !WriteMaps( + short_name, + new_notation_file, + ops_file, + &file, + &resource_directories, + id + ) + ) + { + DEBUG_STREAM << filename << " Did not work!!!! " << endl; + + } + } + else + { + DEBUG_STREAM << filename << " Does not exist! " << endl; + } + + + Unregister_Pointer(filename); + delete filename; + Unregister_Object(new_notation_file); + delete new_notation_file; + } + else if (!stricmp(entry_data, "model")) + { + + strcpy(long_name, entry->GetChar()); + + int id = GetId(long_name); + if (id != -1) + { + + // + // Strip id number off + // + + char *p = strchr(long_name, '\t'); + if (p) + { + *p = '\0'; + } + else + { + char *p = strchr(long_name, ' '); + *p = '\0'; + } + + } + + + // + // open modelname + // + + char *filename = MakePathedFilename(resource_directories.modelDirectory, long_name); + Register_Pointer(filename); + DEBUG_STREAM << "Opening Model " << filename << endl; + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + const char *p = StripExtension(StripDirectory(long_name)); + + strcpy(short_name, p); + + + if (new_notation_file->PageCount()) + { + if ( + !WriteModels( + new_notation_file, + ops_file, + &file, + short_name, + &resource_directories, + id + ) + ) + { + + DEBUG_STREAM << "Error - Model did not work : " << filename << endl; + + } + } + else + { + DEBUG_STREAM << filename << " does not exist " << endl; + + } + + + Unregister_Pointer(filename); + delete filename; + + Unregister_Object(new_notation_file); + delete new_notation_file; + + } + else if (!stricmp(entry_data, "zone")) + { + char *q = entry->GetChar(); + strcpy(long_name, q); + + // + // open zone + // + + char *filename = MakePathedFilename(resource_directories.mapDirectory, long_name); + Register_Pointer(filename); + + DEBUG_STREAM << "Opening Zones " << filename << endl; + + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + if (new_notation_file->PageCount()) + { + + InterestLatticeManager::CreateZoneResources + ( + &file, + new_notation_file + ); + } + else + { + DEBUG_STREAM << filename << " Does not exist! " << endl; + } + + + Unregister_Pointer(filename); + delete filename; + Unregister_Object(new_notation_file); + delete new_notation_file; + + } + else if (!stricmp(entry_data, "static")) + { + // + // Add registry static objects + // + Check(entry); + const char *static_object_file_name = entry->GetChar(); + Check_Pointer(static_object_file_name); + + char *full_path_file_name = + MakePathedFilename( + resource_directories.modelDirectory, + static_object_file_name + ); + Register_Pointer(full_path_file_name); + + NotationFile + static_object_notation_file(full_path_file_name); + + Registry::CreateStaticObjectStreamResource( + &static_object_notation_file, + &file + ); + + Unregister_Pointer(full_path_file_name); + delete full_path_file_name; + } + + entry = entry->GetNextEntry(); + } + + Unregister_Object(entry_list); + delete entry_list; + + // + //------------------------------------------------------- + // Make this resource Lab only if labOnly was specified + //------------------------------------------------------- + // + + if (labOnly == True) + { + file.labOnly = 1; + } + + + Unregister_Pointer(WorkingDirectory); + Unregister_Object(notation_file); + + delete WorkingDirectory; + delete notation_file; + + } + + WriteOpsFile(ops_file, &file, &resource_directories); + + file.SaveAs(resfilename); + ops_file->WriteFile(ops_filename); + + + Unregister_Pointer(resfilename); + delete resfilename; + + //------------------------ + // open the vehicle.tbl + // and write to ops and + //------------------------ + + + Unregister_Object(ops_file); + delete ops_file; + + return 0; +} + +//############################################################################# + +void + ApplicationTool::ListResource( + ResourceDescription *resource + ) +{ + Check(resource); + switch (resource->resourceType) + { + case ResourceDescription::ModelListResourceType: + DEBUG_STREAM << resource->resourceName << ": Model List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::MapListResourceType: + DEBUG_STREAM << resource->resourceName << ": Map List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::AudioStreamListResourceType: + DEBUG_STREAM << resource->resourceName << ": Audio stream List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::VideoListResourceType: + DEBUG_STREAM << resource->resourceName << ": Video List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::SubsystemListResourceType: + DEBUG_STREAM << resource->resourceName << ": Subsystem List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::ControlMappingsListResourceType: + DEBUG_STREAM << resource->resourceName << ": ControlsMappings List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::DamageZoneListResourceType: + DEBUG_STREAM << resource->resourceName << ": DamageZone List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::SkeletonListResourceType: + DEBUG_STREAM << resource->resourceName << ": Skeleton List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::BoxedSolidStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Boxed Solid Stream of " + << resource->resourceSize/sizeof(BoxedSolidResource) + << " solids"; + break; + + case ResourceDescription::VideoModelResourceType: + DEBUG_STREAM << resource->resourceName << ": VideoModel"; + break; + + case ResourceDescription::StaticAudioStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": StaticAudioStream"; + break; + + case ResourceDescription::InternalAudioStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": InternalAudioStream"; + break; + + case ResourceDescription::ExternalAudioStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": ExternalAudioStream"; + break; + + case ResourceDescription::MakeMessageStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Map stream of " + << *(int*)resource->resourceAddress << " instances"; + break; + + case ResourceDescription::GameModelResourceType: + DEBUG_STREAM << resource->resourceName << ": GameModel"; + break; + + case ResourceDescription::AnimationResourceType: + DEBUG_STREAM << resource->resourceName << ": Animation"; + break; + + case ResourceDescription::SubsystemModelStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " Subsystems"; + break; + + case ResourceDescription::GaugeImageStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": GaugeImage"; + break; + + case ResourceDescription::ControlMappingStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " ControlsMappings"; + break; + + case ResourceDescription::DamageZoneStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " DamageZones"; + break; + + case ResourceDescription::SkeletonStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " Segments"; + break; + + case ResourceDescription::EnvironmentZoneResourceType: + DEBUG_STREAM << resource->resourceName << ": EnvironmentZone"; + break; + + case ResourceDescription::InterestZoneResourceType: + DEBUG_STREAM << resource->resourceName << ": InterestZone"; + break; + + case ResourceDescription::VehicleTableResourceType: + DEBUG_STREAM << resource->resourceName << ": VehicleTable"; + break; + + case ResourceDescription::ExistanceBoxStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << resource->resourceSize/sizeof(ExtentBox) + << " Existance boxes"; + break; + + case ResourceDescription::CameraStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " Cameras"; + break; + + case ResourceDescription::DamageLookupTableStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": DamageZoneLookupTable"; + break; + + case ResourceDescription::ExplosionTableStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": ExplosionTable"; + break; + + default: + DEBUG_STREAM << "Unknown type " << resource->resourceType; + break; + } +} + +//############################################################################# + +int + ApplicationTool::ListResources( + int argc, + char **argv + ) +{ + if (argc < 2) + { + DEBUG_STREAM << "Usage: listXX resource.res [res2.res ...]\n"; + return 1; + } + + for (int i=1; i < argc; ++i) + { + char res_name[200]; + strcpy(res_name, argv[i]); + + StreamableResourceFile + file; + + file.Open(res_name); + + DEBUG_STREAM << res_name << ": v" << (int)file.versionArray[0] << '.' + << (int)file.versionArray[1] << '.' << (int)file.versionArray[2] << '.' + << (int)file.versionArray[3] << endl; + + if (file.labOnly == 1) + { + DEBUG_STREAM << "LAB ONLY RESOURCE!" << endl; + } + + DEBUG_STREAM << endl; + DEBUG_STREAM << "ID# Size Data\n"; + DEBUG_STREAM << "---- ------ -----------------------------------------------------\n"; + + for (int j=0; j<=file.GetMaxResourceID(); ++j) + { + DEBUG_STREAM << setw(4) << j << " "; + ResourceDescription *resource = file.FindResourceDescription(j); + if (resource) + { + DEBUG_STREAM << setw(6) << resource->resourceSize << " "; + resource->Lock(); + ListResource(resource); + resource->Unlock(); + } + else + { + DEBUG_STREAM << " Not Used"; + } + DEBUG_STREAM << endl; + } + } + return 0; +} + diff --git a/CODE/RP/MUNGA/TOOL.HPP b/CODE/RP/MUNGA/TOOL.HPP new file mode 100644 index 0000000..4f65d60 --- /dev/null +++ b/CODE/RP/MUNGA/TOOL.HPP @@ -0,0 +1,257 @@ +//===========================================================================// +// File: txttores.hpp // +// Project: Art Tools // +// Author: Jerry Edsall // +// Purpose: Program to convert Notation files to MUNGA .res files. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(TOOL_HPP) +# define TOOL_HPP + +# if !defined(NOTATION_HPP) +# include +# endif + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(CONTROLS_HPP) +# include +# endif + +# if !defined(GAUGALRM_HPP) +# include +# endif + +# if !defined(AUDTOOLS_HPP) +# include +# endif + +# if !defined(ENTITY_HPP) +# include +# endif + + struct + ModelData + { + char pageName[100]; + char modelName[100]; + ResourceDescription::ResourceID videoResourceID; + ResourceDescription::ResourceID skeletonResourceID; + ResourceDescription::ResourceID audioResourceID; + ResourceDescription::ResourceID collisionID; + ResourceDescription::ResourceID gameResourceID; + ResourceDescription::ResourceID subsystemResourceID; + ResourceDescription::ResourceID controlsMappingsResourceID; + ResourceDescription::ResourceID damageZoneResourceID; + ResourceDescription::ResourceID gaugeImageResourceID; + ResourceDescription::ResourceID gaugeAlarmResourceID; + ResourceDescription::ResourceID gaugeMissionReviewResourceID; + ResourceDescription::ResourceID explosionTableResourceID; + RegisteredClass::ClassID classID; + + ResourceDescription::ResourceID resourceID; + }; + + struct + InstanceData + { + char pageName[100]; + char modelName[100]; + + ResourceDescription::ResourceID resourceID; + }; + + struct + InstanceResource + { + Origin origin; + ResourceDescription::ResourceID resourceID; + }; + + //########################################################################## + //######################### PlatformTool ############################# + //########################################################################## + + class PlatformTool + { + public: + PlatformTool() + { + gaugeAlarmManager = NULL; + } + + + virtual ResourceDescription::ResourceID + CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateModelGaugeImageStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateModelGaugeMissionReviewStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateStaticAudioStreamResource( + ResourceFile *resource_file + )=0; + + typedef Logical + (*FindNameFunction)( + const char *control_name, + ControlsMapping *mapping + ); + virtual FindNameFunction + GetControlMappingFunction()=0; + + virtual Logical + ConvertStringToModeMask( + const char *string, + ModeMask *returned_value_ptr + ); + virtual Logical + ConvertStringToTechStatus( + const char *string, + int *returned_value_ptr + ); + + GaugeAlarmManager + *gaugeAlarmManager; // should be set at the topmost level + }; + + //########################################################################## + //######################## ApplicationTool ########################### + //########################################################################## + + class ApplicationTool + { + protected: + PlatformTool* + platformTool; + + virtual Logical + CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + virtual void + CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + virtual ResourceDescription::ResourceID + CreateControlMappingStream( + const char *model_class, + const char *mapping_name, + NotationFile *mapping_file, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + )=0; + + virtual void + ListResource(ResourceDescription *resource); + + Logical + WriteMaps( + char *map_name, + NotationFile *notation_file, + NotationFile *ops_file, + StreamableResourceFile *file, + const ResourceDirectories *resource_directories, + int resource_id = -1 + ); + + Logical + WriteModels( + NotationFile *notation_file, + NotationFile *ops_file, + StreamableResourceFile *file, + const char *model_name, + const ResourceDirectories *resource_directories, + int resource_id = -1 + ); + + void + WriteOpsFile( + NotationFile *ops_file, + StreamableResourceFile *file, + const ResourceDirectories *resource_directories + ); + + Logical + WriteAnimationCycle( + NotationFile *animation_file, + StreamableResourceFile *file, + const char *animation_name + ); + + Logical + WriteAnimationTransition( + NotationFile *animation_file, + StreamableResourceFile *file, + const char *animation_name + ); + + public: + Logical + labOnly, + verboseMode; + + ApplicationTool(PlatformTool *platform) + {platformTool = platform;} + + int + BuildResources( + int argc, + char **argv, + AudioCreateSymbols &create_symbols, + Byte minor_version + ); + int + ListResources( + int argc, + char **argv + ); + }; + +#endif + diff --git a/CODE/RP/MUNGA/TRACE.CPP b/CODE/RP/MUNGA/TRACE.CPP new file mode 100644 index 0000000..8017635 --- /dev/null +++ b/CODE/RP/MUNGA/TRACE.CPP @@ -0,0 +1,584 @@ +//===========================================================================// +// File: analysis.cpp // +// Project: MUNGA Brick: none // +// Contents: Utilities for using logic analyzer with parallel port dongle // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/19/94 WGR Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(TRACE_HPP) + #include +#endif + +#if !defined(FILESTRM_HPP) + #include +#endif + +#if defined(TRACE_ON) + + //########################################################################## + //############################ Trace ################################# + //########################################################################## + + Byte + Trace::NextTraceID = 0; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Trace::Trace( + const char* name, + Type type + ) + { + traceNumber = NextTraceID++; + traceType = (Byte)type; + traceName = name; + + lastFrameActivity = 0; + lastFractionActivity = 0.0f; + + trace_manager.Add(this); + } + + #if defined(USE_TIME_ANALYSIS) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + Trace::PrintUsage(Scalar usage) + { + Check(this); + + DEBUG_STREAM << usage; + } + #endif + + //########################################################################## + //########################### BitTrace ############################### + //########################################################################## + + Byte + BitTrace::NextActiveLine = 0; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + BitTrace::BitTrace(const char* name): + Trace(name, BitType) + { + activeLine = NextActiveLine++; + #if defined(USE_ACTIVE_PROFILE) + DEBUG_STREAM << name << " used trace line " << (int)activeLine + << "!\n"; + if (!IsLineValidImplementation(activeLine)) + { + Fail("Invalid active trace line!"); + } + #endif + + BitTrace::ResetTrace(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::DumpTraceStatus() + { + Check(this); + DEBUG_STREAM << (int)activeLine << ((traceUp) ? " is On" : " is Off"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::ResetTrace() + { + #if defined(USE_TIME_ANALYSIS) + traceUp = False; + lastUpTime = 0.0; + totalUpTime = 0.0; + #endif + + #if defined(USE_ACTIVE_PROFILE) + ClearLineImplementation(activeLine); + #endif + } + + #if defined(USE_TIME_ANALYSIS) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::StartTiming() + { + Check(this); + totalUpTime = 0.0; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Scalar + BitTrace::CalculateUsage( + long frame, + Scalar fraction, + double sample_time + ) + { + if (traceUp) + { + totalUpTime += frame - lastFrameActivity; + totalUpTime += fraction - lastFractionActivity; + } + Scalar result = totalUpTime / sample_time; + Check_Fpu(); + DEBUG_STREAM << setprecision(4) << totalUpTime / GetTicksPerSecond() + << "s, "; + return result; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::PrintUsage(Scalar usage) + { + Check(this); + + DEBUG_STREAM << setprecision(4) << (usage*100.0f) << "% CPU"; + #if defined(USE_ACTIVE_PROFILE) + DEBUG_STREAM << " (active on line " << (int)activeLine << ')'; + #endif + } + + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::Set() + { + Check(this); + + if (!traceUp) + { + #if defined(USE_ACTIVE_PROFILE) + SetLineImplementation(activeLine); + #endif + + traceUp = True; + + #if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG) + long frame = Now().ticks; + Scalar fraction = Get_Frame_Percent_Used(); + #endif + + #if defined(USE_TIME_ANALYSIS) + lastFrameActivity = frame; + lastFractionActivity = fraction; + #endif + + #if defined(USE_TRACE_LOG) + // Check(traceManager); + IncrementSampleCount(); + MemoryStream *log = GetTraceLog(); + if (log) + { + Check(log); + TraceSample *sample = (TraceSample*)log->GetPointer(); + sample->sampleType = TraceSample::GoingUp; + sample->traceNumber = traceNumber; + sample->sampleFrame = (Word)frame; + sample->sampleFraction = fraction; + log->AdvancePointer(sizeof(*sample)); + } + #endif + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::Clear() + { + Check(this); + + if (traceUp) + { + traceUp = False; + + #if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG) + long frame = Now().ticks; + Scalar fraction = Get_Frame_Percent_Used(); + #endif + + #if defined(USE_TIME_ANALYSIS) + if (frame == lastFrameActivity && fraction < lastFractionActivity) + { + ++frame; + } + lastUpTime = frame - lastFrameActivity; + lastUpTime += fraction - lastFractionActivity; + Verify(lastUpTime >= 0.0f) + totalUpTime += lastUpTime; + Check_Fpu(); + #endif + + #if defined(USE_TRACE_LOG) + //Check(traceManager); + IncrementSampleCount(); + MemoryStream *log = GetTraceLog(); + if (log) + { + Check(log); + TraceSample *sample = (TraceSample*)log->GetPointer(); + sample->sampleType = TraceSample::GoingDown; + sample->traceNumber = traceNumber; + sample->sampleFrame = (Word)frame; + sample->sampleFraction = fraction; + log->AdvancePointer(sizeof(*sample)); + } + #endif + + #if defined(USE_ACTIVE_PROFILE) + ClearLineImplementation(activeLine); + #endif + } + } + + //########################################################################## + //######################## TraceManager ############################## + //########################################################################## + + TraceManager + trace_manager; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + TraceManager::TraceManager(): + traceChain(NULL) + { + sampleStartFrame = 0; + sampleStartFraction = 0.0f; + actualSampleCount = 0; + ignoredSampleCount = 0; + traceCount = 0; + activeTraceLog = NULL; + allocatedTraceLog = NULL; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + TraceManager::~TraceManager() + { + Check(this); + + if (allocatedTraceLog) + { + Check(allocatedTraceLog); + allocatedTraceLog->Rewind(); + TraceSample *samples = (TraceSample*)allocatedTraceLog->GetPointer(); + Unregister_Object(allocatedTraceLog); + delete allocatedTraceLog; + activeTraceLog = allocatedTraceLog = NULL; + + Unregister_Pointer(samples); + delete[] samples; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Logical + TraceManager::TestInstance() const + { + return True; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::Add(Trace *trace) + { + Check(this); + + traceCount = (Byte)(traceCount + 1); + traceChain.Add(trace); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::DumpTracesStatus() + { + ChainIteratorOf traces(traceChain); + Trace *trace; + + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + DEBUG_STREAM << trace->traceName << ": "; + trace->DumpTraceStatus(); + DEBUG_STREAM << endl; + } + DEBUG_STREAM << endl; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::ResetTraces() + { + ChainIteratorOf traces(traceChain); + Trace *trace; + + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + trace->ResetTrace(); + } + + #if defined(USE_TRACE_LOG) + actualSampleCount = 0; + ignoredSampleCount = 0; + if (allocatedTraceLog) + { + allocatedTraceLog->Rewind(); + } + #endif + } + + #if defined(USE_TIME_ANALYSIS) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::StartTimingAnalysis() + { + sampleStartFrame = Now().ticks; + sampleStartFraction = Get_Frame_Percent_Used(); + + ChainIteratorOf traces(traceChain); + Trace *trace; + + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + trace->StartTiming(); + trace->lastFrameActivity = sampleStartFrame; + trace->lastFractionActivity = sampleStartFraction; + } + + #if defined(USE_TRACE_LOG) + actualSampleCount = 0; + ignoredSampleCount = 0; + if (allocatedTraceLog) + { + allocatedTraceLog->Rewind(); + } + #endif + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int + TraceManager::SnapshotTimingAnalysis(Logical print) + { + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + double time = now - sampleStartFrame; + time += fraction - sampleStartFraction; + if (time < SMALL) + { + return False; + } + + ChainIteratorOf traces(traceChain); + Trace *trace; + + DEBUG_STREAM << "Sample length: " << setprecision(4) + << time/GetTicksPerSecond() << "s\n"; + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + + if (print) + { + DEBUG_STREAM << trace->traceName << ": "; + Scalar usage = trace->CalculateUsage(now, fraction, time); + trace->PrintUsage(usage); + DEBUG_STREAM << endl; + } + + trace->StartTiming(); + trace->lastFrameActivity = now; + trace->lastFractionActivity = fraction; + } + + sampleStartFrame = now; + sampleStartFraction = fraction; + return True; + } + #endif + + #if defined(USE_TRACE_LOG) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::CreateTraceLog( + size_t max_trace_count, + Logical start_logging + ) + { + Check(this); + Verify(!allocatedTraceLog); + TraceSample *samples = new TraceSample[max_trace_count]; + Register_Pointer(samples); + allocatedTraceLog = + new MemoryStream(samples, max_trace_count*sizeof(TraceSample)); + Register_Object(allocatedTraceLog); + if (start_logging) + { + activeTraceLog = allocatedTraceLog; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::SaveTraceLog(const char* filename) + { + Check(this); + if (allocatedTraceLog) + { + Check(allocatedTraceLog); + + // + //-------------------------------------------------------- + // Rewind the memory stream and save it out in a disk file + //-------------------------------------------------------- + // + FileStream output(filename, True); + size_t size = allocatedTraceLog->GetBytesUsed(); + DEBUG_STREAM << ignoredSampleCount << " samples were ignored\n"; + if (size > 0) + { + DEBUG_STREAM << "Writing " << actualSampleCount + << " samples to trace log..."; + Byte trace_count = GetTraceCount(); + output << trace_count; + + ChainIteratorOf traces(traceChain); + Trace *trace; + while ((trace = traces.ReadAndNext()) != NULL) + { + output << trace->traceType; + const char* p = trace->traceName; + do + { + output << *p; + } while (*p++); + } + + output << size; + allocatedTraceLog->Rewind(); + output.WriteBytes(allocatedTraceLog->GetPointer(), size); + DEBUG_STREAM << "trace log written\n"; + } + + // + //------------------- + // Release the memory + //------------------- + // + TraceSample *samples = (TraceSample*)allocatedTraceLog->GetPointer(); + Unregister_Object(allocatedTraceLog); + delete allocatedTraceLog; + activeTraceLog = allocatedTraceLog = NULL; + + Unregister_Pointer(samples); + delete[] samples; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::MarkTraceLog() + { + Check(this); + + if (activeTraceLog) + { + Check(activeTraceLog); + + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + TraceSample *sample = (TraceSample*)activeTraceLog->GetPointer(); + sample->sampleType = TraceSample::Marker; + sample->sampleFrame = (Word)now; + sample->sampleFraction = fraction; + sample->traceNumber = 0; + activeTraceLog->AdvancePointer(sizeof(*sample)); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::SuspendTraceLogging() + { + Check(this); + + if (activeTraceLog) + { + Check(activeTraceLog); + + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + TraceSample *sample = (TraceSample*)activeTraceLog->GetPointer(); + sample->sampleType = TraceSample::SuspendSampling; + sample->sampleFrame = (Word)now; + sample->sampleFraction = fraction; + sample->traceNumber = 0; + activeTraceLog->AdvancePointer(sizeof(*sample)); + activeTraceLog = NULL; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::ResumeTraceLogging() + { + Check(this); + + if (allocatedTraceLog && !activeTraceLog) + { + Check(allocatedTraceLog); + activeTraceLog = allocatedTraceLog; + + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + TraceSample *sample = (TraceSample*)activeTraceLog->GetPointer(); + sample->sampleType = TraceSample::ResumeSampling; + sample->sampleFrame = (Word)now; + sample->sampleFraction = fraction; + sample->traceNumber = 0; + activeTraceLog->AdvancePointer(sizeof(*sample)); + } + } + + #endif + +#endif + diff --git a/CODE/RP/MUNGA/TRACE.HPP b/CODE/RP/MUNGA/TRACE.HPP new file mode 100644 index 0000000..e164c3f --- /dev/null +++ b/CODE/RP/MUNGA/TRACE.HPP @@ -0,0 +1,420 @@ +#if !defined(TRACE_HPP) +# define TRACE_HPP + +# if !defined(PLUG_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(TIME_HPP) +# include +# endif + +# if !defined(CONFIG_HPP) +# include +# endif + +# if defined(TRACE_ON) + + //####################################################################### + //################### TraceSample ################################# + //####################################################################### + + struct TraceSample + { + Scalar + sampleFraction; + Word + sampleFrame; + Byte + traceNumber, + sampleType; + + enum Type { + GoingUp = 0, + GoingDown, + Marker, + IntegerSnapshot, + ScalarSnapshot, + SuspendSampling, + ResumeSampling + }; + }; + + template struct SnapshotOf: + public TraceSample + { + T snapShot; + }; + + //####################################################################### + //######################### Trace ################################# + //####################################################################### + + class Trace: + public Plug + { + friend class TraceManager; + + public: + enum Type { + BitType, + IntegerType, + ScalarType + }; + + protected: + static Byte NextTraceID; + + const char + *traceName; + long + lastFrameActivity; + Scalar + lastFractionActivity; + Byte + traceNumber, + traceType; + + Trace( + const char* name, + Type type + ); + + MemoryStream* + GetTraceLog(); + void + IncrementSampleCount(); + + virtual void + DumpTraceStatus()=0; + virtual void + ResetTrace()=0; + + #if defined(USE_TIME_ANALYSIS) + virtual void + StartTiming()=0; + virtual Scalar + CalculateUsage( + long frame, + Scalar fraction, + double sample_time + )=0; + virtual void + PrintUsage(Scalar usage); + #endif + }; + + //####################################################################### + //######################## BitTrace ############################### + //####################################################################### + + class BitTrace: + public Trace + { + protected: + static Byte + NextActiveLine; + + Logical + traceUp; + double + lastUpTime, + totalUpTime; + Byte + activeLine; + + #if defined(USE_ACTIVE_PROFILE) + static void + SetLineImplementation(Byte line); + static void + ClearLineImplementation(Byte line); + static Logical + IsLineValidImplementation(Byte line); + #endif + + void + DumpTraceStatus(); + void + ResetTrace(); + #if defined(USE_TIME_ANALYSIS) + void + StartTiming(); + Scalar + CalculateUsage( + long frame, + Scalar fraction, + double sample_time + ); + void + PrintUsage(Scalar usage); + #endif + + public: + BitTrace(const char* name); + + void + Set(); + void + Clear(); + + double + GetLastUpTime() + {Check(this); return lastUpTime;} + double + GetTotalUpTime() + {Check(this); return totalUpTime;} + }; + + //####################################################################### + //######################## TraceOf ################################ + //####################################################################### + + template class TraceOf: + public Trace + { + protected: + double + weightedSum; + T + currentValue; + + TraceSample::Type + sampleType; + + void + DumpTraceStatus(); + void + ResetTrace(); + #if defined(USE_TIME_ANALYSIS) + void + StartTiming(); + Scalar + CalculateUsage( + long frame, + Scalar fraction, + double sample_time + ); + void + PrintUsage(Scalar usage); + #endif + + public: + TraceOf( + const char* name, + const T& initial_value, + Type trace_type, + TraceSample::Type sample_type + ); + + void + TakeSnapshot(const T& value); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template TraceOf::TraceOf( + const char* name, + const T& initial_value, + Type trace_type, + TraceSample::Type sample_type + ): + Trace(name, trace_type) + { + currentValue = initial_value; + sampleType = sample_type; + TraceOf::ResetTrace(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template void + TraceOf::DumpTraceStatus() + { + Check(this); + DEBUG_STREAM << currentValue; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template void + TraceOf::ResetTrace() + { + #if defined(USE_TIME_ANALYSIS) + weightedSum = 0.0; + #endif + } + + #if defined(USE_TIME_ANALYSIS) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template void + TraceOf::StartTiming() + { + Check(this); + weightedSum = 0.0; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template Scalar + TraceOf::CalculateUsage( + long frame, + Scalar fraction, + double sample_time + ) + { + double last_part = frame - lastFrameActivity; + last_part += fraction - lastFractionActivity; + weightedSum += last_part * currentValue; + Scalar result = weightedSum / sample_time; + Check_Fpu(); + weightedSum = 0.0; + return result; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template void + TraceOf::PrintUsage(Scalar usage) + { + Check(this); + + DEBUG_STREAM << usage; + } + + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template void + TraceOf::TakeSnapshot(const T& value) + { + Check(this); + + #if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG) + long frame = Now().ticks; + Scalar fraction = Get_Frame_Percent_Used(); + #endif + + #if defined(USE_TIME_ANALYSIS) + double last_part = frame - lastFrameActivity; + last_part += fraction - lastFractionActivity; + weightedSum += last_part * currentValue; + lastFrameActivity = frame; + lastFractionActivity = fraction; + #endif + + currentValue = value; + + #if defined(USE_TRACE_LOG) + IncrementSampleCount(); + MemoryStream *log = GetTraceLog(); + if (log) + { + Check(log); + SnapshotOf *sample = (SnapshotOf*)log->GetPointer(); + sample->sampleType = (Byte)sampleType; + sample->traceNumber = traceNumber; + sample->sampleFrame = (Word)frame; + sample->sampleFraction = fraction; + sample->snapShot = currentValue; + log->AdvancePointer(sizeof(*sample)); + } + #endif + } + + //####################################################################### + //##################### TraceManager ############################## + //####################################################################### + + class TraceManager SIGNATURED + { + friend class Trace; + + protected: + ChainOf traceChain; + long sampleStartFrame; + Scalar sampleStartFraction; + int + actualSampleCount, + ignoredSampleCount; + MemoryStream + *allocatedTraceLog, + *activeTraceLog; + Byte traceCount; + + void + Add(Trace *trace); + + public: + TraceManager(); + ~TraceManager(); + + Byte + GetTraceCount() + {Check(this); return traceCount;} + void + DumpTracesStatus(); + void + ResetTraces(); + +# if defined(USE_TIME_ANALYSIS) + void + StartTimingAnalysis(); + int + SnapshotTimingAnalysis(Logical print=False); +# endif + +# if defined(USE_TRACE_LOG) + void + CreateTraceLog( + size_t max_trace_samples, + Logical start_sampling + ); + void + SaveTraceLog(const char* filename); + void + MarkTraceLog(); + void + SuspendTraceLogging(); + void + ResumeTraceLogging(); +# endif + + Logical + TestInstance() const; + }; + + extern TraceManager + trace_manager; + + inline MemoryStream* + Trace::GetTraceLog() + { + Check(this); Check(&trace_manager); + return trace_manager.activeTraceLog; + } + + inline void + Trace::IncrementSampleCount() + { + Check(this); Check(&trace_manager); + if (!trace_manager.activeTraceLog) + { + ++trace_manager.ignoredSampleCount; + } + else + { + ++trace_manager.actualSampleCount; + } + } + +# endif + +#endif + diff --git a/CODE/RP/MUNGA/TRACSTUB.CPP b/CODE/RP/MUNGA/TRACSTUB.CPP new file mode 100644 index 0000000..fb75f71 --- /dev/null +++ b/CODE/RP/MUNGA/TRACSTUB.CPP @@ -0,0 +1,38 @@ +#include +#pragma hdrstop + +#if !defined(HEAP_HPP) + #include +#endif + +void* + Get_Caller(int) +{ + return NULL; +} + +size_t + UserHeap::GetMainHeapInitialSize() +{ + return 0x200000; +} + +#if defined(USE_ACTIVE_PROFILE) + + void + BitTrace::SetLineImplementation(Byte) + { + } + + void + BitTrace::ClearLineImplementation(Byte) + { + } + + Logical + BitTrace::IsLineValidImplementation(Byte) + { + return True; + } + +#endif diff --git a/CODE/RP/MUNGA/TREE.CPP b/CODE/RP/MUNGA/TREE.CPP new file mode 100644 index 0000000..775190c --- /dev/null +++ b/CODE/RP/MUNGA/TREE.CPP @@ -0,0 +1,865 @@ +//===========================================================================// +// File: tree.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of Tree class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/01/94 ECH Initial coding. // +// 11/02/94 JMA Made compatible with SGI CC, merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/03/94 ECH Removed SGI warning // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(TREE_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeNode ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// TreeNode +//########################################################################### +// +TreeNode::TreeNode( + Tree *tree, + Plug *plug +): + Link(tree, plug) +{ + less = NULL; + greater = NULL; + parent = NULL; +} + +// +//########################################################################### +// ~TreeNode +//########################################################################### +// +TreeNode::~TreeNode() +{ + Tree *tree = Cast_Object(Tree*, socket); + + Check(this); + Check(tree); + + // + //------------------------------------------- + // Notify iterators that deletion is occuring + //------------------------------------------- + // + tree->SendIteratorMemo(PlugRemoved, this); + + // + //----------------------------------- + // Tell the tree to release this node + //----------------------------------- + // + tree->SeverFromTreeNode(this); + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (tree->GetReleaseNode() != NULL) + { + Check(tree->GetReleaseNode()); + tree->GetReleaseNode()->ReleaseLinkHandler(tree, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + TreeNode::TestInstance() const +{ + Link::TestInstance(); + + if (less != NULL) + { + Check_Signature(less); + } + if (greater != NULL) + { + Check_Signature(greater); + } + if (parent != NULL) + { + Check_Signature(parent); + } + return True; +} + +// +//########################################################################### +// SetupTreeLinks +//########################################################################### +// +void + TreeNode::SetupTreeLinks( + TreeNode *less, + TreeNode *greater, + TreeNode *parent + ) +{ + this->less = less; + this->greater = greater; + this->parent = parent; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tree ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// Tree +//########################################################################### +// +Tree::Tree( + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + root = NULL; +} + +// +//########################################################################### +// ~Tree +//########################################################################### +// +Tree::~Tree() +{ + SetReleaseNode(NULL); + while (root != NULL) + { + Unregister_Object(root); + delete root; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Tree::TestInstance() const +{ + SortedSocket::TestInstance(); + + // + // Check root if not null + // + if (root != NULL) + { + Check(root); + } + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Tree::AddImplementation( + Plug *plug + ) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + Tree::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + Check(this); + Check(plug); + + /* + * Verify that value has not been added + */ + Verify(HasUniqueEntries() ? SearchForValue(value) == NULL : (Logical)True); + + /* + * Make new tree node + */ + TreeNode *node; + + node = MakeTreeNode(plug, value); + Register_Object(node); + + /* + * Add to the tree and send iterators memo to + * update pointers + */ + AddTreeNode(node); + SendIteratorMemo(PlugAdded, node); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + Tree::FindImplementation( + const void *value + ) +{ + TreeNode *node; + + if ((node = SearchForValue(value)) != NULL) + { + Check(node); + return node->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// MakeTreeNode +//########################################################################### +// +TreeNode* + Tree::MakeTreeNode( + Plug*, + const void* + ) +{ + Fail("Tree::MakeTreeNode - Shoule never reach here"); + return NULL; +} + +// +//########################################################################### +// CompareTreeNodes +//########################################################################### +// +int + Tree::CompareTreeNodes( + TreeNode*, + TreeNode* + ) +{ + Fail("Tree::CompareTreeNodes - Shoule never reach here"); + return 0; +} + +// +//########################################################################### +// CompareValueToTreeNode +//########################################################################### +// +int + Tree::CompareValueToTreeNode( + const void*, + TreeNode* + ) +{ + Fail("Tree::CompareValueToTreeNode - Shoule never reach here"); + return 0; +} + +// +//########################################################################### +// AddTreeNode +//########################################################################### +// +void + Tree::AddTreeNode( + TreeNode *newNode + ) +{ + Check(this); + Check(newNode); + + /* + * If root is NULL this is the first item + */ + if (root == NULL) + { + newNode->SetupTreeLinks(NULL, NULL, NULL); + root = newNode; + return; + } + + /* + * Search for insertion point + */ + TreeNode *node; + + node = root; + while (node != NULL) + { + Check(node); + + if (CompareTreeNodes(newNode, node) < 0) + { + if (node->less == NULL) + { + newNode->SetupTreeLinks(NULL, NULL, node); + node->less = newNode; + break; + } + else + node = node->less; + } + else + { + if (node->greater == NULL) + { + newNode->SetupTreeLinks(NULL, NULL, node); + node->greater = newNode; + break; + } + else + node = node->greater; + } + } +} + +// +//########################################################################### +// SeverFromTreeNode +//########################################################################### +// +void + Tree::SeverFromTreeNode( + TreeNode *node + ) +{ + Check(this); + Check(node); + + if (node->greater == NULL) + { + if (node->less == NULL) + { + // + //-------------------------------------------------------------------- + // The node has no subtrees + //-------------------------------------------------------------------- + // + if (node == root) + { + // + // Tree is now empty, set root to null + // + root = NULL; + } + else + { + // + // Set appropiate branch to NULL + // + Check(node->parent); + if (node->parent->less == node) + node->parent->less = NULL; + else + node->parent->greater = NULL; + } + } + else + { + // + //-------------------------------------------------------------------- + // The node has a less subtree + //-------------------------------------------------------------------- + // + Check(node->less); + + if (node == root) + { + // + // Node is root... Set subtree to new root + // + root = node->less; + node->less->parent = NULL; + } + else + { + // + // Node is not root + // Set parents pointer to subtree + // + Check( node->parent ); + if (node->parent->less == node) + { + node->parent->less = node->less; + } + else + { + node->parent->greater = node->less; + } + // + // Set subtree parent to node parent + // + node->less->parent = node->parent; + } + } + } + else { + if (node->less == NULL) + { + // + //-------------------------------------------------------------------- + // The node has a greater subtree + //-------------------------------------------------------------------- + // + Check( node->greater ); + if (node == root) + { + // + // Node is root + // Set subtree to new root + // + root = node->greater; + // + // Set new root to have null parent + // + node->greater->parent = NULL; + } + else + { + // + // Node is not root + // Set parents pointer to subtree + // + Check( node->parent ); + if (node->parent->less == node) + node->parent->less = node->greater; + else + node->parent->greater = node->greater; + // + // Set subtree parent to node parent + // + node->greater->parent = node->parent; + } + } + else + { + // + //-------------------------------------------------------------------- + // The node has lesser and greater sub-trees + //-------------------------------------------------------------------- + // + TreeNode *successor; + + Check(node->less); + Check(node->greater); + + successor = node->greater; + while (successor->less != NULL) + { + successor = successor->less; + Check(successor); + } + + // + // Set successor's parent to subtree + // + Check(successor->parent); + if (successor->parent->less == successor) + successor->parent->less = successor->greater; + else + successor->parent->greater = successor->greater; + + // + // Set successor's subtree to parent + // + if (successor->greater != NULL) + { + Check(successor->greater); + successor->greater->parent = successor->parent; + } + + // + // Place at node + // + successor->parent = node->parent; + successor->less = node->less; + successor->greater = node->greater; + + if (root == node) + { + // + // Node was root + // + root = successor; + } + else + { + // + // Set nodes parent to successor + // + Check(successor->parent); + if (successor->parent->less == node) + successor->parent->less = successor; + else + successor->parent->greater = successor; + } + + // + // Set subtrees parent to successor + // + if (successor->greater != NULL) + { + Check(successor->greater); + successor->greater->parent = successor; + } + if (successor->less != NULL) + { + Check(successor->less); + successor->less->parent = successor; + } + } + } +} + +// +//########################################################################### +// SearchForValue +//########################################################################### +// +TreeNode* + Tree::SearchForValue( + const void *value + ) +{ + TreeNode *node; + int ret; + + node = root; + while (node != NULL) + { + Check(node); + if ((ret = CompareValueToTreeNode(value, node)) == 0) + break; + node = (ret < 0) ? node->less : node->greater; + } + return node; +} + +// +//########################################################################### +// TreeIterator +//########################################################################### +// +TreeIterator::TreeIterator(Tree *tree): + SortedIterator(tree) +{ + First(); +} + +// +//########################################################################### +//########################################################################### +// +TreeIterator::~TreeIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + TreeIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + if (currentNode != NULL) + { + Check(currentNode); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + TreeIterator::First() +{ + TreeNode *node; + + node = Cast_Object(Tree*, socket)->root; + if (node != NULL) + { + Check(node); + while (node->less != NULL) + { + node = node->less; + Check(node); + } + } + currentNode = node; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + TreeIterator::Last() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + TreeIterator::Next() +{ + TreeNode *node; + + if ((node = currentNode) == NULL) + return; + + Check(node); + if (node->greater != NULL) + { + node = node->greater; + Check(node); + while (node->less != NULL) + { + node = node->less; + Check(node); + } + currentNode = node; + return; + } + + currentNode = NULL; + while (node->parent != NULL) + { + Check(node->parent); + if (node == node->parent->less) + { + currentNode = node->parent; + return; + } + node = node->parent; + Check(node); + } +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + TreeIterator::Previous() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +#if 0 +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *TreeIterator::ReadAndNextImplementation() +{ + void *plug; + + if ((plug = GetCurrentImplementation()) != NULL) + { + Next(); + } + return plug; +} +#endif + +#if 0 +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *TreeIterator::ReadAndPreviousImplementation() +{ + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif + return(NULL); +} +#endif + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *TreeIterator::GetCurrentImplementation() +{ + if (currentNode != NULL) + { + Check(currentNode); + return currentNode->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + TreeIterator::GetSize() +{ + TreeIterator iterator(Cast_Object(Tree*, socket)); + CollectionSize i = 0; + + while (iterator.ReadAndNextImplementation() != NULL) + { + i++; + } + return(i); +} + +#if 0 +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *TreeIterator::GetNthImplementation( + CollectionSize index + ) +{ + CollectionSize i = 0; + void *plug; + + First(); + while ((plug = GetCurrentImplementation()) != NULL) + { + if (i == index) + return plug; + Next(); + i++; + } + return NULL; +} +#endif + +// +//########################################################################### +// Remove +//########################################################################### +// +void + TreeIterator::Remove() +{ + if (currentNode != NULL) + { + Unregister_Object(currentNode); + delete currentNode; + } +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + TreeIterator::FindImplementation( + const void *value + ) +{ + TreeNode *node; + + if ((node = Cast_Object(Tree*, socket)->SearchForValue(value)) != NULL) + { + Check(node); + return (currentNode = node)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + TreeIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + if (memo == PlugRemoved) + { + if (content == currentNode) + Next(); + } +} + +#if defined(TEST_CLASS) +# include "tree.tcp" +#endif diff --git a/CODE/RP/MUNGA/TREE.HPP b/CODE/RP/MUNGA/TREE.HPP new file mode 100644 index 0000000..ad8fb35 --- /dev/null +++ b/CODE/RP/MUNGA/TREE.HPP @@ -0,0 +1,571 @@ +//===========================================================================// +// File: tree.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification of Tree class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/01/94 ECH Initial coding. // +// 11/02/94 JMA Made compatible with SGI CC, merged with iterator // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/05/94 JMA Made compatible with GNU C++ // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(TREE_HPP) +# define TREE_HPP + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(SRTSKT_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + + class Tree; + class TreeIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeNode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class TreeNode: + public Link + { + friend class Tree; + friend class TreeIterator; + + public: + ~TreeNode(); + Logical + TestInstance() const; + + protected: + TreeNode( + Tree *tree, + Plug *plug + ); + + private: + void + SetupTreeLinks( + TreeNode *less, + TreeNode *greater, + TreeNode *parent + ); + + TreeNode *less; + TreeNode *greater; + TreeNode *parent; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeNodeOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define TREENODE_MEMORYBLOCK_ALLOCATION (100) + + template class TreeNodeOf: + public TreeNode + { + public: + TreeNodeOf( + Tree *tree, + Plug *plug, + const V &value + ); + ~TreeNodeOf(); + + void* + operator new(size_t); + void + operator delete(void *where); + + V + GetValue() + {return value;} + V* + GetValuePointer() + {return &value;} + + private: + static MemoryBlock + *allocatedMemory; + static CollectionSize + allocationCount; + + V value; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeNodeOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~ + + template MemoryBlock* + TreeNodeOf::allocatedMemory = NULL; + template CollectionSize + TreeNodeOf::allocationCount = 0; + + template + TreeNodeOf::TreeNodeOf( + Tree *tree, + Plug *plug, + const V &value + ): + TreeNode(tree, plug) + { + this->value = value; + } + + template + TreeNodeOf::~TreeNodeOf() + { + } + + #if 0 + template void* + TreeNodeOf::operator new(size_t) + { + if (allocatedMemory == NULL) + { + allocatedMemory = + new MemoryBlock( + sizeof(TreeNodeOf), + TREENODE_MEMORYBLOCK_ALLOCATION, + TREENODE_MEMORYBLOCK_ALLOCATION + ); + } + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void + TreeNodeOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + } + #else + template void* + TreeNodeOf::operator new(size_t) + { + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = + new MemoryBlock( + sizeof(TreeNodeOf), + TREENODE_MEMORYBLOCK_ALLOCATION, + TREENODE_MEMORYBLOCK_ALLOCATION, + "TreeNodeOf" + ); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void + TreeNodeOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); + } + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tree ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Tree: + public SortedSocket + { + friend class TreeNode; + friend class TreeIterator; + + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructor and testing + //-------------------------------------------------------------------- + // + Tree( + Node *node, + Logical has_unique_entries + ); + ~Tree(); + + Logical + TestInstance() const; + static void + TestClass(); + static void + ProfileClass(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + AddImplementation(Plug *); + void + AddValueImplementation( + Plug *plug, + const void *value + ); + Plug + *FindImplementation(const void *value); + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + virtual TreeNode* + MakeTreeNode( + Plug *plug, + const void *value + ); + virtual int + CompareTreeNodes( + TreeNode *link1, + TreeNode *link2 + ); + virtual int + CompareValueToTreeNode( + const void *value, + TreeNode *link + ); + + void + AddTreeNode(TreeNode *node); + void + SeverFromTreeNode(TreeNode *node); + TreeNode* + SearchForValue(const void *value); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + TreeNode *root; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class TreeOf: + public Tree + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + TreeOf( + Node *node, + Logical has_unique_entries + ); + ~TreeOf(); + + // + //-------------------------------------------------------------------- + // Socket methods (see Socket for full listing) + //-------------------------------------------------------------------- + // + void + AddValue( + T plug, + const V &value + ) + {AddValueImplementation(plug, &value);} + T + Find(const V &value) + {return (T)FindImplementation(&value);} + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + TreeNode + *MakeTreeNode( + Plug *plug, + const void *value + ) + {return new TreeNodeOf(this, plug, *(V*)value);} + int + CompareTreeNodes( + TreeNode *link1, + TreeNode *link2 + ); + int + CompareValueToTreeNode( + const void *value, + TreeNode *link + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + TreeOf::TreeOf( + Node *node, + Logical has_unique_entries + ): + Tree( + node, + has_unique_entries + ) + { + } + + template + TreeOf::~TreeOf() + { + } + + #if 0 + template int + TreeOf::CompareTreeNodes( + TreeNode *node1, + TreeNode *node2 + ) + { + V result = + Cast_Object(TreeNodeOf*, node1)->GetValue() - + Cast_Object(TreeNodeOf*, node2)->GetValue(); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } + #else + template int + TreeOf::CompareTreeNodes( + TreeNode *node1, + TreeNode *node2 + ) + { + V *ptr1 = Cast_Object(TreeNodeOf*, node1)->GetValuePointer(); + V *ptr2 = Cast_Object(TreeNodeOf*, node2)->GetValuePointer(); + + Check_Pointer(ptr1); + Check_Pointer(ptr2); + + if (*ptr1 == *ptr2) + return 0; + else + return ((*ptr1 > *ptr2) ? 1 : -1); + } + #endif + + #if 0 + template int + TreeOf::CompareValueToTreeNode( + const void *value, + TreeNode *node + ) + { + Check_Pointer(value); + + V result = + *(V*)value - Cast_Object(TreeNodeOf*, node)->GetValue(); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } + #else + template int + TreeOf::CompareValueToTreeNode( + const void *value, + TreeNode *node + ) + { + Check_Pointer(value); + + V *ptr = Cast_Object(TreeNodeOf*, node)->GetValuePointer(); + Check_Pointer(ptr); + + if (*(V*)value == *ptr) + return 0; + else + return (*(V*)value > *ptr) ? 1 : -1; + } + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class TreeIterator: + public SortedIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors, Destructor and testing + //-------------------------------------------------------------------- + // + TreeIterator(Tree *tree); + ~TreeIterator(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + void + First(); + void + Next(); + CollectionSize + GetSize(); + void + Remove(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void* + GetCurrentImplementation(); + Plug* + FindImplementation(const void *value); + + protected: + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + TreeNode + *currentNode; + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + Last(); // Marked as private so that clients do not use it + void + Previous(); // Marked as private so that clients do not use it + + void + ReceiveMemo( + IteratorMemo memo, + void *content + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class TreeIteratorOf: + public TreeIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors and Destructor + //-------------------------------------------------------------------- + // + TreeIteratorOf(TreeOf *tree); + TreeIteratorOf(TreeOf &tree); + ~TreeIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T + ReadAndNext() + {return (T)ReadAndNextImplementation();} + T + GetCurrent() + {return (T)GetCurrentImplementation();} + T + GetNth(CollectionSize index) + {return (T)GetNthImplementation(index);} + T + Find(const V &value) + {return (T)FindImplementation(&value);} + V + GetValue() + {return Cast_Object(TreeNodeOf*, currentNode)->GetValue();} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + TreeIteratorOf::TreeIteratorOf(TreeOf *tree): + TreeIterator(tree) + { + } + + template + TreeIteratorOf::TreeIteratorOf(TreeOf &tree): + TreeIterator(&tree) + { + } + + template + TreeIteratorOf::~TreeIteratorOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/TREE.TCP b/CODE/RP/MUNGA/TREE.TCP new file mode 100644 index 0000000..73b4c52 --- /dev/null +++ b/CODE/RP/MUNGA/TREE.TCP @@ -0,0 +1,521 @@ +//===========================================================================// +// File: tree.tst // +// Project: MUNGA Brick: Connection Library // +// Contents: test routines for Table class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 10/01/94 ECH Initial coding. // +// 11/02/94 JMA Made compatible with SGI CC, used Time class instead of // +// clock_t // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/08/94 JMA Made compatible with GNU C++ // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "time.hpp" + +class TreeTestPlug: + public Plug +{ +public: + int value; + + TreeTestPlug(int value); + ~TreeTestPlug(); +}; + +class TreeTestNode: + public Node +{ +public: + TreeOf tree1; + TreeOf tree2; + + TreeTestNode(); + ~TreeTestNode(); + + void VerifyOrder(); + void RunProfile(); + void RunTest(); +}; + +#define RandInt(x) (rand() % x + 1) + +TreeTestPlug::TreeTestPlug(int value) +{ + this->value = value; +} + +TreeTestPlug::~TreeTestPlug() +{ + this->value = -1; +} + +TreeTestNode::TreeTestNode(): + tree1(this, True), tree2(this, True) +{ +} + +TreeTestNode::~TreeTestNode() +{ +} + +// +//########################################################################### +// ProfileClass +//########################################################################### +// + +void + Tree::ProfileClass() +{ + TreeTestNode testNode; + Time startTicks = Now(); + + Test_Message("Tree::ProfileClass \n"); + + testNode.RunProfile(); + + Test_Message("Tree::ProfileClass elapsed = " << (Now() - startTicks) << endl); +} + +// +//########################################################################### +// TestClass +//########################################################################### +// + +void + Tree::TestClass() +{ + DEBUG_STREAM << "Starting Tree test...\n"; + + TreeTestNode testNode; + + testNode.RunTest(); +} + +// +//########################################################################### +// VerifyOrder +//########################################################################### +// +void + TreeTestNode::VerifyOrder() +{ + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + TreeTestPlug *testPlug1, *testPlug2; + int i, size; + + size = iterator1.GetSize(); + for (i = 1; i < size; i++) + { + testPlug1 = iterator1.GetNth(i-1); + testPlug2 = iterator2.GetNth(i); + Check(testPlug1); + Check(testPlug2); + + Verify(testPlug1->value < testPlug2->value); + } +} + +// +//########################################################################### +// RunProfile +//########################################################################### +// +void + TreeTestNode::RunProfile() +{ + TreeTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; + Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Run timing tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + startTicks = Now(); + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new TreeTestPlug(values[i]); + Register_Object( testPlug1 ); + tree1.AddValue(testPlug1, values[i]); + tree2.AddValue(testPlug1, values[i]); + } + Test_Message("TreeTestNode::RunTest Create = " << (Now() - startTicks) << endl); + + /* + * Iterate over both sockets + */ + startTicks = Now(); + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator2.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + } + Test_Message("TreeTestNode::RunTest Iterate = " << (Now() - startTicks) << endl); + + /* + * Find + */ + startTicks = Now(); + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = iterator1.Find(i); + testPlug2 = iterator2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + Verify( testPlug1 == testPlug2 ); + } + } + Test_Message("TreeTestNode::RunTest Find = " << (Now() - startTicks) << endl); + + /* + * Destroy from tree1, verify with tree2 + */ + startTicks = Now(); + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + + Unregister_Object(testPlug1); + delete(testPlug1); + } + Verify( i == TEST_CLASS ); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + Test_Message("TreeTestNode::RunTest Destroy = " << (Now() - startTicks) << endl); +} + +// +//########################################################################### +// RunTest +//########################################################################### +// +void + TreeTestNode::RunTest() +{ + TreeTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; +// Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Stress tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new TreeTestPlug(values[i]); + Register_Object(testPlug1); + tree1.AddValue(testPlug1, values[i]); + tree2.AddValue(testPlug1, values[i]); + } + VerifyOrder(); + + /* + * Find + */ + { + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = tree1.Find(i); + testPlug2 = tree2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + Verify( testPlug1 == testPlug2 ); + } + } + + /* + * Test first and last + */ + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + iterator1.First(); + iterator2.First(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + Verify( testPlug1 == iterator1.GetNth(0) ); + Verify( testPlug1 == iterator2.GetNth(0) ); + } + + /* + * Test next and prev + */ + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + iterator1.Next(); + iterator2.Next(); + + i++; + } + Verify( i == TEST_CLASS ); + } + + /* + * Test read next and read prev + */ + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + testPlug2 = iterator2.ReadAndNext(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + i++; + } + Verify( i == TEST_CLASS ); + } + + /* + * Test nth + */ + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = iterator1.GetNth((int)i); + testPlug2 = iterator2.GetNth((int)i); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + } + } + + /* + * Test Remove + */ + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(0); + + Check( testPlug2 ); + Verify( testPlug2->value == i ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object(testPlug2); + delete testPlug2; + + i++; + VerifyOrder(); + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + + /* + * Test random deletion + */ + /* + * Add plugs to both sockets + */ + { + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new TreeTestPlug(values[i]); + Register_Object( testPlug1 ); + tree1.AddValue(testPlug1, values[i]); + tree2.AddValue(testPlug1, values[i]); + + VerifyOrder(); + } + VerifyOrder(); + } + + /* + * Perform random deletion + */ + { + int size, index; + TreeIteratorOf iterator1(tree1); + TreeIteratorOf iterator2(tree2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while((size = iterator1.GetSize()) != 0) + { + index = RandInt(size) - 1; + testPlug1 = iterator1.GetNth(index); + Check( testPlug1 ); + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(index); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + i++; + VerifyOrder(); + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } +} + + diff --git a/CODE/RP/MUNGA/UNITVEC.CPP b/CODE/RP/MUNGA/UNITVEC.CPP new file mode 100644 index 0000000..53eecff --- /dev/null +++ b/CODE/RP/MUNGA/UNITVEC.CPP @@ -0,0 +1,66 @@ +//===========================================================================// +// File: unitvec.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for unit vector class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(UNITVEC_HPP) + #include +#endif + +// +//############################################################################# +//############################################################################# +// +UnitVector& + UnitVector::Lerp( + const UnitVector&, // v1, + const UnitVector&, // v2, + Scalar // t + ) +{ + Check_Pointer(this); + Tell("UnitVector::Lerp stubbed out!\n"); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Logical + UnitVector::TestInstance() const +{ + Scalar length = Vector3D::LengthSquared(); + Scalar diff = 1.0f - length; + if (!Small_Enough(diff,2e-5)) + { + length = x*x + y*y + z*z; + diff = 1.0f - length; + if (!Small_Enough(diff,2e-5)) + { + Dump(*this); + Dump(length); + Dump(x*x + y*y + z*z); + Dump(diff); + return False; + } + } + return True; +} + +#if defined(TEST_CLASS) +# include "unitvec.tcp" +#endif + diff --git a/CODE/RP/MUNGA/UNITVEC.HPP b/CODE/RP/MUNGA/UNITVEC.HPP new file mode 100644 index 0000000..4c17f27 --- /dev/null +++ b/CODE/RP/MUNGA/UNITVEC.HPP @@ -0,0 +1,118 @@ +//===========================================================================// +// File: unitvec.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for unit vector class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +// 12/01/94 JMA Made compatible with SGI CC // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(UNITVEC_HPP) +# define UNITVEC_HPP + +# if !defined(VECTOR3D_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ UnitVector ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class LinearMatrix; + + class UnitVector: + public Vector3D + { + public: + // + // Constructors + // + UnitVector() + {} + UnitVector( + Scalar x, + Scalar y, + Scalar z + ): + Vector3D(x,y,z) + {} + + // + // Assignment operators + // + UnitVector& + operator=(const UnitVector &vector) + {Check(&vector); Vector3D::operator=(vector); return *this;} + UnitVector& + operator=(const Vector3D& v) + {Vector3D::Normalize(v); return *this;} + + // + // Math operations + // + UnitVector& + Negate(const UnitVector &v) + {Check(&v); Vector3D::Negate(v); return *this;} + + Scalar + operator*(const Vector3D& v) const + {return Vector3D::operator*(v);} + + // + // Transforms + // + UnitVector& Multiply( + const UnitVector &v, + const LinearMatrix &m + ); + UnitVector& + operator*=(const LinearMatrix &m); + UnitVector& + MultiplyByInverse( + const UnitVector &v, + const LinearMatrix &m + ) + {Vector3D::MultiplyByInverse(v,m); return *this;} + + // + // Template support + // + UnitVector& + Lerp( + const UnitVector& v1, + const UnitVector& v2, + Scalar t + ); + + // + // Support functions + // + Logical + TestInstance() const; + static Logical + TestClass(); + + private: + static const UnitVector identity; + UnitVector& Negate(const Vector3D &V); + UnitVector& Add(const Vector3D& V1,const Vector3D& V2); + UnitVector& operator+=(const Vector3D& V); + UnitVector& Subtract(const Vector3D& V1,const Vector3D& V2); + UnitVector& operator-=(const Vector3D& V); + UnitVector& Cross(const Vector3D& V1,const Vector3D& V2); + UnitVector& Multiply(const Vector3D& V,Scalar Scale); + UnitVector& operator*=(Scalar Value); + UnitVector& Multiply(const Vector3D& V1,const Vector3D& V2); + UnitVector& operator*=(const Vector3D &V); + UnitVector& Multiply(const Vector3D &Source, const AffineMatrix &M); + UnitVector& MultiplyByInverse(const Vector3D &Source, const LinearMatrix &M); + UnitVector& Divide(const Vector3D& V,Scalar Scale); + UnitVector& operator/=(Scalar Value); + UnitVector& Combine(const Vector3D& V1,Scalar t1,const Vector3D& V2,Scalar t2); + }; + +#endif diff --git a/CODE/RP/MUNGA/UNITVEC.TCP b/CODE/RP/MUNGA/UNITVEC.TCP new file mode 100644 index 0000000..45a605d --- /dev/null +++ b/CODE/RP/MUNGA/UNITVEC.TCP @@ -0,0 +1,77 @@ +//===========================================================================// +// File: unitvec.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for unit vector class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LINMTRX_HPP) + #include +#endif + +#if !defined(ROTATION_HPP) + #include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + UnitVector::TestClass() +{ + DEBUG_STREAM << "Starting UnitVector test...\n"; + + UnitVector + b; + const UnitVector + c(0.6f,0.0f,0.8f); + UnitVector + d(0.8f,-0.6f,0.0f); + + Test(c.x == 0.6f && c.y == 0.0f && c.z == 0.8f); + + Test(c[2] == c.z); + + b = c; + Test(b.x == c.x && b.y == c.y && b.z == c.z); + Test(Close_Enough(b,c)); + Test(b == c); + + b.Negate(c); + Test(b == UnitVector(-c.x,-c.y,-c.z)); + + Scalar f = c*d; + Test(Close_Enough(f,c.x*d.x + c.y*d.y + c.z*d.z)); + + LinearMatrix + m; + EulerAngles + r(PI_OVER_4,0.0f,0.0f); + m = r; + b.Multiply(c,m); + Test(b == UnitVector(c.x,c.y*m(1,1)+c.z*m(2,1),c.y*m(1,2)+c.z*m(2,2))); + b = c; + b *= m; + Test(b == UnitVector(c.x,c.y*m(1,1)+c.z*m(2,1),c.y*m(1,2)+c.z*m(2,2))); + + f = c.LengthSquared(); + Test(f == 1.0f); + f = c.Length(); + Test(f == 1.0f); + + Vector3D v(0.0f,1.2f,1.6f); + f = v.Length(); + b = v; + Test(b == UnitVector(v.x/f, v.y/f, v.z/f)); + + return True; +} + diff --git a/CODE/RP/MUNGA/UPDATE.CPP b/CODE/RP/MUNGA/UPDATE.CPP new file mode 100644 index 0000000..ac6757b --- /dev/null +++ b/CODE/RP/MUNGA/UPDATE.CPP @@ -0,0 +1,273 @@ +//===========================================================================// +// File: update.cc // +// Project: MUNGA Brick: Update Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/20/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(UPDATE_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(HOSTMGR_HPP) + #include +#endif + +#if !defined(INTEREST_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +#if defined(TRACE_UPDATE_REPLICANTS) + static BitTrace Update_Replicants("Update Replicants"); + #define SET_UPDATE_REPLICANTS() Update_Replicants.Set() + #define CLEAR_UPDATE_REPLICANTS() Update_Replicants.Clear() +#else + #define SET_UPDATE_REPLICANTS() + #define CLEAR_UPDATE_REPLICANTS() +#endif + +#if defined(TRACE_UPDATE_MASTERS) + static BitTrace Update_Masters("Update Masters"); + #define SET_UPDATE_MASTERS() Update_Masters.Set() + #define CLEAR_UPDATE_MASTERS() Update_Masters.Clear() +#else + #define SET_UPDATE_MASTERS() + #define CLEAR_UPDATE_MASTERS() +#endif + +MemoryBlock + SimulationEncore::AllocatedMemory( + sizeof(SimulationEncore), + 10, + 10, + "Simulation Encores" + ); + +SimulationEncore::SimulationEncore( + Simulation *sim, + Simulation::Encore callback +) +{ + encoreSimulation = sim; + encoreCallback = callback; + runWatchers = True; +} + +SimulationEncore::~SimulationEncore() +{ +} + +// +//############################################################################# +//############################################################################# +// +UpdateManager::UpdateManager(): + simulationEncores(NULL) +{ +} + +// +//############################################################################# +//############################################################################# +// +UpdateManager::~UpdateManager() +{ + ChainIteratorOf encores(simulationEncores); + SimulationEncore *encore; + while ((encore = encores.ReadAndNext()) != NULL) + { + Unregister_Object(encore); + delete encore; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + UpdateManager::TestInstance() const +{ + Node::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + UpdateManager::Execute(Time target_render_time) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Execute the replicants and masters that are interesting and dynamic + //-------------------------------------------------------------------------- + // + Check(application); + Check(application->GetHostManager()); + + HostManager::DynamicReplicantEntityIterator + replicant_entity_iterator(application->GetHostManager()); + HostManager::DynamicMasterEntityIterator + master_entity_iterator(application->GetHostManager()); + + // + //-------------------------------------------------------------------------- + // Execute the replicants + //-------------------------------------------------------------------------- + // + SET_UPDATE_REPLICANTS(); + + Entity + *replicant; + + while ((replicant = replicant_entity_iterator.ReadAndNext()) != NULL) + { + Check(replicant); + if (replicant->IsReplicantExecutable()) + { + replicant->Execute(target_render_time); + } + } + + CLEAR_UPDATE_REPLICANTS(); + + // + //-------------------------------------------------------------------------- + // Execute the master entities, if they need to be updated then send + // update messages, and notify the interest manager of moved entities + //-------------------------------------------------------------------------- + // + SET_UPDATE_MASTERS(); + + Entity + *entity; + Entity::UpdateMessage + *update_message; + + while ((entity = master_entity_iterator.ReadAndNext()) != NULL) + { + Check(entity); + + // + //----------------------------------------------------------------------- + // If the entity is not interesting then skip it + //----------------------------------------------------------------------- + // + if (!entity->IsInteresting() || !entity->IsNonReplicantExecutable()) + { + continue; + } + + // + //----------------------------------------------------------------------- + // Run the execute method + //----------------------------------------------------------------------- + // + update_message = entity->Execute(target_render_time); + + // + //----------------------------------------------------------------------- + // Update the interest zone id + //----------------------------------------------------------------------- + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->EntityUpdateInterestZone(entity); + + // + //----------------------------------------------------------------------- + // If update message is not null then send the change + //----------------------------------------------------------------------- + // + if (update_message != NULL) + { + Check(update_message); + + Check(application); + application->GetInterestManager()->EntityUpdateReplicants( + entity, + update_message + ); + } + } + + // + //-------------------------------------------------------------------------- + // Lastly, run through and do any requested encores + //-------------------------------------------------------------------------- + // + ChainIteratorOf + encores(simulationEncores); + SimulationEncore + *encore; + + while ((encore = encores.ReadAndNext()) != NULL) + { + Check(encore); + Check(encore->encoreSimulation); + (encore->encoreSimulation->*encore->encoreCallback)(); + if (encore->runWatchers) + { + encore->encoreSimulation->ExecuteWatchers(); + encore->encoreSimulation->ClearWatcherDelay(); + } + Unregister_Object(encore); + delete encore; + } + CLEAR_UPDATE_MASTERS(); +} + +// +//############################################################################# +//############################################################################# +// +void + UpdateManager::RequestEncore( + Simulation *simulation, + Simulation::Encore encore + ) +{ + // + //---------------------------------------------------------------------- + // Make sure that we only run the watcher on a given simulation once per + // frame + //---------------------------------------------------------------------- + // + ChainIteratorOf encores(simulationEncores); + SimulationEncore *i; + while ((i = encores.ReadAndNext()) != NULL) + { + if (i->encoreSimulation == simulation && i->runWatchers) + { + i->runWatchers = False; + break; + } + } + + SimulationEncore *request = new SimulationEncore(simulation, encore); + Register_Object(request); + simulationEncores.Add(request); +} + diff --git a/CODE/RP/MUNGA/UPDATE.HPP b/CODE/RP/MUNGA/UPDATE.HPP new file mode 100644 index 0000000..a3c4ade --- /dev/null +++ b/CODE/RP/MUNGA/UPDATE.HPP @@ -0,0 +1,109 @@ +//===========================================================================// +// File: update.hh // +// Project: MUNGA Brick: Update Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/20/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(UPDATE_HPP) +# define UPDATE_HPP + +#if !defined(NODE_HPP) +# include +#endif + +#if !defined(TIME_HPP) +# include +#endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + + class UpdateManager; + + class SimulationEncore: + public Plug + { + friend class UpdateManager; + + private: + static MemoryBlock AllocatedMemory; + + void* + operator new(size_t) + {return AllocatedMemory.New();} + void + operator delete(void *where) + {AllocatedMemory.Delete(where);} + + Simulation *encoreSimulation; + Simulation::Encore encoreCallback; + Logical runWatchers; + + SimulationEncore( + Simulation *sim, + Simulation::Encore callback + ); + ~SimulationEncore(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UpdateManager ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class UpdateManager: + public Node + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction + //-------------------------------------------------------------------- + // + UpdateManager(); + ~UpdateManager(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Execute + // + // Perform update management functions + //-------------------------------------------------------------------- + // + void + Execute(Time target_render_time); + + // + //---------------------------------------------------------------------- + // CreateEncore + // + // Registers a callback to be executed after all entity performances are + // completed + //---------------------------------------------------------------------- + // + void + RequestEncore( + Simulation *simulation, + Simulation::Encore encore + ); + + protected: + ChainOf + simulationEncores; + }; + +#endif + diff --git a/CODE/RP/MUNGA/VCHAIN.CPP b/CODE/RP/MUNGA/VCHAIN.CPP new file mode 100644 index 0000000..cc1fa77 --- /dev/null +++ b/CODE/RP/MUNGA/VCHAIN.CPP @@ -0,0 +1,647 @@ +//===========================================================================// +// File: vchain.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details of VChain class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/02/94 ECH Initial coding. // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(VCHAIN_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// VChainLink +//########################################################################### +// +VChainLink::VChainLink( + VChain *vchain, + Plug *plug +): + Link(vchain, plug) +{ + next = NULL; + prev = NULL; +} + +// +//########################################################################### +// ~VChainLink +//########################################################################### +// +VChainLink::~VChainLink() +{ + VChain *vchain = Cast_Object(VChain*, socket); + + // + //------------------------------------------- + // Notify iterators that deletion is occuring + //------------------------------------------- + // + vchain->SendIteratorMemo(PlugRemoved, this); + + // + //--------------------------- + // Remove from existing links + //--------------------------- + // + if (prev != NULL) + { + Check(prev); + prev->next = next; + } + else + { + Check(vchain); + vchain->head = next; + } + if (next != NULL) + { + Check(next); + next->prev = prev; + } + else + { + Check(vchain); + vchain->tail = prev; + } + prev = next = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (vchain->GetReleaseNode() != NULL) + { + Check(vchain->GetReleaseNode()); + vchain->GetReleaseNode()->ReleaseLinkHandler(vchain, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + VChainLink::TestInstance() const +{ + Link::TestInstance(); + + if (next != NULL) + { + Check_Signature(next); + } + if (prev != NULL) + { + Check_Signature(prev); + } + + return True; +} + +// +//########################################################################### +// SetupVChainLinks +//########################################################################### +// +void + VChainLink::SetupVChainLinks( + VChainLink *next, + VChainLink *prev + ) +{ + this->next = next; + this->prev = prev; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// VChain +//########################################################################### +// +VChain::VChain( + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + head = NULL; + tail = NULL; +} + +// +//########################################################################### +// ~VChain +//########################################################################### +// +VChain::~VChain() +{ + SetReleaseNode(NULL); + while (head != NULL) + { + Unregister_Object(head); + delete head; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + VChain::TestInstance() const +{ + SortedSocket::TestInstance(); + + if (head != NULL) + { + Check(head); + } + if (tail != NULL) + { + Check(tail); + } + + return True; +} + +// +//########################################################################### +// MakeVChainLink +//########################################################################### +// +VChainLink + *VChain::MakeVChainLink( + Plug*, + const void* + ) +{ + Fail("VChain::MakeVChainLink - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// CompareVChainLinks +//########################################################################### +// +int + VChain::CompareVChainLinks( + VChainLink*, + VChainLink* + ) +{ + Fail("VChain::CompareVChainLinks - Should never reach here"); + return 0; +} + +// +//########################################################################### +// CompareValueToVChainLink +//########################################################################### +// +int + VChain::CompareValueToVChainLink( + const void*, + VChainLink* + ) +{ + Fail("VChain::CompareValueToVChainLink - Should never reach here"); + return 0; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + VChain::AddImplementation( + Plug *plug + ) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + VChain::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + VChainLink *link; + + // + //------------------------------------------------------------- + // Verify that value has not been added + //------------------------------------------------------------- + // + Verify(HasUniqueEntries() ? (SearchForValue(value) == NULL) : (Logical)True); + + // + //------------------------------------------------------------- + // Make new vchain link + //------------------------------------------------------------- + // + link = MakeVChainLink(plug, value); + Register_Object(link); + + // + //------------------------------------------------------------- + // Find insertion point for the new link + //------------------------------------------------------------- + // + if (head == NULL) + { + link->SetupVChainLinks(NULL, NULL); + head = link; + tail = link; + } + else + { + VChainLink *greater_link; + + Check(head); + Check(tail); + + for ( + greater_link = head; + greater_link != NULL; + greater_link = greater_link->next + ) + { + Check(greater_link); + if (CompareValueToVChainLink(value, greater_link) < 0) + break; + } + + if (greater_link == NULL) + { + // + // Add after tail + // + link->SetupVChainLinks(NULL, tail); + tail->next = link; + tail = link; + } + else if (greater_link == head) + { + // + // Add before head + // + link->SetupVChainLinks(head, NULL); + head->prev = link; + head = link; + } + else + { + // + // Add before greater_link + // + link->SetupVChainLinks(greater_link, greater_link->prev); + greater_link->prev->next = link; + greater_link->prev = link; + } + } + + SendIteratorMemo(PlugAdded, link); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + VChain::FindImplementation( + const void *value + ) +{ + VChainLink *link; + + if ((link = SearchForValue(value)) != NULL) + { + Check(link); + return link->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// SearchForValue +//########################################################################### +// +VChainLink* + VChain::SearchForValue( + const void *value + ) +{ + VChainLink *link; + int ret; + + for (link = head; link != NULL; link = link->next) + { + Check(link); + if ((ret = CompareValueToVChainLink(value, link)) == 0) + break; + if (ret < 0) + return(NULL); + } + return link; +} + +// +//########################################################################### +// VChainIterator +//########################################################################### +// +VChainIterator::VChainIterator(VChain *vchain): + SortedIterator(vchain) +{ + Check(vchain); + currentLink = vchain->head; +} + +// +//########################################################################### +// VChainIterator +//########################################################################### +// +VChainIterator::VChainIterator(const VChainIterator *iterator): + SortedIterator(Cast_Object(VChain*, iterator->socket)) +{ + Check(iterator); + currentLink = iterator->currentLink; +} + +// +//########################################################################### +//########################################################################### +// +VChainIterator::~VChainIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + VChainIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + if (currentLink != NULL) + { + Check(currentLink); + } + + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + VChainIterator::First() +{ + currentLink = Cast_Object(VChain*, socket)->head; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + VChainIterator::Last() +{ + currentLink = Cast_Object(VChain*, socket)->tail; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + VChainIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->next; +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + VChainIterator::Previous() +{ + Check(currentLink); + currentLink = currentLink->prev; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *VChainIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->GetPlug(); + currentLink = currentLink->next; + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *VChainIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->prev; + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *VChainIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + return currentLink->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + VChainIterator::GetSize() +{ + VChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(VChain*, socket)->head; + link != NULL; + link = link->next + ) + { + Check(link); + count++; + } + return count; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *VChainIterator::GetNthImplementation( + CollectionSize index + ) +{ + VChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(VChain*, socket)->head; + link != NULL; + link = link->next + ) + { + Check(link); + if (count == index) + { + currentLink = link; + return currentLink->GetPlug(); + } + count++; + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + VChainIterator::Remove() +{ + Check(currentLink); + Unregister_Object(currentLink); + delete currentLink; +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + VChainIterator::FindImplementation( + const void *value + ) +{ + VChainLink *link; + + if ((link = Cast_Object(VChain*, socket)->SearchForValue(value)) != NULL) + { + Check(link); + return (currentLink = link)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + VChainIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + if (memo == PlugRemoved) + { + if (content == currentLink) + { + Next(); + } + } +} + +#if defined(TEST_CLASS) +# include "vchain.tcp" +#endif diff --git a/CODE/RP/MUNGA/VCHAIN.HPP b/CODE/RP/MUNGA/VCHAIN.HPP new file mode 100644 index 0000000..db6091b --- /dev/null +++ b/CODE/RP/MUNGA/VCHAIN.HPP @@ -0,0 +1,631 @@ +//===========================================================================// +// File: vchain.hh // +// Project: MUNGA Brick: Connection Library // +// Contents: Interface specification of VChain class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/02/94 ECH Initial coding. // +// 12/12/94 ECH Changed release handling // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(VCHAIN_HPP) +# define VCHAIN_HPP + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(SRTSKT_HPP) +# include +# endif + +# if !defined(MEMBLOCK_HPP) +# include +# endif + + class VChain; + class VChainIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class VChainLink: + public Link + { + friend class VChain; + friend class VChainIterator; + + public: + ~VChainLink(); + Logical + TestInstance() const; + + protected: + VChainLink( + VChain *vchain, + Plug *plug + ); + + private: + void + SetupVChainLinks( + VChainLink *next, + VChainLink *prev + ); + + VChainLink *next; + VChainLink *prev; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLinkOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define VCHAINLINK_MEMORYBLOCK_ALLOCATION (100) + + template class VChainLinkOf: + public VChainLink + { + public: + VChainLinkOf( + VChain *vchain, + Plug *plug, + const V &value + ); + ~VChainLinkOf(); + + void* + operator new(size_t); + void + operator delete(void *where); + + V + GetValue() + {return value;} + V* + GetValuePointer() + {return &value;} + + private: + static MemoryBlock + *allocatedMemory; + static CollectionSize + allocationCount; + + V value; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLinkOf templates ~~~~~~~~~~~~~~~~~~~~~~~~ + + template MemoryBlock* + VChainLinkOf::allocatedMemory = NULL; + template CollectionSize + VChainLinkOf::allocationCount = 0; + + template + VChainLinkOf::VChainLinkOf( + VChain *vchain, + Plug *plug, + const V &value + ): + VChainLink(vchain, plug) + { + this->value = value; + } + + template + VChainLinkOf::~VChainLinkOf() + { + } + + #if 0 + template void* + VChainLinkOf::operator new(size_t) + { + if (allocatedMemory == NULL) + { + allocatedMemory = + new MemoryBlock( + sizeof(VChainLinkOf), + VCHAINLINK_MEMORYBLOCK_ALLOCATION, + VCHAINLINK_MEMORYBLOCK_ALLOCATION + ); + } + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void + VChainLinkOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + } + #else + template void* + VChainLinkOf::operator new(size_t) + { + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = + new MemoryBlock( + sizeof(VChainLinkOf), + VCHAINLINK_MEMORYBLOCK_ALLOCATION, + VCHAINLINK_MEMORYBLOCK_ALLOCATION, + "VChainLinkOf" + ); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void + VChainLinkOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); + } + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class VChain: + public SortedSocket + { + friend class VChainLink; + friend class VChainIterator; + + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructor, Destructor and testing + //-------------------------------------------------------------------- + // + VChain( + Node *node, + Logical has_unique_entries + ); + ~VChain(); + + Logical + TestInstance() const; + static Logical + TestClass(); + static Logical + ProfileClass(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + AddImplementation(Plug *); + void + AddValueImplementation( + Plug *plug, + const void *value + ); + Plug + *FindImplementation(const void *value); + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + virtual VChainLink + *MakeVChainLink( + Plug *plug, + const void *value + ); + virtual int + CompareVChainLinks( + VChainLink *link1, + VChainLink *link2 + ); + virtual int + CompareValueToVChainLink( + const void *value, + VChainLink *link + ); + + VChainLink* + SearchForValue(const void *value); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + VChainLink *head; + VChainLink *tail; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define VCHAIN_MEMORYBLOCK_ALLOCATION (100) + + template class VChainOf: + public VChain + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + VChainOf( + Node *node, + Logical has_unique_entries + ); + ~VChainOf(); + + void* + operator new(size_t); + void + operator delete(void *where); + + // + //-------------------------------------------------------------------- + // Socket methods (see Socket for full listing) + //-------------------------------------------------------------------- + // + void + AddValue( + T plug, + const V &value + ) + {AddValueImplementation(Cast_Object(Plug*,plug), &value);} + T + Find(const V &value) + {return (T)FindImplementation(&value);} + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + VChainLink + *MakeVChainLink( + Plug *plug, + const void *value + ) + {return new VChainLinkOf(this, plug, *(V*)value);} + int + CompareVChainLinks( + VChainLink *link1, + VChainLink *link2 + ); + int + CompareValueToVChainLink( + const void *value, + VChainLink *link + ); + + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + static MemoryBlock + *allocatedMemory; + static CollectionSize + allocationCount; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template MemoryBlock* + VChainOf::allocatedMemory = NULL; + template CollectionSize + VChainOf::allocationCount = 0; + + template + VChainOf::VChainOf( + Node *node, + Logical has_unique_entries + ): + VChain( + node, + has_unique_entries + ) + { + } + + template + VChainOf::~VChainOf() + { + } + + template int + VChainOf::CompareVChainLinks( + VChainLink *node1, + VChainLink *node2 + ) + { + V *ptr1 = Cast_Object(VChainLinkOf*, node1)->GetValuePointer(); + V *ptr2 = Cast_Object(VChainLinkOf*, node2)->GetValuePointer(); + + Check_Pointer(ptr1); + Check_Pointer(ptr2); + + if (*ptr1 == *ptr2) + return 0; + else + return ((*ptr1 > *ptr2) ? 1 : -1); + } + + template int + VChainOf::CompareValueToVChainLink( + const void *value, + VChainLink *node + ) + { + Check_Pointer(value); + + V *ptr = Cast_Object(VChainLinkOf*, node)->GetValuePointer(); + Check_Pointer(ptr); + + if (*(V*)value == *ptr) + return 0; + else + return (*(V*)value > *ptr) ? 1 : -1; + } + + #if 0 + template void* + VChainOf::operator new(size_t) + { + if (allocatedMemory == NULL) + { + allocatedMemory = + new MemoryBlock( + sizeof(VChainOf), + VCHAIN_MEMORYBLOCK_ALLOCATION, + VCHAIN_MEMORYBLOCK_ALLOCATION + ); + } + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void + VChainOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + } + #else + template void* + VChainOf::operator new(size_t) + { + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = + new MemoryBlock( + sizeof(VChainOf), + VCHAIN_MEMORYBLOCK_ALLOCATION, + VCHAIN_MEMORYBLOCK_ALLOCATION, + "VChainOf" + ); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void + VChainOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); + } + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class VChainIterator: + public SortedIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors, Destructor and testing + //-------------------------------------------------------------------- + // + VChainIterator(VChain *vchain); + VChainIterator(const VChainIterator *iterator); + ~VChainIterator(); + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + void + First(); + void + Last(); + void + Next(); + void + Previous(); + CollectionSize + GetSize(); + void + Remove(); + + protected: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Protected interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void* + ReadAndNextImplementation(); + void* + ReadAndPreviousImplementation(); + void* + GetCurrentImplementation(); + void* + GetNthImplementation( + CollectionSize index + ); + Plug* + FindImplementation(const void *value); + + protected: + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + VChainLink + *currentLink; + + private: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Private interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + void + ReceiveMemo( + IteratorMemo memo, + void *content + ); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class VChainIteratorOf: + public VChainIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors and Destructor + //-------------------------------------------------------------------- + // + VChainIteratorOf(VChainOf *vchain); + VChainIteratorOf(VChainOf &vchain); + VChainIteratorOf(const VChainIteratorOf &iterator); + ~VChainIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T + ReadAndNext() + {return (T)ReadAndNextImplementation();} + T + ReadAndPrevious() + {return (T)ReadAndPreviousImplementation();} + T + GetCurrent() + {return (T)GetCurrentImplementation();} + T + GetNth(CollectionSize index) + {return (T)GetNthImplementation(index);} + T + Find(const V &value) + {return (T)FindImplementation(&value);} + V + GetValue() + {return Cast_Object(VChainLinkOf*, currentLink)->GetValue();} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + VChainIteratorOf::VChainIteratorOf(VChainOf *vchain): + VChainIterator(vchain) + { + } + + template + VChainIteratorOf::VChainIteratorOf(VChainOf &vchain): + VChainIterator(&vchain) + { + } + + template + VChainIteratorOf::VChainIteratorOf( + const VChainIteratorOf &iterator + ): + VChainIterator(&iterator) + { + } + + template + VChainIteratorOf::~VChainIteratorOf() + { + } + +#endif diff --git a/CODE/RP/MUNGA/VCHAIN.TCP b/CODE/RP/MUNGA/VCHAIN.TCP new file mode 100644 index 0000000..9544a72 --- /dev/null +++ b/CODE/RP/MUNGA/VCHAIN.TCP @@ -0,0 +1,531 @@ +//===========================================================================// +// File: vchain.tst // +// Project: MUNGA Brick: Connection Library // +// Contents: test routines for VChain class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/02/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "time.hpp" + +class VChainTestPlug: + public Plug +{ +public: + int value; + + VChainTestPlug(int value); + ~VChainTestPlug(); +}; + +class VChainTestNode: + public Node +{ +public: + VChainOf vchain1; + VChainOf vchain2; + + VChainTestNode(); + ~VChainTestNode(); + + void RunProfile(); + void RunTest(); +}; + +#define RandInt(x) (rand() % x + 1) + +VChainTestPlug::VChainTestPlug(int value) +{ + this->value = value; +} + +VChainTestPlug::~VChainTestPlug() +{ +} + +VChainTestNode::VChainTestNode(): + vchain1(this, True), vchain2(this, True) +{ +} + +VChainTestNode::~VChainTestNode() +{ +} + +// +//########################################################################### +// ProfileClass +//########################################################################### +// + +Logical + VChain::ProfileClass() +{ + VChainTestNode testNode; + Time startTicks = Now(); + + Test_Message("VChain::ProfileClass\n"); + + testNode.RunProfile(); + + Test_Message("VChain::ProfileClass elapsed = " << (Now() - startTicks) << endl); + return True; +} + +// +//########################################################################### +// TestClass +//########################################################################### +// + +Logical + VChain::TestClass() +{ + DEBUG_STREAM << "Starting VChain test...\n"; + + VChainTestNode testNode; + + testNode.RunTest(); + return True; +} + +void + VChainTestNode::RunProfile() +{ + VChainTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; + Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Run timing tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + startTicks = Now(); + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new VChainTestPlug(values[i]); + Register_Object(testPlug1); + vchain1.AddValue(testPlug1, values[i]); + vchain2.AddValue(testPlug1, values[i]); + } + Test_Message("VChainTestNode::RunTest Create = " << (Now() - startTicks) << endl); + + /* + * Iterate over both sockets + */ + startTicks = Now(); + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator2.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + } + Verify( i == TEST_CLASS ); + } + Test_Message("VChainTestNode::RunTest Iterate = " << (Now() - startTicks) << endl); + + /* + * Find + */ + startTicks = Now(); + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = iterator1.Find(i); + testPlug2 = iterator2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + Verify( testPlug1 == testPlug2 ); + } + } + Test_Message("VChainTestNode::RunTest Find = " << (Now() - startTicks) << endl); + + /* + * Destroy from vchain1, verify with vchain2 + */ + startTicks = Now(); + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + i++; + + Unregister_Object( testPlug1 ); + delete(testPlug1); + } + Verify( i == TEST_CLASS ); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + Test_Message("VChainTestNode::RunTest Destroy = " << (Now() - startTicks) << endl); +} + +void + VChainTestNode::RunTest() +{ + VChainTestPlug *testPlug1, *testPlug2; + int values[TEST_CLASS]; + int i, j; +// Time startTicks; + + /* + * Generate unique values, shuffle them + */ + for (i = 0; i < TEST_CLASS; i++) { + values[i] = i; + } + for (i = 0; i < TEST_CLASS; i++) { + int tmp; + + j = i + RandInt(TEST_CLASS - i) - 1; + tmp = values[j]; + values[j] = values[i]; + values[i] = tmp; + } + + // + //-------------------------------------------------------------------- + // Stress tests + //-------------------------------------------------------------------- + // + + /* + * Create plugs and add to both sockets + */ + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new VChainTestPlug(values[i]); + Register_Object( testPlug1 ); + vchain1.AddValue(testPlug1, values[i]); + vchain2.AddValue(testPlug1, values[i]); + } + + /* + * Find + */ + { + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = vchain1.Find(i); + testPlug2 = vchain2.Find(i); + + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + Verify( testPlug1 == testPlug2 ); + } + } + + /* + * Test first and last + */ + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + iterator1.First(); + iterator2.First(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + Verify( testPlug1 == iterator1.GetNth(0) ); + Verify( testPlug1 == iterator2.GetNth(0) ); + + iterator1.Last(); + iterator2.Last(); + + testPlug1 = iterator1.GetCurrent(); + testPlug2 = iterator2.GetCurrent(); + Check( testPlug1 ); + Check( testPlug2 ); + + Verify( testPlug1 == testPlug2 ); + Verify( testPlug1 == iterator1.GetNth(TEST_CLASS - 1) ); + Verify( testPlug1 == iterator2.GetNth(TEST_CLASS - 1) ); + } + + /* + * Test next and prev + */ + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + iterator1.Next(); + iterator2.Next(); + + i++; + } + Verify( i == TEST_CLASS ); + + iterator1.Last(); + iterator2.Last(); + + i = TEST_CLASS-1; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + testPlug2 = iterator2.GetCurrent(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + iterator1.Previous(); + iterator2.Previous(); + + i--; + } + Verify( i == -1 ); + } + + /* + * Test read next and read prev + */ + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.ReadAndNext()) != NULL) + { + testPlug2 = iterator2.ReadAndNext(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + i++; + } + Verify( i == TEST_CLASS ); + + iterator1.Last(); + iterator2.Last(); + + i = TEST_CLASS-1; + while ((testPlug1 = iterator1.ReadAndPrevious()) != NULL) + { + testPlug2 = iterator2.ReadAndPrevious(); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + + i--; + } + Verify( i == -1 ); + } + + /* + * Test nth + */ + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + for ( + i = 0; + i < TEST_CLASS; + i++ + ) + { + testPlug1 = iterator1.GetNth((int)i); + testPlug2 = iterator2.GetNth((int)i); + + Check( testPlug1 ); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Verify( testPlug1->value == i ); + Verify( testPlug2->value == i ); + } + } + + /* + * Test Remove + */ + { + VChainIteratorOf iterator1(&vchain1); + VChainIteratorOf iterator2(&vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while ((testPlug1 = iterator1.GetCurrent()) != NULL) + { + Check( testPlug1 ); + Verify( testPlug1->value == i ); + + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(0); + + Check( testPlug2 ); + Verify( testPlug2->value == i ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + i++; + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } + + /* + * Test random deletion + */ + { + /* + * Add plugs to both sockets + */ + VChainIteratorOf iterator1(vchain1); + VChainIteratorOf iterator2(vchain2); + + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + + for (i = 0; i < TEST_CLASS; i++) + { + testPlug1 = new VChainTestPlug(values[i]); + Register_Object( testPlug1 ); + vchain1.AddValue(testPlug1, values[i]); + vchain2.AddValue(testPlug1, values[i]); + } + } + + { + /* + * Perform random deletion + */ + int size, index; + VChainIteratorOf iterator1(vchain1); + VChainIteratorOf iterator2(vchain2); + + Verify( iterator1.GetSize() == TEST_CLASS ); + Verify( iterator2.GetSize() == TEST_CLASS ); + + i = 0; + while((size = iterator1.GetSize()) != 0) + { + index = RandInt(size) - 1; + testPlug1 = iterator1.GetNth(index); + Check( testPlug1 ); + iterator1.Remove(); + + testPlug2 = iterator2.GetNth(index); + Check( testPlug2 ); + Verify( testPlug1 == testPlug2 ); + + Unregister_Object( testPlug2 ); + delete(testPlug2); + + i++; + } + Verify( i == TEST_CLASS ); + Verify( iterator1.GetSize() == 0 ); + Verify( iterator2.GetSize() == 0 ); + } +} diff --git a/CODE/RP/MUNGA/VDATA.CPP b/CODE/RP/MUNGA/VDATA.CPP new file mode 100644 index 0000000..819479f --- /dev/null +++ b/CODE/RP/MUNGA/VDATA.CPP @@ -0,0 +1,158 @@ +//===========================================================================// +// File: vdata.cc // +// Project: MUNGA Brick: Connection Library // +// Contents: Implementation details for registered classes and virtual data // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 11/03/94 ECH Initial coding. // +// 11/03/94 ECH Made compatible with BC4.0 // +// 11/08/94 ECH Made compatible with BC4.0 // +// 11/29/94 JMA Changed ClassIdentity to ClassID // +// 11/30/94 JMA Adapted to style changes // +// 12/01/94 JMA Made compatible with SGI CC // +// 12/12/94 ECH Changed class id access // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(VDATA_HPP) + #include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +//############################################################################# +//####################### RegisteredClass ############################### +//############################################################################# + +// +//############################################################################# +// RegisteredClass +//############################################################################# +// +RegisteredClass::RegisteredClass(ClassID class_id) +{ + classID = class_id; +} + +// +//############################################################################# +// ~RegisteredClass +//############################################################################# +// +RegisteredClass::~RegisteredClass() +{ +} + +// +//############################################################################# +// RegisteredClass +//############################################################################# +// +RegisteredClass::RegisteredClass(ObjectStream *stream) +{ + ObjectID object_ID; + + MemoryStream_Read(stream, &classID); + Verify(classID != NullClassID); + MemoryStream_Read(stream, &object_ID); +} + +// +//############################################################################# +// BuildFromPage +//############################################################################# +// +void + RegisteredClass::BuildFromPage( + ObjectStream *stream, + NameList*, + ClassID class_ID, + ObjectID object_ID + ) +{ + *stream << class_ID << object_ID; +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + RegisteredClass::TestInstance() const +{ + return True; +} + +// +//############################################################################# +// GetClassID +//############################################################################# +// +RegisteredClass::ClassID + RegisteredClass::GetClassID(const CString &class_name_string) +{ + // + //-------------------------------------------------------------------------- + // HACK - Class name lookup could be perfromed via registration, for now, + // use if statements + //-------------------------------------------------------------------------- + // + #define COMPARE_AND_RETURN(class_name)\ + if (!strcmp(class_name_string, #class_name))\ + return class_name##ClassID; + + COMPARE_AND_RETURN(AudioStateTrigger); + COMPARE_AND_RETURN(AudioMotionScale); + COMPARE_AND_RETURN(AudioRenderer); + COMPARE_AND_RETURN(AudioLocation); + COMPARE_AND_RETURN(AudioMotionTrigger); + COMPARE_AND_RETURN(AudioControlMixer); + COMPARE_AND_RETURN(AudioHingeScale); + COMPARE_AND_RETURN(AudioControlSmoother); + COMPARE_AND_RETURN(AudioResourceSelector); + COMPARE_AND_RETURN(L4AudioCollisionTrigger); + COMPARE_AND_RETURN(AudioResourceIndex); + COMPARE_AND_RETURN(AudioScalarScale); + COMPARE_AND_RETURN(AudioControlSend); + COMPARE_AND_RETURN(L4AudioLocation); + COMPARE_AND_RETURN(DirectPatchSource); + COMPARE_AND_RETURN(Dynamic3DPatchSource); + COMPARE_AND_RETURN(PatchResource); + COMPARE_AND_RETURN(Static3DPatchSource); + COMPARE_AND_RETURN(AudioControlMultiplier); + COMPARE_AND_RETURN(AudioSampleAndHold); + COMPARE_AND_RETURN(AudioScalarTrigger); + COMPARE_AND_RETURN(AudioEnumerationTrigger); + COMPARE_AND_RETURN(AudioIntegerTrigger); + COMPARE_AND_RETURN(AudioLogicalTrigger); + COMPARE_AND_RETURN(AudioControlsButtonTrigger); + COMPARE_AND_RETURN(ExplosionResourceTable); + COMPARE_AND_RETURN(AudioIdleWatcher); + COMPARE_AND_RETURN(AudioControlEvent); + COMPARE_AND_RETURN(AudioControlSequence); + COMPARE_AND_RETURN(AudioControlSplitter); + COMPARE_AND_RETURN(AudioLFO); + COMPARE_AND_RETURN(AudioEnumerationDeltaTrigger); + COMPARE_AND_RETURN(AudioScalarDeltaTrigger); + COMPARE_AND_RETURN(AudioLevelOfDetail); + COMPARE_AND_RETURN(PatchLevelOfDetail); + COMPARE_AND_RETURN(AudioMessageWatcher); + COMPARE_AND_RETURN(AudioControlsButtonMessageWatcher); + + // + // Etc... + // + + return NullClassID; +} + diff --git a/CODE/RP/MUNGA/VECTOR3D.CPP b/CODE/RP/MUNGA/VECTOR3D.CPP new file mode 100644 index 0000000..0f3ee41 --- /dev/null +++ b/CODE/RP/MUNGA/VECTOR3D.CPP @@ -0,0 +1,479 @@ +//===========================================================================// +// File: vector3d.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(VECTOR3D_HPP) + #include +#endif + +#if !defined(LINMTRX_HPP) + #include +#endif + +#if !defined(CSTR_HPP) + #include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AbstractVector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile AbstractVector3D *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +AbstractVector3D& + AbstractVector3D::operator=(const AbstractVector3D &vector) +{ + Check_Pointer(this); + Check(&vector); + + x = vector.x; + y = vector.y; + z = vector.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Small_Enough(const AbstractVector3D &V,Scalar e) +{ + Check(&V); + return + Small_Enough(V.x,e) + && Small_Enough(V.y,e) + && Small_Enough(V.z,e); +} + +// +//########################################################################### +//########################################################################### +// +Logical + Close_Enough( + const AbstractVector3D &V1, + const AbstractVector3D &V2, + Scalar e + ) +{ + Check(&V1); + Check(&V2); + return + Close_Enough(V1.x,V2.x,e) + && Close_Enough(V1.y,V2.y,e) + && Close_Enough(V1.z,V2.z,e); +} + +// +//########################################################################### +//########################################################################### +// +Logical + AbstractVector3D::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const Vector3D + Vector3D::Identity(0.0f,0.0f,0.0f); + +// +//########################################################################### +//########################################################################### +// +inline Vector3D& + Vector3D::operator=(const LBE3Vector3D &vector) +{ + Check_Pointer(this); + Check(&vector); + + x = vector.x; + y = vector.z; + z = vector.y; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +inline Vector3D& + Vector3D::operator=(const TIVector3D &vector) +{ + Check_Pointer(this); + Check(&vector); + + x = vector.x; + y = vector.y; + z = -vector.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Negate(const Vector3D &V) +{ + Check_Pointer(this); + Check(&V); + x = -V.x; + y = -V.y; + z = -V.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Add( + const Vector3D& V1, + const Vector3D& V2 + ) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + x = V1.x + V2.x; + y = V1.y + V2.y; + z = V1.z + V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::AddScaled( + const Vector3D& V1, + const Vector3D& V2, + Scalar scale + ) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x + V2.x*scale; + y = V1.y + V2.y*scale; + z = V1.z + V2.z*scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Subtract(const Vector3D& V1,const Vector3D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + x = V1.x - V2.x; + y = V1.y - V2.y; + z = V1.z - V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Cross(const Vector3D& v1,const Vector3D& v2) +{ + Check_Pointer(this); + Check(&v1); + Check(&v2); + + Verify(this != &v1); + Verify(this != &v2); + + x = v1.y*v2.z - v1.z*v2.y; + y = v1.z*v2.x - v1.x*v2.z; + z = v1.x*v2.y - v1.y*v2.x; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Multiply(const Vector3D& V,Scalar Scale) +{ + Check_Pointer(this); + Check(&V); + x = V.x * Scale; + y = V.y * Scale; + z = V.z * Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Multiply(const Vector3D& V1,const Vector3D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + x = V1.x * V2.x; + y = V1.y * V2.y; + z = V1.z * V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Divide(const Vector3D& V,Scalar Scale) +{ + Check_Pointer(this); + Check(&V); + Verify(!Small_Enough(Scale)); + x = V.x / Scale; + y = V.y / Scale; + z = V.z / Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Divide(const Vector3D& V1,const Vector3D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + Verify(!Small_Enough(V2.x)); + Verify(!Small_Enough(V2.y)); + Verify(!Small_Enough(V2.z)); + x = V1.x / V2.x; + y = V1.y / V2.y; + z = V1.z / V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Multiply(const Vector3D& v,const AffineMatrix& m) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + Verify(this != &v); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::MultiplyByInverse( + const Vector3D& v, + const LinearMatrix& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + Verify(this != &v); + + x = v.x*m(0,0) + v.y*m(0,1) + v.z*m(0,2); + y = v.x*m(1,0) + v.y*m(1,1) + v.z*m(1,2); + z = v.x*m(2,0) + v.y*m(2,1) + v.z*m(2,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Normalize(const Vector3D &V) +{ + Check(this); + Scalar len = V.Length(); + Verify(len); + + x = V.x / len; + y = V.y / len; + z = V.z / len; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& + Vector3D::Combine( + const Vector3D& V1, + Scalar t1, + const Vector3D& V2, + Scalar t2 + ) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = t1*V1.x + t2*V2.x; + y = t1*V1.y + t2*V2.y; + z = t1*V1.z + t2*V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator<<(ostream& Stream, const Vector3D& V) +{ + Check(&V); + return Stream << setprecision(4) << '<' << V.x << ',' + << V.y << ',' << V.z << '>'; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +void + Convert_From_Ascii( + const char *str, + Vector3D *vector_3D + ) +{ + Check_Pointer(str); + Check_Signature(vector_3D); + + CString parse_string(str); + + Check_Pointer(parse_string.GetNthToken(0)); + vector_3D->x = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + vector_3D->y = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + vector_3D->z = atof(parse_string.GetNthToken(2)); + + Check(vector_3D); +} + +// +//########################################################################### +//########################################################################### +// +LBE3Vector3D& + LBE3Vector3D::operator=(const Vector3D& vector) +{ + Check_Pointer(this); + Check(&vector); + + x = vector.x; + y = vector.z; + z = vector.y; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LBE3Vector3D& + LBE3Vector3D::operator=(const TIVector3D &vector) +{ + Check_Pointer(this); + Check(&vector); + + x = vector.x; + y = -vector.z; + z = vector.y; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +TIVector3D& + TIVector3D::operator=(const Vector3D &vector) +{ + Check_Pointer(this); + Check(&vector); + + x = vector.x; + y = vector.y; + z = -vector.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +TIVector3D& + TIVector3D::operator=(const LBE3Vector3D &vector) +{ + Check_Pointer(this); + Check(&vector); + + x = vector.x; + y = vector.z; + z = -vector.y; + return *this; +} + +#if defined(TEST_CLASS) +# include "vector3d.tcp" +#endif + diff --git a/CODE/RP/MUNGA/VECTOR3D.HPP b/CODE/RP/MUNGA/VECTOR3D.HPP new file mode 100644 index 0000000..a50635e --- /dev/null +++ b/CODE/RP/MUNGA/VECTOR3D.HPP @@ -0,0 +1,421 @@ +//===========================================================================// +// File: vector3d.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(VECTOR3D_HPP) +# define VECTOR3D_HPP + +# if !defined(MEMSTRM_HPP) +# include +# endif + +# if !defined(SCALAR_HPP) +# include +# endif + + class AbstractVector3D; + class Vector3D; + class LBE3Vector3D; + class TIVector3D; + class AffineMatrix; + class LinearMatrix; + class Matrix4x4; + class Point3D; + + enum Axes { + X_Axis, + Y_Axis, + Z_Axis, + W_Axis + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ AbstractVector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AbstractVector3D + { + public: + Scalar + x, + y, + z; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile AbstractVector3D *p); + #endif + + // + // Assignment operators + // + AbstractVector3D& + operator=(const AbstractVector3D& v); + + // + // "Close-enough" comparators + // + friend Logical + Small_Enough( + const AbstractVector3D &v, + Scalar e=SMALL + ); + Logical + operator!() const + {return Small_Enough(*this, SMALL);} + + friend Logical + Close_Enough( + const AbstractVector3D &v1, + const AbstractVector3D &v2, + Scalar e=SMALL + ); + Logical + operator==(const AbstractVector3D& v) const + {return Close_Enough(*this,v,SMALL);} + Logical + operator!=(const AbstractVector3D& v) const + {return !Close_Enough(*this,v,SMALL);} + + Logical + TestInstance() const; + + protected: + AbstractVector3D() + {} + AbstractVector3D( + Scalar x, + Scalar y, + Scalar z + ): + x(x), + y(y), + z(z) + {} + }; + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AbstractVector3D *output + ) + {return stream->ReadBytes(output, sizeof(*output));} + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AbstractVector3D *input + ) + {return stream->WriteBytes(input, sizeof(*input));} + + class LBE3Vector3D; + class TIVector3D; + class AffineMatrix; + class LinearMatrix; + class Matrix4x4; + class Point3D; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Vector3D: + public AbstractVector3D + { + public: + static const Vector3D + Identity; + + // + // Constructors + // + Vector3D() + {} + Vector3D( + Scalar x, + Scalar y, + Scalar z + ): + AbstractVector3D(x,y,z) + {} + + // + // Assignment operators + // + Vector3D& + operator=(const Vector3D &vector) + { + Check_Pointer(this); Check(&vector); + AbstractVector3D::operator=(vector); return *this; + } + Vector3D& + operator=(const LBE3Vector3D &vector); + Vector3D& + operator=(const TIVector3D &vector); + + // Comparison operator (for sorting by length, GDU 1/26/96) + Logical + operator>(const Vector3D &v) const + { + Check(this); Check(&v); + return LengthSquared() > v.LengthSquared(); + } + Logical + operator<(const Vector3D &v) const + { + Check(this); Check(&v); + return LengthSquared() < v.LengthSquared(); + } + + // + // Indexing operations + // + const Scalar& + operator[](size_t index) const + {Check_Pointer(this); Warn(index>Z_Axis); return (&x)[index];} + Scalar& + operator[](size_t index) + {Check_Pointer(this); Warn(index>Z_Axis); return (&x)[index];} + + // + // The following operators all assume that this points to the destination + // of the operation results + // + Vector3D& + Negate(const Vector3D &v); + + Vector3D& + Add( + const Vector3D& v1, + const Vector3D& v2 + ); + Vector3D& + AddScaled( + const Vector3D& v1, + const Vector3D& v2, + Scalar scale + ); + Vector3D& + operator+=(const Vector3D& v) + {return Add(*this,v);} + + Vector3D& + Subtract( + const Vector3D& v1, + const Vector3D& v2 + ); + Vector3D& + operator-=(const Vector3D& v) + {return Subtract(*this,v);} + + Scalar + operator*(const Vector3D& v) const + {Check(this); Check(&v); return x*v.x + y*v.y + z*v.z;} + + Vector3D& + Cross( + const Vector3D& v1, + const Vector3D& v2 + ); + + Vector3D& + Multiply( + const Vector3D& v, + Scalar Scale + ); + Vector3D& + operator*=(Scalar v) + {return Multiply(*this,v);} + + Vector3D& + Multiply( + const Vector3D& v1, + const Vector3D& v2 + ); + Vector3D& + operator*=(const Vector3D &v) + {return Multiply(*this,v);} + + Vector3D& + Divide( + const Vector3D& v, + Scalar scale + ); + Vector3D& + operator/=(Scalar v) + {return Divide(*this,v);} + + Vector3D& + Divide( + const Vector3D& v1, + const Vector3D& v2 + ); + Vector3D& + operator/=(const Vector3D &v) + {return Divide(*this,v);} + + // + // Transform operators + // + Vector3D& + Multiply( + const Vector3D &v, + const AffineMatrix &m + ); + Vector3D& + operator*=(const AffineMatrix &m) + {Vector3D src(*this); return Multiply(src,m);} + Vector3D& + MultiplyByInverse( + const Vector3D &v, + const LinearMatrix &m + ); + + // + // Miscellaneous functions + // + Scalar + LengthSquared() const + {Check(this); return x*x + y*y + z*z;} + Scalar + Length() const + {return Sqrt(LengthSquared());} + + Vector3D& + Normalize(const Vector3D &v); + + Vector3D& + Combine( + const Vector3D& v1, + Scalar t1, + const Vector3D& v2, + Scalar t2 + ); + + // + // Template support + // + Vector3D& + Lerp( + const Vector3D& v1, + const Vector3D& v2, + Scalar t + ) + {return Combine(v1,1.0f-t,v2,t);} + + // + // Support functions + // + friend ostream& + operator<<( + ostream& stream, + const Vector3D& v + ); + static Logical + TestClass(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + void + Convert_From_Ascii( + const char *str, + Vector3D *vector_3D + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ LBE3Vector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class LBE3Vector3D: + public AbstractVector3D + { + public: + // + // Constructors + // + LBE3Vector3D() + {} + LBE3Vector3D( + Scalar x, + Scalar y, + Scalar z + ): + AbstractVector3D(x,y,z) + {} + + // + // Assignment operators + // + LBE3Vector3D& + operator=(const LBE3Vector3D &vector) + { + Check_Pointer(this); Check(&vector); + AbstractVector3D::operator=(vector); return *this; + } + LBE3Vector3D& + operator=(const Vector3D& vector); + LBE3Vector3D& + operator=(const TIVector3D &vector); + + // + // Support functions + // + friend ostream& + operator<<( + ostream &stream, + const LBE3Vector3D &vector + ); + static Logical + TestClass(); + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TIVector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class TIVector3D: + public AbstractVector3D + { + public: + // + // Constructors + // + TIVector3D() + {} + TIVector3D( + Scalar x, + Scalar y, + Scalar z + ): + AbstractVector3D(x,y,z) + {} + + // + // Assignment operators + // + TIVector3D& + operator=(const TIVector3D &vector) + { + Check_Pointer(this); Check(&vector); + AbstractVector3D::operator=(vector); return *this; + } + TIVector3D& + operator=(const Vector3D &vector); + TIVector3D& + operator=(const LBE3Vector3D &vector); + + // + // Support functions + // + friend ostream& + operator<<( + ostream &stream, + const TIVector3D &vector + ); + static Logical + TestClass(); + }; + +#endif diff --git a/CODE/RP/MUNGA/VECTOR3D.TCP b/CODE/RP/MUNGA/VECTOR3D.TCP new file mode 100644 index 0000000..1b758dc --- /dev/null +++ b/CODE/RP/MUNGA/VECTOR3D.TCP @@ -0,0 +1,185 @@ +//===========================================================================// +// File: vector.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Test code for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +// +//########################################################################### +//########################################################################### +// +Logical + Vector3D::TestClass() +{ + DEBUG_STREAM << "Starting Vector3D test...\n"; + + const Vector3D + a(Identity); + Vector3D + b; + const Vector3D + c(1.0f,2.0f,3.0f); + Vector3D + d(2.0f,3.0f,1.0f); + + Test(!a.x && !a.y && !a.z); + Test(c.x == 1.0f && c.y == 2.0f && c.z == 3.0f); + + Test(c[2] == c.z); + Test(a[1] == a.y); + + Test(Small_Enough(a)); + Test(!a); + + b = c; + Test(b.x == c.x && b.y == c.y && b.z == c.z); + Test(Close_Enough(b,c)); + Test(b == c); + Test(a != b); + + b.Negate(c); + Test(b == Vector3D(-c.x,-c.y,-c.z)); + + b.Add(c,d); + Test(b == Vector3D(c.x+d.x,c.y+d.y,c.z+d.z)); + b = c; + b += d; + Test(b == Vector3D(c.x+d.x,c.y+d.y,c.z+d.z)); + + b.Subtract(d,c); + Test(b == Vector3D(d.x-c.x,d.y-c.y,d.z-c.z)); + b = d; + b -= c; + Test(b == Vector3D(d.x-c.x,d.y-c.y,d.z-c.z)); + + Scalar f = c*d; + Test(f == c.x*d.x + c.y*d.y + c.z*d.z); + + b.Cross(c,d); + Test(b == Vector3D(c.y*d.z-c.z*d.y,c.z*d.x-c.x*d.z,c.x*d.y-c.y*d.x)); + + f = 2.0f; + b.Multiply(c,f); + Test(b == Vector3D(f*c.x,f*c.y,f*c.z)); + b = c; + b *= f; + Test(b == Vector3D(f*c.x,f*c.y,f*c.z)); + + b.Multiply(c,d); + Test(b == Vector3D(c.x*d.x,c.y*d.y,c.z*d.z)); + b = c; + b *= d; + Test(b == Vector3D(c.x*d.x,c.y*d.y,c.z*d.z)); + + b.Divide(c,f); + Test(b == Vector3D(c.x/f,c.y/f,c.z/f)); + b = c; + b /= f; + Test(b == Vector3D(c.x/f,c.y/f,c.z/f)); + + b.Divide(c,d); + Test(b == Vector3D(c.x/d.x,c.y/d.y,c.z/d.z)); + b = c; + b /= d; + Test(b == Vector3D(c.x/d.x,c.y/d.y,c.z/d.z)); + + AffineMatrix + m(True); + EulerAngles + r(PI_OVER_4,0.0f,0.0f); + m = r; + b.Multiply(c,m); + Test(b == Vector3D(c.x,c.y*m(1,1)+c.z*m(2,1),c.y*m(1,2)+c.z*m(2,2))); + b = c; + b *= m; + Test(b == Vector3D(c.x,c.y*m(1,1)+c.z*m(2,1),c.y*m(1,2)+c.z*m(2,2))); + + Test(!a.LengthSquared()); + f = c.LengthSquared(); + Test(f == c.x*c.x + c.y*c.y + c.z*c.z); + f = c.Length(); + Test(Close_Enough(f,Sqrt(c.x*c.x + c.y*c.y + c.z*c.z))); + b.Normalize(c); + Test(b == Vector3D(c.x/f, c.y/f, c.z/f)); + + b.Combine(c,2.0f,d,2.0f); + Test(b == Vector3D(2.0f*(c.x+d.x),2.0f*(c.y+d.y),2.0f*(c.z+d.z))); + + b.Lerp(c,d,0.5f); + Test(b == Vector3D(0.5f*(c.x+d.x),0.5f*(c.y+d.y),0.5f*(c.z+d.z))); + + LBE3Vector3D lbe3(1.0f,2.0f,3.0f); + TIVector3D ti(1.0f,2.0f,3.0f); + + b = lbe3; + Test(b == Vector3D(lbe3.x,lbe3.z,lbe3.y)); + b = ti; + Test(b == Vector3D(ti.x,ti.y,-ti.z)); + + return True; +} + +// +//########################################################################### +//########################################################################### +// +Logical + LBE3Vector3D::TestClass() +{ + DEBUG_STREAM << "Starting LBE3Vector3D test...\n"; + + const LBE3Vector3D + a(1.0f,2.0f,3.0f); + LBE3Vector3D + b; + + b = a; + Test(b == a); + + Vector3D v(1.0f,2.0f,3.0f); + b = v; + Test(b == LBE3Vector3D(v.x,v.z,v.y)); + + TIVector3D ti(1.0f,2.0f,3.0f); + b = ti; + Test(b == LBE3Vector3D(ti.x, -ti.z, ti.y)); + + return True; +} + +// +//########################################################################### +//########################################################################### +// +Logical + TIVector3D::TestClass() +{ + DEBUG_STREAM << "Starting TIVector3D test...\n"; + + const TIVector3D + a(1.0f,2.0f,3.0f); + TIVector3D + b; + + b = a; + Test(b == a); + + Vector3D v(1.0f,2.0f,3.0f); + b = v; + Test(b == TIVector3D(v.x,v.y,-v.z)); + + LBE3Vector3D lbe3(1.0f,2.0f,3.0f); + b = lbe3; + Test(b == TIVector3D(lbe3.x, lbe3.z, -lbe3.y)); + + return True; +} + diff --git a/CODE/RP/MUNGA/VECTOR4D.CPP b/CODE/RP/MUNGA/VECTOR4D.CPP new file mode 100644 index 0000000..377eec4 --- /dev/null +++ b/CODE/RP/MUNGA/VECTOR4D.CPP @@ -0,0 +1,393 @@ +//===========================================================================// +// File: vector4d.cc // +// Project: MUNGA Brick: Math Library // +// Contents: Implementation details for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(VECTOR4D_HPP) + #include +#endif + +#if !defined(MATRIX_HPP) +# include +#endif + +#if !defined(POINT3D_HPP) +# include +#endif + +#if !defined(AFFNMTRX_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector4D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const Vector4D + Vector4D::Identity(0.0f,0.0f,0.0f,0.0f); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Vector4D *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::operator=(const Vector4D &v) +{ + Check_Pointer(this); + Check(&v); + + x = v.x; + y = v.y; + z = v.z; + w = v.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::operator=(const Vector3D &v) +{ + Check_Pointer(this); + Check(&v); + + x = v.x; + y = v.y; + z = v.z; + w = 0.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::operator=(const Point3D &p) +{ + Check_Pointer(this); + Check(&p); + + x = p.x; + y = p.y; + z = p.z; + w = 1.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Small_Enough(const Vector4D &V,Scalar e) +{ + Check(&V); + return + Small_Enough(V.x,e) + && Small_Enough(V.y,e) + && Small_Enough(V.z,e) + && Small_Enough(V.w,e); +} + +// +//########################################################################### +//########################################################################### +// +Logical + Close_Enough(const Vector4D &V1, const Vector4D &V2, Scalar e) +{ + Check(&V1); + Check(&V2); + return + Close_Enough(V1.x,V2.x,e) + && Close_Enough(V1.y,V2.y,e) + && Close_Enough(V1.z,V2.z,e) + && Close_Enough(V1.w,V2.w,e); +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Negate(const Vector4D &V) +{ + Check_Pointer(this); + Check(&V); + + x = -V.x; + y = -V.y; + z = -V.z; + w = -V.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Add(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x + V2.x; + y = V1.y + V2.y; + z = V1.z + V2.z; + w = V1.w + V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Subtract(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x - V2.x; + y = V1.y - V2.y; + z = V1.z - V2.z; + w = V1.w - V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply(const Vector4D& V,Scalar Scale) +{ + Check_Pointer(this); + Check(&V); + + x = V.x * Scale; + y = V.y * Scale; + z = V.z * Scale; + w = V.w * Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x * V2.x; + y = V1.y * V2.y; + z = V1.z * V2.z; + w = V1.w * V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Divide(const Vector4D& V,Scalar Scale) +{ + Check_Pointer(this); + Check(&V); + Verify(!Small_Enough(Scale)); + + x = V.x / Scale; + y = V.y / Scale; + z = V.z / Scale; + w = V.w / Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Divide(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + Verify(!Small_Enough(V1.x)); + Verify(!Small_Enough(V1.y)); + Verify(!Small_Enough(V1.z)); + Verify(!Small_Enough(V1.w)); + + x = V1.x / V2.x; + y = V1.y / V2.y; + z = V1.z / V2.z; + w = V1.w / V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Vector4D& v, + const AffineMatrix& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + Verify(this != &v); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0) + v.w*m(3,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1) + v.w*m(3,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2) + v.w*m(3,2); + w = v.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Vector4D& v, + const Matrix4x4& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + Verify(this != &v); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0) + v.w*m(3,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1) + v.w*m(3,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2) + v.w*m(3,2); + w = v.x*m(0,3) + v.y*m(1,3) + v.z*m(2,3) + v.w*m(3,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Vector3D& v, + const Matrix4x4& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2); + w = v.x*m(0,3) + v.y*m(1,3) + v.z*m(2,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Point3D& v, + const Matrix4x4& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0) + m(3,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1) + m(3,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2) + m(3,2); + w = v.x*m(0,3) + v.y*m(1,3) + v.z*m(2,3) + m(3,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Combine( + const Vector4D& V1, + Scalar t1, + const Vector4D& V2, + Scalar t2 + ) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x*t1 + V2.x*t2; + y = V1.y*t1 + V2.y*t2; + z = V1.z*t1 + V2.z*t2; + w = V1.w*t1 + V2.w*t2; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +ostream& + operator<<(ostream& Stream, const Vector4D& V) +{ + Check(&V); + return Stream << setprecision(4) << '<' << V.x << ',' + << V.y << ',' << V.z << ',' << V.w << '>'; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Vector4D::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) +# include "vector4d.tcp" +#endif + + diff --git a/CODE/RP/MUNGA/VECTOR4D.HPP b/CODE/RP/MUNGA/VECTOR4D.HPP new file mode 100644 index 0000000..4d40d8e --- /dev/null +++ b/CODE/RP/MUNGA/VECTOR4D.HPP @@ -0,0 +1,229 @@ +//===========================================================================// +// File: vector4d.hh // +// Project: MUNGA Brick: Math Library // +// Contents: Interface specification for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(VECTOR4D_HPP) +# define VECTOR4D_HPP + +# if !defined(SCALAR_HPP) +# include +# endif + + class Vector3D; + class Point3D; + class AffineMatrix; + class Matrix4x4; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector4D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class Vector4D + { + public: + Scalar + x, + y, + z, + w; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Vector4D *); + #endif + + static const Vector4D + Identity; + + // + // Constructors + // + Vector4D() + {} + Vector4D( + Scalar X, + Scalar Y, + Scalar Z, + Scalar W) + {x=X; y=Y; z=Z; w=W;} + + // + // Assignment operators + // + Vector4D& + operator=(const Vector4D &v); + Vector4D& + operator=(const Vector3D &v); + Vector4D& + operator=(const Point3D &p); + + // + // Index operators + // + const Scalar& + operator[](size_t index) const + {Check_Pointer(this); Warn(index>W_Axis); return (&x)[index];} + Scalar& + operator[](size_t index) + {Check_Pointer(this); Warn(index>W_Axis); return (&x)[index];} + + friend Logical + Small_Enough(const Vector4D &v,Scalar e=SMALL); + Logical + operator!() const + {return Small_Enough(*this);} + + // + // "Close-enough" comparison operators + // + friend Logical + Close_Enough( + const Vector4D &v1, + const Vector4D &v2, + Scalar e=SMALL + ); + Logical + operator==(const Vector4D& v) const + {return Close_Enough(*this,v);} + Logical + operator!=(const Vector4D& v) const + {return !Close_Enough(*this,v);} + + // + // The following operators all assume that this points to the destination + // of the operation results + // + Vector4D& + Negate(const Vector4D &v); + + Vector4D& + Add( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator+=(const Vector4D& v) + {return Add(*this,v);} + + Vector4D& + Subtract( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator-=(const Vector4D& v) + {return Subtract(*this,v);} + + Scalar + operator*(const Vector4D& v) const + {Check(this); return x*v.x + y*v.y + z*v.z + w*v.w;} + + Vector4D& + Multiply( + const Vector4D& v, + Scalar scale + ); + Vector4D& + operator*=(Scalar v) + {return Multiply(*this,v);} + + Vector4D& + Multiply( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator*=(const Vector4D &v) + {return Multiply(*this,v);} + + Vector4D& + Divide( + const Vector4D& v, + Scalar scale + ); + Vector4D& + operator/=(Scalar v) + {return Divide(*this,v);} + + Vector4D& + Divide( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator/=(const Vector4D &v) + {return Divide(*this,v);} + + // + // Transforms + // + Vector4D& + Multiply( + const Vector4D &v, + const AffineMatrix &m + ); + Vector4D& + operator*=(const AffineMatrix &M) + {Vector4D src(*this); return Multiply(src,M);} + Vector4D& Multiply( + const Vector4D &v, + const Matrix4x4 &m + ); + Vector4D& + operator*=(const Matrix4x4 &m) + {Vector4D src(*this); return Multiply(src,m);} + Vector4D& Multiply( + const Vector3D &v, + const Matrix4x4 &m + ); + Vector4D& Multiply( + const Point3D &p, + const Matrix4x4 &m + ); + + // + // Support functions + // + Scalar + LengthSquared() const + {return operator*(*this);} + Scalar + Length() const + {return Sqrt(LengthSquared());} + + Vector4D& + Combine( + const Vector4D& v1, + Scalar t1, + const Vector4D& v2, + Scalar t2 + ); + + Vector4D& + Lerp( + const Vector4D& v1, + const Vector4D& v2, + Scalar t + ) + {return Combine(v1,1.0f-t,v2,t);} + + friend ostream& + operator<<( + ostream& stream, + const Vector4D& v + ); + Logical + TestInstance() const; + static Logical + TestClass(); + }; + +#endif diff --git a/CODE/RP/MUNGA/VECTOR4D.TCP b/CODE/RP/MUNGA/VECTOR4D.TCP new file mode 100644 index 0000000..5a58591 --- /dev/null +++ b/CODE/RP/MUNGA/VECTOR4D.TCP @@ -0,0 +1,140 @@ +//===========================================================================// +// File: vector4d.tst // +// Project: MUNGA Brick: Math Library // +// Contents: Test code for vector classes // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/19/94 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(ROTATION_HPP) + #include +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + Vector4D::TestClass() +{ + DEBUG_STREAM << "Starting Vector4D test...\n"; + + const Vector4D + a(Identity); + Vector4D + b; + const Vector4D + c(1.0f,2.0f,3.0f,4.0f); + Vector4D + d(2.0f,3.0f,1.0f,4.0f); + + Test(!a.x && !a.y && !a.z && !a.w); + Test(c.x == 1.0f && c.y == 2.0f && c.z == 3.0f && c.w == 4.0f); + + Test(c[2] == c.z); + Test(a[1] == a.y); + + Test(Small_Enough(a)); + Test(!a); + + b = c; + Test(b.x == c.x && b.y == c.y && b.z == c.z && b.w == c.w); + Test(Close_Enough(b,c)); + Test(b == c); + Test(a != b); + + Point3D p(3.0f,2.0f,1.0f); + b = p; + Test(b == Vector4D(p.x,p.y,p.z,1.0f)); + + Vector3D v(-1.0f,3.0f,2.0f); + b = v; + Test(b == Vector4D(v.x,v.y,v.z,0.0f)); + + b.Negate(c); + Test(b == Vector4D(-c.x,-c.y,-c.z,-c.w)); + + b.Add(c,d); + Test(b == Vector4D(c.x+d.x,c.y+d.y,c.z+d.z,c.w+d.w)); + b = c; + b += d; + Test(b == Vector4D(c.x+d.x,c.y+d.y,c.z+d.z,c.w+d.w)); + + b.Subtract(d,c); + Test(b == Vector4D(d.x-c.x,d.y-c.y,d.z-c.z,d.w-c.w)); + b = d; + b -= c; + Test(b == Vector4D(d.x-c.x,d.y-c.y,d.z-c.z,d.w-c.w)); + + Scalar f = c*d; + Test(f == c.x*d.x + c.y*d.y + c.z*d.z + c.w*d.w); + + f = 2.0f; + b.Multiply(c,f); + Test(b == Vector4D(f*c.x,f*c.y,f*c.z,f*c.w)); + b = c; + b *= f; + Test(b == Vector4D(f*c.x,f*c.y,f*c.z,f*c.w)); + + b.Multiply(c,d); + Test(b == Vector4D(c.x*d.x,c.y*d.y,c.z*d.z,c.w*d.w)); + b = c; + b *= d; + Test(b == Vector4D(c.x*d.x,c.y*d.y,c.z*d.z,c.w*d.w)); + + b.Divide(c,f); + Test(b == Vector4D(c.x/f,c.y/f,c.z/f,c.w/f)); + b = c; + b /= f; + Test(b == Vector4D(c.x/f,c.y/f,c.z/f,c.w/f)); + + b.Divide(c,d); + Test(b == Vector4D(c.x/d.x,c.y/d.y,c.z/d.z,c.w/d.w)); + b = c; + b /= d; + Test(b == Vector4D(c.x/d.x,c.y/d.y,c.z/d.z,c.w/d.w)); + + AffineMatrix m; + EulerAngles r(PI_OVER_4,0.0f,0.0f); + m = r; + m = p; + b.Multiply(c,m); + Test(b == Vector4D(c.x+c.w*m(3,0),c.y*m(1,1)+c.z*m(2,1)+c.w*m(3,1),c.y*m(1,2)+c.z*m(2,2)+c.w*m(3,2),c.w)); + b = c; + b *= m; + Test(b == Vector4D(c.x+c.w*m(3,0),c.y*m(1,1)+c.z*m(2,1)+c.w*m(3,1),c.y*m(1,2)+c.z*m(2,2)+c.w*m(3,2),c.w)); + + Matrix4x4 m2; + m2 = m; + b.Multiply(c,m2); + Test(b == Vector4D(c.x+c.w*m2(3,0),c.y*m2(1,1)+c.z*m2(2,1)+c.w*m2(3,1),c.y*m2(1,2)+c.z*m2(2,2)+c.w*m2(3,2),c.w)); + b = c; + b *= m2; + Test(b == Vector4D(c.x+c.w*m2(3,0),c.y*m2(1,1)+c.z*m2(2,1)+c.w*m2(3,1),c.y*m2(1,2)+c.z*m2(2,2)+c.w*m2(3,2),c.w)); + + b.Multiply(v,m2); + Test(b == Vector4D(v.x,v.y*m2(1,1)+v.z*m2(2,1),v.y*m2(1,2)+v.z*m2(2,2),0.0f)); + b.Multiply(p,m2); + Test(b == Vector4D(p.x+m2(3,0),p.y*m2(1,1)+p.z*m2(2,1)+m2(3,1),p.y*m2(1,2)+p.z*m2(2,2)+m2(3,2),1.0f)); + + Test(!a.LengthSquared()); + f = c.LengthSquared(); + Test(f == c.x*c.x + c.y*c.y + c.z*c.z + c.w*c.w); + f = c.Length(); + Test(Close_Enough(f,Sqrt(c.LengthSquared()))); + + b.Combine(c,2.0f,d,2.0f); + Test(b == Vector4D(2.0f*(c.x+d.x),2.0f*(c.y+d.y),2.0f*(c.z+d.z),2.0f*(c.w+d.w))); + + b.Lerp(c,d,0.5f); + Test(b == Vector4D(0.5f*(c.x+d.x),0.5f*(c.y+d.y),0.5f*(c.z+d.z),0.5f*(c.w+d.w))); + + return True; +} + diff --git a/CODE/RP/MUNGA/VERIFY.HPP b/CODE/RP/MUNGA/VERIFY.HPP new file mode 100644 index 0000000..8ea27d1 --- /dev/null +++ b/CODE/RP/MUNGA/VERIFY.HPP @@ -0,0 +1,61 @@ +//===========================================================================// +// File: verify.hpp // +// Contents: verification fail routines // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 09/29/94 JMA Initial coding. // +// 11/01/94 JMA Made compatible with SGI CC // +// 11/03/94 ECH Made compatible with BC4.0 // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(VERIFY_HPP) +# define VERIFY_HPP + +# if defined(__BCPLUSPLUS__) + extern int + _matherr(struct exception *a); +# endif + + extern int + Fpu_Ok(); + extern void + Verify_Failed(char *message, char *file, int line); + extern void + Fail_To_Debugger(char *message, char *file, int line); + + class Signature + { + private: +# if DEBUG_LEVEL>0 + enum Mark + { + ok, + destroyed, + corrupted, + noMagic=(int)0xAB135795L, + magic=(int)0xFFED1231L + } mark; +# endif + + protected: + Signature(); + ~Signature(); + + public: + friend int + Is_Signature_Bad(const volatile Signature *p); + }; + +# if defined(USE_SIGNATURE) +# define SIGNATURED : public Signature +# else +# define SIGNATURED +# define Is_Signature_Bad(p) (False) +# endif + +#endif + diff --git a/CODE/RP/MUNGA/VIDREND.CPP b/CODE/RP/MUNGA/VIDREND.CPP new file mode 100644 index 0000000..8ef109f --- /dev/null +++ b/CODE/RP/MUNGA/VIDREND.CPP @@ -0,0 +1,283 @@ +//===========================================================================// +// File: vidrend.cc // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(VIDREND_HPP) +# include +#endif + +#if !defined(APP_HPP) + #include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +#if defined(USE_ONE_VIDEO_TRACE) || defined(TRACE_VIDEO_RENDERER) + BitTrace Video_Renderer("Video Renderer"); +#endif + +#if !defined(USE_ONE_VIDEO_TRACE) +# if defined(TRACE_VIDEO_BECOME_INTERESTING) + BitTrace Video_Become_Interesting("Video Become Interesting"); +# endif + +# if defined(TRACE_VIDEO_BECOME_UNINTERESTING) + BitTrace Video_Become_Uninteresting("Video Become Uninteresting"); +# endif +#endif + +// +//############################################################################# +// Constructor for the video renderer +//############################################################################# +// +VideoRenderer::VideoRenderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration +): + Renderer( + calibration_rate, + calibration_complexity, + calibration_priority, + interest_type, + depth_calibration + ) +{ + Disconnected_Eye = False; +} +// +//############################################################################# +// Destructor for the video renderer +//############################################################################# +// +VideoRenderer::~VideoRenderer() +{ +} +// +//############################################################################# +// This creates the data structures and loads up data for an entity that has +// become interesting to the renderer. +//############################################################################# +// +void + VideoRenderer::NotifyOfNewInterestingEntity(Entity *interesting_entity) +{ + ResourceDescription + *video_resource; + ResourceFile + *this_resource_file; + ResourceDescription::ResourceID + this_resource_ID; + ViewFrom + view_this_entity_from; + // + // Check the newly interesting entity, then determine what kind of view we want + // to construct for it by seeing if it is the linked entity and checking to + // see if the eye is disconnected at a higher renderer level. + // + SET_VIDEO_BECOME_INTERESTING(); + Check(interesting_entity); + if(Disconnected_Eye) + { + view_this_entity_from = outsideEntity; + } + else + { + if(interesting_entity == GetLinkedEntity()) + { + view_this_entity_from = insideEntity; + } + else + { + view_this_entity_from = outsideEntity; + } + } + // + // Try to fetch this entity's video resource, if there isn't one, we still + // call make renderables as something up above us may have code to construct + // some effects independant of the resource file. + // + Check(application); + this_resource_file = application->GetResourceFile(); + Check(this_resource_file); + this_resource_ID = interesting_entity->GetResourceID(); + video_resource = this_resource_file->SearchList( + this_resource_ID, + ResourceDescription::VideoModelResourceType); + // + // Call the make renderables process to convert the resource script into a + // set of renderables for this entity. + // + if (video_resource) + { + video_resource->Lock(); + } + MakeEntityRenderables( + interesting_entity, + video_resource, + view_this_entity_from + ); + if (video_resource) + { + video_resource->Unlock(); + } + + CLEAR_VIDEO_BECOME_INTERESTING(); +} +// +//############################################################################# +// This handles killing off of an entity that has become uninteresting. +//############################################################################# +// +void + VideoRenderer::NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity) +{ + SET_VIDEO_BECOME_UNINTERESTING(); + // + // Destroy the dynamic entities that go with this uninteresting Entity + // in the reverse order that they were created. + // + { + Entity::DynamicVideoSocketIterator + iterator(uninteresting_entity); + Component + *component; + + Check(&iterator); + iterator.Last(); + while ((component = iterator.ReadAndPrevious()) != NULL) + { + Unregister_Object(component); + delete component; + } + } + + // + // Destroy the static entities that go with this uninteresting Entity + // in the reverse order that they were created. + // + { + Entity::StaticVideoSocketIterator + iterator(uninteresting_entity); + Component + *component; + + Check(&iterator); + iterator.Last(); + while ((component = iterator.ReadAndPrevious()) != NULL) + { + Unregister_Object(component); + delete component; + } + } + + #if 0 + // + // Destroy all the static and dynamic entities that go with this uninteresting Entity + // in the same order they were created. This caused some problems for DPL in the past + // but it may no longer be the case. + // + + Entity::DynamicVideoSocketIterator iterator(uninteresting_entity); + iterator.DeletePlugs(); + + Entity::StaticVideoSocketIterator static_iterator(uninteresting_entity); + static_iterator.DeletePlugs(); + + uninteresting_entity->DeleteVideoWatchers(); + #endif + + CLEAR_VIDEO_BECOME_UNINTERESTING(); +} +// +//############################################################################# +// Execute Method, performs the rendering of one frame +//############################################################################# +// +void + VideoRenderer::ExecuteImplementation( + RendererComplexity, + RendererOrigin::InterestingEntityIterator * + ) +{ + Tell("VideoRenderer::ExecuteImplementation has been called\n"); +} +// +//############################################################################# +// This process is supposed to make the renderables for an object, when a higher +// level of this virtual can't figure out how to make something it calls down +// to the level below it. If we reach here then nobody could figure out what +// to do so we can print an error or information message. +//############################################################################# +// +void + VideoRenderer::MakeEntityRenderables( + Entity* my_entity, // The entity we are dealing with + ResourceDescription*, // Pointer to the video resource + ViewFrom) // Type of reference (inside/outside...etc.) +{ + switch (my_entity->GetClassID()) + { + // + // Scorezones are allowed to have no graphics. + // + case ScoreZoneClassID: + break; + // + // Default case complains about missing graphics + // + default: + DEBUG_STREAM<<"Entity "<entityID<<" class"<GetClassID(); + DEBUG_STREAM<<" couldn't figure out how to MakeEntityRenderables\n"; + break; + } +} +// +//############################################################################# +// Startup the implementation of the Division video renderer +//############################################################################# +// +void + VideoRenderer::LoadMissionImplementation(Mission*) +{ + Tell("VideoRenderer::StartImplementation has been called\n"); +} +void + VideoRenderer::ShutdownImplementation() +{ + Tell("VideoRenderer::StopImplementation has been called\n"); +} +void + VideoRenderer::SuspendImplementation() +{ + Tell("VideoRenderer::SuspendImplementation has been called\n"); +} +void + VideoRenderer::ResumeImplementation() +{ + Tell("VideoRenderer::ResumeImplementation has been called\n"); +} + +Logical + VideoRenderer::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} diff --git a/CODE/RP/MUNGA/VIDREND.HPP b/CODE/RP/MUNGA/VIDREND.HPP new file mode 100644 index 0000000..5559fc5 --- /dev/null +++ b/CODE/RP/MUNGA/VIDREND.HPP @@ -0,0 +1,150 @@ +//===========================================================================// +// File: vidrend.hh // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(VIDREND_HPP) +# define VIDREND_HPP + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(RENDERER_HPP) +# include +# endif + +# if defined(TRACE_VIDEO_RENDERER) || defined(USE_ONE_VIDEO_TRACE) + extern BitTrace Video_Renderer; +# endif + +# if defined(TRACE_VIDEO_RENDERER) +# define SET_VIDEO_RENDERER() Video_Renderer.Set() +# define CLEAR_VIDEO_RENDERER() Video_Renderer.Clear() +# else +# define SET_VIDEO_RENDERER() +# define CLEAR_VIDEO_RENDERER() +# endif + +# if defined(TRACE_VIDEO_BECOME_INTERESTING) +# if defined(USE_ONE_VIDEO_TRACE) +# define SET_VIDEO_BECOME_INTERESTING() Video_Renderer.Set() +# define CLEAR_VIDEO_BECOME_INTERESTING() Video_Renderer.Clear() +# else + extern BitTrace Video_Become_Interesting; +# define SET_VIDEO_BECOME_INTERESTING() Video_Become_Interesting.Set() +# define CLEAR_VIDEO_BECOME_INTERESTING()\ + Video_Become_Interesting.Clear() +# endif +# else +# define SET_VIDEO_BECOME_INTERESTING() +# define CLEAR_VIDEO_BECOME_INTERESTING() +# endif + +# if defined(TRACE_VIDEO_BECOME_UNINTERESTING) +# if defined(USE_ONE_VIDEO_TRACE) +# define SET_VIDEO_BECOME_UNINTERESTING() Video_Renderer.Set() +# define CLEAR_VIDEO_BECOME_UNINTERESTING() Video_Renderer.Clear() +# else + extern BitTrace Video_Become_Uninteresting; +# define SET_VIDEO_BECOME_UNINTERESTING()\ + Video_Become_Uninteresting.Set() +# define CLEAR_VIDEO_BECOME_UNINTERESTING()\ + Video_Become_Uninteresting.Clear() +# endif +# else +# define SET_VIDEO_BECOME_UNINTERESTING() +# define CLEAR_VIDEO_BECOME_UNINTERESTING() +# endif + + class VideoRenderer: + public Renderer + { + public: + VideoRenderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration + ); + ~VideoRenderer(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // NotifyOfNewInterestingEntity + // + // This method tells the renderer that a new entity will be in it's + // interest list the next time the Execute method is called. + //-------------------------------------------------------------------- + // + void + NotifyOfNewInterestingEntity(Entity *interesting_entity); + + void + NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity); + + private: + void + LoadMissionImplementation(Mission *mission); + void + ShutdownImplementation(); + void + SuspendImplementation(); + void + ResumeImplementation(); + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + + protected: + + enum ViewFrom + { + outsideEntity, // The external view of an entity will be displayed + insideEntity, // The internal view of the entity will be displayed + collisionEntity // The collision solids of the entity will be displayed + }; + + // + //-------------------------------------------------------------------- + // MakeEntityRenderables + // + // This method is called to create the renderables for a given entity + // it must be provided by the hardware specific renderer. + //-------------------------------------------------------------------- + // + virtual void + MakeEntityRenderables( + Entity*, // The entity we are dealing with + ResourceDescription*, // Pointer to the video resource + ViewFrom // Type of reference (inside/outside...etc.) + ); + + Logical + Disconnected_Eye; // If this is true, we will construct an outside + // version of the viewpoint entity. This is so + // higher level renderers can fix the eye in one + // spot and watch the viewpoint entity drive around. + + }; + +#endif diff --git a/CODE/RP/MUNGA/VIDREND.TCP b/CODE/RP/MUNGA/VIDREND.TCP new file mode 100644 index 0000000..1a0f020 --- /dev/null +++ b/CODE/RP/MUNGA/VIDREND.TCP @@ -0,0 +1,21 @@ +//===========================================================================// +// File: vidrend.tst // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +Logical + VideoRenderer::TestClass() + +{ + Tell("Starting VideoRenderer::TestClass\n"); + return False; +} diff --git a/CODE/RP/MUNGA/WATCHER.CPP b/CODE/RP/MUNGA/WATCHER.CPP new file mode 100644 index 0000000..a762577 --- /dev/null +++ b/CODE/RP/MUNGA/WATCHER.CPP @@ -0,0 +1,224 @@ +//===========================================================================// +// File: watcher.cc // +// Project: MUNGA Brick: Watcher // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(WATCHER_HPP) +# include +#endif + +#if !defined(ENTITY_HPP) + #include +#endif + +#if !defined(CSTR_HPP) + #include +#endif + +#if !defined(OBJSTRM_HPP) + #include +#endif + +#if !defined(NAMELIST_HPP) + #include +#endif + +#if !defined(SUBSYSTM_HPP) + #include +#endif + +//############################################################################# +//########################## AttributeWatcher ########################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AttributeWatcher::~AttributeWatcher() +{ +} + +// +//############################################################################# +//############################################################################# +// +AttributeWatcher::AttributeWatcher( + PlugStream *stream, + Entity *entity +): + Component(stream) +{ + Check(stream); + Check(entity); + +#if 0 + // + // Get attribute ptr + // + int subsystem_ID; + DynamicMemoryStream_Read(stream, &subsystem_ID); + + Simulation *simulation; + if ((simulation = entity->GetSubsystem(subsystem_ID)) == NULL) + { + simulation = entity; + } + Check(simulation); + + Simulation::AttributeID attribute_ID; + DynamicMemoryStream_Read(stream, &attribute_ID); + attributePointer = simulation->GetAttributePointer(attribute_ID); + Check_Pointer(attributePointer); +#else + // + // HACK - Get attribute pointer using names + // + CString subsystem_name; + *stream >> subsystem_name; + + if ((simulation = entity->FindSubsystem(subsystem_name)) == NULL) + { + #if DEBUG_LEVEL>0 + { + CString entity_name("Entity"); + if (!(subsystem_name == entity_name)) + { + Dump(subsystem_name); + } + Verify(subsystem_name == entity_name); + } + #else + { + CString entity_name("Entity"); + if (!(subsystem_name == entity_name)) + { + DEBUG_STREAM << + "AttributeWatcher::AttributeWatcher - subsystem " << + subsystem_name << + "\n"; + Fail("AttributeWatcher::AttributeWatcher - subsystem not found\n"); + } + } + #endif + simulation = entity; + } + Check(simulation); + + CString attribute_name; + *stream >> attribute_name; + + #if DEBUG_LEVEL>2 + Tell("AttributeWatcher::AttributeWatcher - " << attribute_name << "\n"); + #endif + + attributePointer = simulation->GetAttributePointer(attribute_name); + + #if DEBUG_LEVEL>0 + if (attributePointer == NULL) + { + Dump(attribute_name); + } + #else + if (attributePointer == NULL) + { + DEBUG_STREAM << + "AttributeWatcher::AttributeWatcher - attribute " << + attribute_name << + "\n"; + Fail("AttributeWatcher::AttributeWatcher - attribute not found\n"); + } + #endif + + Check_Pointer(attributePointer); +#endif + + // + // Get other fields + // + *stream >> sendNotificationOnChange; + attributeChanged = False; +} + +// +//############################################################################# +// BuildFromPage +//############################################################################# +// +void + AttributeWatcher::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Component::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // HACK - Store attribute pointer using names + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, subsystem); + MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, attribute); + + // + // Store other fields + // + Logical send_notification_on_change = True; + *stream << send_notification_on_change; +} + +// +//############################################################################# +//############################################################################# +// +Logical + AttributeWatcher::TestInstance() const +{ + Component::TestInstance(); + Check(simulation); + Check_Pointer(attributePointer); + return True; +} + +// +//############################################################################# +//############################################################################# +// +Logical + AttributeWatcher::DidAttributeChange() +{ + if (attributeChanged) + { + attributeChanged = False; + return True; + } + return False; +} + +// +//############################################################################# +//############################################################################# +// +void + AttributeWatcher::SendNotificationOfChange() +{ + Fail("AttributeWatcher::SendNotificationOfChange - Should never reach here"); +} + +#ifdef TEST_CLASS +# include "watcher.tcp" +#endif + diff --git a/CODE/RP/MUNGA/WATCHER.HPP b/CODE/RP/MUNGA/WATCHER.HPP new file mode 100644 index 0000000..7471cc6 --- /dev/null +++ b/CODE/RP/MUNGA/WATCHER.HPP @@ -0,0 +1,337 @@ +//===========================================================================// +// File: watcher.hh // +// Project: MUNGA Brick: Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/14/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(WATCHER_HPP) +# define WATCHER_HPP + +# if !defined(CMPNNT_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +# if !defined(MEMSTRM_HPP) +# include +# endif + + class PlugStream; + class Simulation; + class Entity; + + //########################################################################## + //########################### AttributeWatcher ####################### + //########################################################################## + + class AttributeWatcher: + public Component + { + public: + // + //----------------------------------------------------------------------- + // Destructor + //----------------------------------------------------------------------- + // + ~AttributeWatcher(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // DidAttributeChange + // + // Returns True if attribute has changed since the last time + // DidAttributeChange was called. + //----------------------------------------------------------------------- + // + Logical + DidAttributeChange(); + + protected: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AttributeWatcher( + PlugStream *stream, + Entity *entity + ); + + // + //----------------------------------------------------------------------- + // SendNotificationOfChange + //----------------------------------------------------------------------- + // + virtual void + SendNotificationOfChange(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Protected data + //----------------------------------------------------------------------- + // + Simulation* + simulation; + void* + attributePointer; + Logical + attributeChanged; + Logical + sendNotificationOnChange; + }; + + //########################################################################## + //########################### AttributeWatcherOf ##################### + //########################################################################## + + template class AttributeWatcherOf: + public AttributeWatcher + { + public: + ~AttributeWatcherOf(); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + T + GetCurrentValue() + {return currentValue;} + T* + GetCurrentPointer() + {return ¤tValue;} + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + void + Execute(); + + // + //----------------------------------------------------------------------- + // PrimeWatcher + //----------------------------------------------------------------------- + // + void + PrimeWatcher(); + + protected: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AttributeWatcherOf( + PlugStream *stream, + Entity *entity + ); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + private: + // + //----------------------------------------------------------------------- + // InitializeCurrentValue + //----------------------------------------------------------------------- + // + void + InitializeCurrentValue(); + + // + //----------------------------------------------------------------------- + // GrabCurrentValue + //----------------------------------------------------------------------- + // + void + GrabCurrentValue(); + + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + virtual void + DumpValue(const T *attribute_ptr); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + T + currentValue; + #if DEBUG_LEVEL>0 + Logical + dumpValue; + #endif + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ AttributeWatcherOf templates ~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AttributeWatcherOf::~AttributeWatcherOf() + { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template + AttributeWatcherOf::AttributeWatcherOf( + PlugStream *stream, + Entity *entity + ): + AttributeWatcher(stream, entity) + { + Check_Pointer(this); + + Logical dump_value; + + MemoryStream_Read(stream, &dump_value); + + #if DEBUG_LEVEL>0 + dumpValue = dump_value; + if (dumpValue) + { + Tell( + "AttributeWatcherOf::AttributeWatcherOf - " << + *(T*)attributePointer << + "\n" + ); + } + #endif + + InitializeCurrentValue(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AttributeWatcherOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) + { + Check(stream); + Check(name_list); + + AttributeWatcher::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store dump_value + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AttributeWatcherOf::PrimeWatcher() + { + Check(this); + #if DEBUG_LEVEL>0 + if (dumpValue) + { + DumpValue((T*)attributePointer); + } + #endif + GrabCurrentValue(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AttributeWatcherOf::Execute() + { + Check(this); + + Check_Pointer(attributePointer); + if (!(currentValue == *(T*)attributePointer)) + { + #if DEBUG_LEVEL>0 + if (dumpValue) + { + DumpValue((T*)attributePointer); + } + #endif + GrabCurrentValue(); + } + Check_Fpu(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AttributeWatcherOf::InitializeCurrentValue() + { + Check_Pointer(attributePointer); + currentValue = *(T*)attributePointer; + Verify(currentValue == *(T*)attributePointer); + Check_Fpu(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + template void + AttributeWatcherOf::GrabCurrentValue() + { + InitializeCurrentValue(); + attributeChanged = True; + if (sendNotificationOnChange) + { + SendNotificationOfChange(); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + #if DEBUG_LEVEL>0 + template void + AttributeWatcherOf::DumpValue(const T *attribute_ptr) + #else + template void + AttributeWatcherOf::DumpValue(const T*) + #endif + { + Check_Pointer(attribute_ptr); + Tell((void *)attribute_ptr << " = " << *attribute_ptr << "\n"); + } + +#endif + diff --git a/CODE/RP/MUNGA/WATCHER.TCP b/CODE/RP/MUNGA/WATCHER.TCP new file mode 100644 index 0000000..d0a8a45 --- /dev/null +++ b/CODE/RP/MUNGA/WATCHER.TCP @@ -0,0 +1,198 @@ +//===========================================================================// +// File: watcher.tst // +// Project: MUNGA Brick: // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/03/94 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "entity.thp" + +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +class WatcherReceiver: + public Receiver +{ +//############################################################################# +// Shared Data Support +// +public: + SharedData* + GetSharedData() + {return (SharedData*)sharedData;} + + static Derivation ClassDerivations; + static SharedData DefaultData; + +//########################################################################## +// Message Support +// +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; + +public: + void WatcherChangedHandler(WatcherChangedMessage *message); + +//########################################################################## +// Testing Support +// +public: + ReceiverAttributeWatcherOf + *linearOriginWatcher; + + void + Tester(); + +//########################################################################## +// Construction and Destruction +// +public: + WatcherReceiver(SharedData &virtual_data = DefaultData); + ~WatcherReceiver(); +}; + +//############################################################################# +// Shared Data Support +// +Derivation + WatcherReceiver::ClassDerivations(Entity::ClassDerivations,"WatcherReceiver"); + +WatcherReceiver::SharedData + WatcherReceiver::DefaultData( + WatcherReceiver::ClassDerivations, + WatcherReceiver::MessageHandlers + ); + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + WatcherReceiver::MessageHandlerEntries[]= +{ + { + WatcherReceiver::WatcherChangedMessageID, + (WatcherReceiver::Handler)&WatcherReceiver::WatcherChangedHandler + } +}; + +WatcherReceiver::MessageHandlerSet + WatcherReceiver::MessageHandlers( + ELEMENTS(WatcherReceiver::MessageHandlerEntries), + WatcherReceiver::MessageHandlerEntries, + WatcherReceiver::MessageHandlers + ); + +void + WatcherReceiver::WatcherChangedHandler(WatcherChangedMessage *message) +{ + Check(message); + Check(message->changedWatcher); + Check(message->changedWatcher->GetLinkedSystem()); + Verify( + message->changedWatcher->GetAttributeID() == + Entity::LocalOriginAttributeID + ); +}; + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +WatcherReceiver::WatcherReceiver(WatcherReceiver::SharedData &virtual_data): + Receiver(TrivialReceiverClassID, virtual_data) +{ + linearOriginWatcher = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +WatcherReceiver::~WatcherReceiver() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + WatcherReceiver::Tester() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + AttributeWatcher::TestClass() +{ + DEBUG_STREAM << "Starting Watcher test...\n"; + + // + //-------------- + // Create testEntity + //-------------- + // + TestEntity::MakeMessage + message( + TestEntity::MakeMessageID, + sizeof(TestEntity::MakeMessage), + TestEntity::TrivialEntityClassID, + 0, + TestEntity::DefaultFlags, + Origin::Identity + ); + TestEntity *testEntity = TestEntity::Make(&message); + Register_Object(testEntity); + + // + //------------------------ + // Create watcher receiver + //------------------------ + // + WatcherReceiver + watcherReceiver; + + // + //--------------- + // Create watcher + //--------------- + // + watcherReceiver.linearOriginWatcher = + new ReceiverAttributeWatcherOf( + testEntity, + Entity::LocalOriginAttributeID, + True, + &watcherReceiver + ); + Register_Object(watcherReceiver.linearOriginWatcher); + + // + //------------- + // Test watcher + //------------- + // + testEntity->Tester(); + Test(testEntity->localOrigin.linearPosition == Point3D(2.0f,2.0f,2.0f)); + Check(application); + application->ProcessAllEvents(); + + // + //----------------- + // Test destruction + //----------------- + // + Unregister_Object(testEntity); + delete testEntity; + + return True; +} +#endif diff --git a/CODE/RP/MUNGA/WRHOUS.CPP b/CODE/RP/MUNGA/WRHOUS.CPP new file mode 100644 index 0000000..b4fc268 --- /dev/null +++ b/CODE/RP/MUNGA/WRHOUS.CPP @@ -0,0 +1,185 @@ +//===========================================================================// +// File: wrhous.cc // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +// This object manages creation and deletion of dynamically-created objects // +// of which only on instantiation should exist. It is currently used // +// only by the gauge renderer. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/01/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(WRHOUS_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//####################################################################### +// WarehouseObject +//####################################################################### +WarehouseObject::WarehouseObject( + const char *new_name, + Logical keep_forever +): + Plug(WarehouseObject::WarehouseObjectClassID) +{ + Test_Tell("WarehouseObject::WarehouseObject(" << new_name << "\n"); + Str_Copy(name, new_name, sizeof(name)); + resourceID = ResourceDescription::NullResourceType; + + referenceCount = 1; // at least one reference exists, otherwise no obj + keepForever = keep_forever; + Check_Fpu(); +} + +WarehouseObject::WarehouseObject( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever +): + Plug(WarehouseObject::WarehouseObjectClassID) +{ + Test_Tell("WarehouseObject::WarehouseObject(" << new_resource_id << "\n"); + name[0] = '\0'; + resourceID = new_resource_id; + + referenceCount = 1; // at least one reference exists, otherwise no obj + keepForever = keep_forever; + Check_Fpu(); +} + +WarehouseObject::~WarehouseObject() +{ + Check(this); + Check_Fpu(); +} + +Logical + WarehouseObject::TestInstance() const +{ + return True; +} + +//####################################################################### +// WarehouseBin +//####################################################################### +WarehouseBin::WarehouseBin() : + Node(WarehouseBin::WarehouseBinClassID), + instanceList(this) +{ + Test_Tell("WarehouseBin::WarehouseBin()\n"); + Check_Pointer(this); + + Check_Fpu(); +} + +WarehouseBin::~WarehouseBin() +{ + Check(this); +} + +Logical + WarehouseBin::TestInstance() const +{ + return True; +} + +WarehouseObject * + WarehouseBin::Find(const char *old_name) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + WarehouseObject + *object_instance; + + while ((object_instance=i.ReadAndNext()) != NULL) + { + Check(object_instance); + if (stricmp(object_instance->name, old_name) == 0) + { + Check_Fpu(); + return object_instance; + } + } + Check_Fpu(); + return NULL; +} + +WarehouseObject * + WarehouseBin::Find(ResourceDescription::ResourceID old_resource_id) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + WarehouseObject + *object_instance; + + while ((object_instance=i.ReadAndNext()) != NULL) + { + Check(object_instance); + if (object_instance->resourceID == old_resource_id) + { + Check_Fpu(); + return object_instance; + } + } + Check_Fpu(); + return NULL; +} + +//####################################################################### +// Warehouse +//####################################################################### +Warehouse::Warehouse() +{ + Test_Tell("Warehouse::Warehouse\n"); + Check_Pointer(this); +} + +Warehouse::~Warehouse() +{ + Test_Tell("Warehouse::~Warehouse\n"); + Check(this); + Purge(); + Check_Fpu(); +} + +void + Warehouse::Purge() +{ + Check(this); + + bitMapBin.Purge(); + pixelMap8Bin.Purge(); + palette8Bin.Purge(); + + Check_Fpu(); +} + + +Logical + Warehouse::TestInstance() const +{ + Check_Pointer(this); + return True; +} + diff --git a/CODE/RP/MUNGA/WRHOUS.HPP b/CODE/RP/MUNGA/WRHOUS.HPP new file mode 100644 index 0000000..1ace6f2 --- /dev/null +++ b/CODE/RP/MUNGA/WRHOUS.HPP @@ -0,0 +1,481 @@ +//===========================================================================// +// File: wrhous.hh // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/01/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(WRHOUS_HPP) +# define WRHOUS_HPP + +# if !defined(RESOURCE_HPP) +# include +# endif + +# if !defined(CHAIN_HPP) +# include +# endif + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(PLUG_HPP) +# include +# endif + +# if !defined(GRAPH2D_HPP) +# include +# endif + + //####################################################################### + // WarehouseObject + //####################################################################### + class WarehouseObject : + public Plug + { + friend class WarehouseBin; + public: + WarehouseObject( + const char *new_name, + Logical keep_forever = False + ); + + WarehouseObject( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever = False + ); + + ~WarehouseObject(); + + Logical + TestInstance() const; + + void + SetKeepForever(Logical keep_forever) + { + Check(this); + keepForever = keep_forever; + } + + Logical + GetKeepForever() + { + Check(this); + return keepForever; + } + + void + Reference() + { + Check(this); + ++referenceCount; + } + + Logical + Unreference() // returns True if no longer referenced + { + Check(this); + return (Logical) ((--referenceCount) <= 0); + } + + + protected: + char + name[32]; + ResourceDescription::ResourceID + resourceID; + int + referenceCount; + Logical + keepForever; + }; + + //----------------------------------------------------------------------- + // WarehouseObjectOf + //----------------------------------------------------------------------- + template class WarehouseObjectOf: + public WarehouseObject + { + public: + WarehouseObjectOf( + const char *new_name, + T *new_pointer, + Logical keep_forever = False + ); + + WarehouseObjectOf( + ResourceDescription::ResourceID new_resource_id, + T *new_pointer, + Logical keep_forever = False + ); + + virtual ~WarehouseObjectOf(); + + Logical + TestInstance() const; + + T + *dataPointer; + }; + + template + WarehouseObjectOf::WarehouseObjectOf( + const char *new_name, + T *new_pointer, + Logical keep_forever + ): + WarehouseObject(new_name, keep_forever) + { + Register_Pointer(new_pointer); + dataPointer = new_pointer; + } + + template + WarehouseObjectOf::WarehouseObjectOf( + ResourceDescription::ResourceID new_resource_id, + T *new_pointer, + Logical keep_forever + ): + WarehouseObject(new_resource_id, keep_forever) + { + Register_Pointer(new_pointer); + dataPointer = new_pointer; + } + + template WarehouseObjectOf::~WarehouseObjectOf() + { + Check(dataPointer); + Unregister_Pointer(dataPointer); + delete dataPointer; + dataPointer = NULL; // safety check + } + + template Logical + WarehouseObjectOf::TestInstance() const + { + Check_Pointer(this); + Check_Pointer(dataPointer); + return WarehouseObject::TestInstance(); + } + + //####################################################################### + // WarehouseBin + //####################################################################### + class WarehouseBin : + public Node + { + public: + WarehouseBin(); + ~WarehouseBin(); + Logical + TestInstance() const; + void + Add(WarehouseObject *new_object) + { + Check(this); + Check_Pointer(new_object); + instanceList.Add(new_object); + } + + void + Remove(void *old_object); + WarehouseObject * + Find(const char *name); + WarehouseObject * + Find(ResourceDescription::ResourceID new_resource_id); + + protected: + ChainOf + instanceList; + }; + + + template class WarehouseBinOf : + public WarehouseBin + { + friend class WarehouseBin; + public: + WarehouseBinOf(); + ~WarehouseBinOf(); + + Logical + TestInstance() const; + + T* + Get( + const char *name, + Logical keep_forever = False + ); + + T* + Get( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever = False + ); + + T* + GetIfAlreadyExists( + const char *name + ); + + T* + GetIfAlreadyExists( + ResourceDescription::ResourceID new_resource_id + ); + + void + Release( + const char *name + ); + void + Release( + ResourceDescription::ResourceID new_resource_id + ); + + void + Purge(); + }; + + //-------------------------------------------------------------------- + template Logical + WarehouseBinOf::TestInstance() const + { + Check_Pointer(this); + return WarehouseBin::TestInstance(); + } + + //-------------------------------------------------------------------- + template + WarehouseBinOf::WarehouseBinOf() + : WarehouseBin() + { + } + + //-------------------------------------------------------------------- + template WarehouseBinOf::~WarehouseBinOf() + { + Check(this); + + Purge(); // remove EVERYTHING unconditionally + Check_Fpu(); + } + + //-------------------------------------------------------------------- + template T* + WarehouseBinOf::Get( + const char *name, + Logical keep_forever + ) + { + Check(this); + + WarehouseObjectOf + *instance = + (WarehouseObjectOf*) WarehouseBin::Find(name); + + if (instance != NULL) + { + instance->Reference(); + return instance->dataPointer; + } + else + { + T *new_object = T::Make(name); + + if (new_object != NULL) + { + Check(new_object); + // new_object is registered in the warehouseObject creator + instance = new WarehouseObjectOf( + name, + new_object, + keep_forever + ); + Register_Object(instance); + WarehouseBin::Add(instance); + return new_object; + } + } + return NULL; + } + + template T* + WarehouseBinOf::Get( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever + ) + { + Check(this); + + WarehouseObjectOf + *instance = + (WarehouseObjectOf*) WarehouseBin::Find(new_resource_id); + + if (instance != NULL) + { + instance->Reference(); + return instance->dataPointer; + } + else + { + T *new_object = T::Make(new_resource_id); + + if (new_object != NULL) + { + Check(new_object); + // new_object is registered in the warehouseObject creator + instance = new WarehouseObjectOf( + new_resource_id, + new_object, + keep_forever + ); + Register_Object(instance); + WarehouseBin::Add(instance); + return new_object; + } + } + return NULL; + } + + //-------------------------------------------------------------------- + template T* + WarehouseBinOf::GetIfAlreadyExists( + const char *name + ) + { + Check(this); + Check_Pointer(name); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf *) WarehouseBin::Find(name); + if (warehouse_object != NULL) + { + Check(warehouse_object); + warehouse_object->Reference(); + + Check(warehouse_object->dataPointer); + return warehouse_object->dataPointer; + } + return NULL; + } + + template T* + WarehouseBinOf::GetIfAlreadyExists( + ResourceDescription::ResourceID id + ) + { + Check(this); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf*) WarehouseBin::Find(id); + if (warehouse_object != NULL) + { + Check(warehouse_object); + warehouse_object->Reference(); + + Check(warehouse_object->dataPointer); + return warehouse_object->dataPointer; + } + return NULL; + } + + //-------------------------------------------------------------------- + template void + WarehouseBinOf::Release( + const char *name + ) + { + Check(this); + Check_Pointer(name); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf *) WarehouseBin::Find(name); + if (warehouse_object != NULL) + { + Check(warehouse_object); + if (warehouse_object->Unreference()) + { + if (warehouse_object->GetKeepForever() == False) + { + Unregister_Object(warehouse_object); + // the dataPointer is deregistered & deleted in the destructor + delete warehouse_object; + } + } + } + } + + template void + WarehouseBinOf::Release( + ResourceDescription::ResourceID id + ) + { + Check(this); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf *) WarehouseBin::Find(id); + if (warehouse_object != NULL) + { + Check(warehouse_object); + if (warehouse_object->Unreference()) + { + if (warehouse_object->GetKeepForever() == False) + { + Unregister_Object(warehouse_object); + // the dataPointer is deregistered & deleted in the destructor + delete warehouse_object; + } + } + } + } + + template void + WarehouseBinOf::Purge() + { + Check(this); + //------------------------------------------ + // Delete everything in the bin + //------------------------------------------ + ChainIteratorOf + i(instanceList); + + WarehouseObject + *object_instance; + + while ((object_instance=i.ReadAndNext()) != NULL) + { + Check(object_instance); + Unregister_Object(object_instance); + delete object_instance; + } + Check_Fpu(); + } + + //####################################################################### + // Warehouse + //####################################################################### + class Warehouse SIGNATURED + { + public: + Warehouse(); + virtual ~Warehouse(); + Logical + TestInstance() const; + virtual void + Purge(); + + WarehouseBinOf + bitMapBin; + WarehouseBinOf + pixelMap8Bin; + WarehouseBinOf + palette8Bin; + }; +#endif diff --git a/CODE/RP/MUNGA/mssccprj.scc b/CODE/RP/MUNGA/mssccprj.scc new file mode 100644 index 0000000..b760d70 --- /dev/null +++ b/CODE/RP/MUNGA/mssccprj.scc @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[MUNGA.MAK] +SCC_Aux_Path = "M:\VWESS" +SCC_Project_Name = "$/Tesla_rp/MUNGA", FEVAAAAA diff --git a/CODE/RP/MUNGA/opt/ANGLE.obj b/CODE/RP/MUNGA/opt/ANGLE.obj new file mode 100644 index 0000000000000000000000000000000000000000..58ca11c6001bde239dd385683ef9779e1e39c2e2 GIT binary patch literal 3671 zcma)8Z)_7~7=OFATQ!wUMHqC&p+#pPWE0SYm{8a%k}%k4S3p|2x4mn7z(%#AG0^6vI(0Qz?nq~DrR_gXEv83#a9582Go{zA+n@Wm6JpRxD9|Q z0Q%d3If)b1T}*=z(^?SHbXpWtd9DHEtbqkKrAl(0@kuj-FAtJHIMA+8lDQ0L7V;9n z-UZm^c374wSwkFxP@Dxwm08m}bT|Vb3x`#jtUHXd5M?1tkyYi4YGgzhX0(76QdwG8 z--#{FKE{S^wO~`4*sx60W>KcXOQtg1BIv6{N5#jsNGBi_Se{c%Moc?poi?SYa>Eb= zS(K2H#59*_z-%j}JT=)cW!5^S$_Y(}VcNPEVc*3 zCi597oi>0Sj*Ft6tsfUW?I_LSJp zl-Z}PfEpa~Y~2L!jbv(1j1yCQo?&Ak3I13}NQzrb%!U>W`WD?3h#S+L(;rN;V9b!5@Md`I|3LsU6WwnHwGX` zfxD1eZ|K^GL1Ww7{Hiy7I5>feTpS|qL?m<~;u<|V7J~WM{>Xk8{_7q)cG2S9shf0Hoz*V#QHHn@DMkng2cd@!inVB zpxKjPAjvD)z-+30DML0qLP>cQdKj3^&85^4;!PyfyquKYM#~9VgvL8I2ai#Pqhjzd zE9U~U^4uH7y*iS<17AjqKESN6V~$9&KzZ&xHZYrppnbH!W7Oa`mCA3L(jTRmb^r!? z=IF2UM_5HYBq}NuQ*2;vw(uDuY+1(G416ZsX|Naz!B!S8SiT6IcMJr>oH!~e6O@y| zK&oV#3hqY~yk{LR*1c^~JTlyPlCh*~O?n4VS9Uu=+?4kFWcHt}n}S*JWO{zNqK7;` z3)uPRbrV=qkVC zg62T~Lu(7rKIqoAA$T`}o_a+fzUu|jhb^rQj#8G+} b?fR_;cI1^l0tb0erVJTm*bJ)FV1fJxu236j literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/APPMSG.obj b/CODE/RP/MUNGA/opt/APPMSG.obj new file mode 100644 index 0000000000000000000000000000000000000000..fecab7fff2eacb610695892ff4c6a271492885d2 GIT binary patch literal 3052 zcma)8O>Z1U5G}_W#|TRxAqZbF4jAOb$ONKXIC*1RIa%3w?FgZ@mfo43-Bx$mk*uF* zy|hq6)@ye<$K6MJ2b~T~-U5I(9_m~&6>lBv?ruHUy9bj`0sd)@Jb9Ylfyp+&%Ts*v zB#F{YDZ4kyGMIdVupz=eSk_`JvwVhn>PPW0uefd_7bSmhnTusv$wacg^~)M*V?|uT zK0{c9u+3$voJU-Yd0qn1j+X-j-dYAKZhz4Evsqr!=CK2{rDj;d$c`rn^Vq@EP&zwE zT@p~I(KVsfOdXZsQI~0g3s%Y`b8M7yCW*P8Kzw=hrVR&lxUNIo@O%73%R83(dLnmP`w+3TN&bq@>g*&v?XqPz-gF zlt~-!=Zk7xXxmAe=bk}nI34MXjrPT3+c;*H&GtCZflL;)n=(LUa~8Qi(JNtVXZ<$4 z5(d$Oo=}l2V%|eZ_>W^km~1-CI|~>ladw&jk-f+;4@_=3hPM|O${~fxNACRQ!Z}J1 z3hN0Y`nWS>a#*FYvCvHv2#{hxh%G1M-31v!r%VZ)j4&jbx`kZ~OPv)HGF{*c7Cmod zks=k=P@a&fDYJOrhYd-jX1K~>KwlM7HUeUvOeKW-79)fxXg!#Jpr;>Hv&{{>{OccF zt4IdF?7;Q@>Crc*t%JvhNBDf$K5e(?zqP|hCy&oMt^UJqcNKr&*BkKXU$AlwrcVH^ z>($eZb%5X2VC~iFt7~xe1;EPAeml#gh^8M0{eG9et)3J-zc}W`up!^y9z-_Z{$Aim zpEu&9P{+a;{Ipnz7~{PJSNAZ-oy8nF^M{Ci3i%R4?#_p_2RgTbn3!VjW6bCCG2Oys zT*dyV@r0tj!l>Q(s1t6Alm~+Tz@Xp%h82Lb%YQGA)?dJz_?H*^E$k5fTE_#pJlpuW wvvL0X>Z-zQlo)J6g*ks-ow@k6+1YZu!@S;vaXGNP%Q@WHYxOg@#OZ+l01X=et^fc4 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/AUDWGT.obj b/CODE/RP/MUNGA/opt/AUDWGT.obj new file mode 100644 index 0000000000000000000000000000000000000000..4b0ddb6a342eb867ae4ebfdb5b728993b6ec4814 GIT binary patch literal 4960 zcmcIn%TF6e82=0g96}P>00F|oNlYFM%9BWGm4kUDMM{W^mrc@w=wOfSY4+jljvdld zrK%E@d*D=6l_H@km)Tiezneb>Yba<=T8E1KXzo;MAOHX~f7U=dWH(-nn)IwxyE5-RZf>D zIw|^E1)VB)f*PFhSGNP}K9|##Oq(;`S3xJ7ki^8G{H19<_vkMAYA0G_=c#QbY-``G zAS_I-xMDC~rMUpNF2`xi(7Cl082AKn5(5iNqc*qn07&IPi`r(z%K4ENE{k%JFj_Q6 zS(REIqo@}Jfs%U3>1D&<9_#|bL|L6}4WZ2mZ_+AI60J7VE7}22Xcd8$X!SA@XkC$O zC6zog0~bV-NXQWNve@LpXAxvZQEPIcfGCLzmWiG+)9|z&wKYU0gjxw9DHK9QAc{%? z#De0c)oAgfY8F9`=yB6xMdmwl9$}){Mq5)`B6i91R)BrQB1U>YJLG^CxV( zEFg$B`6(hN@zXH#O;sc&l4R6`G9^Z({aNR_;tI5&cGV>5SWjTt$ulBa8E68=$C2-_1rW+;Rq8rDub zK#spEV?Dt3xX&;cV(^L-wkLi0nUEY!U z$P8xc#9&w%(U5{0Ej-}c>1j9<6?BHzB8+)k7LDnQ+d@xNP<6s_-bV+dpqT_)IU2BG zR5ZLgwgKd6!8IW|Z+V0W3Q>hbUeNC4I_TVp!@v3R-HBxI<6Y?5P!^vm@%hIKi}<`S ztIWp5NB6>mmB*`@_{Ll|+llY)jiu!!Wg{Uzg&cnBfnNt9)&cGlK)lO)ibGEVU@r^H z=_y5=aZCPOd0a^G^37Y1@XBK`qCLb}pWthcefrHrOe_*wa!a4)j zk8EpR*jk0yv~YW=8;8F278k*nr=iTJxB50(fH<4pMt${7!DANMm{V* z2V;T!zG=NARtx4lj0c!Gl6x)#O+m5=u_dEAH;D?!x<5($Btti{>}!lj6-(x@-78c#tFGi~i-hE7jl9s;>i%^(xM4)=hL1uU z(4_f_Wnl@mVlTF0mw73SV-UvOXRS3?-m1c6h;POFDfb9nPrYDRC9rb|AeKzeieE=h zC@YpYo`Puwe?nrtaAM?WY72vhubs0H>l_FpmvMdz>Fx-`09I>%{f7Tw{q4@q?fUmP z^8nt$>n?Eml}`BOB;Z($BT!)Qy_YYwp{m@CMr=31^!0A^9odI>o8CL3D z&X`i~c9KfH$4M#mgmYOPcBa)4=Y~4!%&2FbyGs3-b5E)FI%%bT+*wfSea@%q8RwyT z(#fdfj-rk^Pt{YfI{gqA6mZGSnfHroNg@R3D-oj;4TkC u{g}Hf(w41t?q}l9y!7s(2#*OrJFY0vBszXr)Yl}!R5b7E_eC|V5BLY}^nlX< literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/BOXLIST.obj b/CODE/RP/MUNGA/opt/BOXLIST.obj new file mode 100644 index 0000000000000000000000000000000000000000..e82d1f989f24ac8e5a45b8a96f3fceed91790245 GIT binary patch literal 4388 zcma)8U2M}<6uwE*Hl>-U#KwQ2Y+>uhRsktPfF`v`!`h9O(j+b&EtwNLjlr>leUp_3 zCZ?)VqYF}>rfC}!50s6Uy$)&9hSX{m(zFM(2M`aNG(bh{Wn$u~qC3ZS8Ygv9nkKgI z{mys3^K-B7#hs*8I6O*4UFPFjb~KYy#`)3U@sr2;BGHb};2@daKnPhMR5h7bgtpM0 zJ#7a%_LAw>30YjjG{R-xG=PtX;cmxjH{t|UXhNOnNN2NTdN(1D(ZoSdLJ`Ja2&YcS zl1@#&*MRQ?@NHY|m{-PS(L_NUk5kU_G?nsHQk9atq_e!NDk(G|lnBwSL%e({rDUjP z#fzRLXJB4TQdKK5Vq#vzvmbB?Al$w>U{#aGB`c6u0rnBVwyuVyc|C1Lfglv;0HT^` z!dgDhR6`dO=72t$t!uzWJj7uDBdONnJ{SXKu%-NuGtqBe&x zby>BPVWBXu4i#0(TBH_`&xobgM7J?#w@IC9W(hD-1UZC|RF#x8UV>GPl$Uvn4PB<4 zT~aAyTMQpNN172c30X~^Ejg`LQviup=Fll-&LO>uD%iRx3Lu9rs;JbMGnFhUmMkp5 zsIz{FiW(1#s-zzSb;vCQs)<%^QGd0iBJx?23!P$}9NI$=6S;9Ul`?@fmWxi$7ncjJ zc9iC@4T3c2j!cOS*Na2i@&ZqJ6IG)ESvhBgiNdN-QH@Vpb=n1}ws!BXEwFDSk_Sd5 zB`N0waTFxMzX%S=^bQNNu>!-(&^xsNNqRmDe#msI#qdf6gW05HdZ#tNsbU@^ND9PL z9TA5$gGsKgQm2BX)}jD_EF}=pX35xGAwyC#ydptoREMODY(W*PODzRcE$NcFHj6A} zB&wsIYDvxT6!!b-2}#K+4@LG8HL5@m_&;#c+UP+2UQC1-o8+L0MwpXIT^N_yIW0E40Ui(}~ zmEqM22eo6s)zvKsD+5s#hrnvzKASXqaD>e4AuhMy&WAPw@OtX%#$Ai2qF~kw&cS5n zZ9-hT9nn!yr+tbU4WuS-z+sC)(S0)mK|XE z#wyDp=)XKRNLgOy(Ev^zuGUosVGY{U%w>MF3t;a7?A=u`ET}EfRtrEw*b93S?N5XK z@LKkwZf7VLtL^VB^JHs*OX%P*I0&reAf^Z+EUHq|Wm8LN+zH0-tYuu*k!jc%X4=85 zY!Mg@S=kp~1N7=$H~5LMe{RBsjLpr=zy8+ zV=*t-Z3S)XS>VX;vj(FRZV%`hn=>>GvkSf=#Wofg=8AEE77zRN zNs}q>Vc=HLW^#TJ-ImOTD$I^>!-1z6ZOxT5#o*wVf5(%n`8AbDXT30i?Tu!?1l|*cv%p z>CJRI(45(y{tp`QOq;y~FVCGJ_Gj-LxiUho^>D6hL-0*;t_Pn+-Pa~L&$Vy4hKCJN z_iQs)|F9FThq(G#m1~;4&Ut5Va*eb1Ip6i2+`2~{QP=g)xaLPUqV7jOMBUea;@poG z;QAX^N3Qk|NWzQ$+4cuqh;6v1>u7v+9r3`W?K>p9QcoVZqb?kTS2}5%w+}LW_#doB B;wJzA literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/BOXSORT.obj b/CODE/RP/MUNGA/opt/BOXSORT.obj new file mode 100644 index 0000000000000000000000000000000000000000..2fb836f420b57f3653e05e900ade5844479eb49b GIT binary patch literal 4512 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 RWr$ya>qj_otUA3^s+fWQAEwDwK>5p=fz zE}!Got=TkfZLA2l+etFyy9^L^XBL+7fQwU}X21`SuZcj1Y{l&lI(;$5kpc%U(8_4Z zGu->g_ch|)olVSCYlOmbFC&jUZJ8BXjnh&cjm(n`wWl^MJo4(8lDYI|` zPkCTVTL^MEY*};U zFv%j6LzYRcd114R1fz@&*lEyaBlYvxB7TL9+Uj646Kqr_X>*imq|TL5qsUiBN7a=P znFnMsm%`+Xl$J)=kv1?k-v_FcK#me{&Lhzp`{u2bNtUxw%C;8BD&RYJr7@42 zQV01C&g%k#_(YxLoTE;q!-*-XBFHgCQ=K|-Q%Rw6S){-2)-Nni87|e>G%D2LEf$*c z+*>luwuaU%ENY AxBvhE literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/ENTITYID.obj b/CODE/RP/MUNGA/opt/ENTITYID.obj new file mode 100644 index 0000000000000000000000000000000000000000..ae0688698d1c686fcd834498fc61b6c3fe277c6d GIT binary patch literal 3728 zcmb7`TW=dh6vtRz1P zu}L0~D)q(D3dv8XLIfh-_y#DBp_jSW(tB!rA#wHX( zKCzwKp&&Yt2r^4>vEPpT3JAUj;EVl&)G8S)lq<^R99vMqZ7cMLiAelaY;K9gj)XC+ z#2+mdEmJsqVPq}`YfKlm(^kaFJWXWm2v$(i5!>M<9whQIVA#0n{<@T@TlUQ%gytlW za9B_~tZ)e+NreT?w=0ackdoMP9pT;NUg}a)Ud4*HMc_z(?oBQ zG+o0EoZ$##T_qj0x<+IWNKIyNH&Dc|8F^UU6~TtUOc9c#pxaiFm%_S5W=ahjsA0&m zJfz@e$7Z-C&(vgQ-mvvx6AtPEK&&HAtem90mR;zWA`KwP6!mm!M=oV>tK)3Q%KdY} z915E%EE*;%sVyYxu%NbBw5YAZXvNpUu4A7h<56JwYRN7ZeQ>~bam9XnyWnm|Ym##Y ztig1cp&ITNN!e-zDyUCk1`!>o7}X$6G!`Kx9I6L>x(HPAjrhfLaBk%FOIdE|Mzz4Q zUeki}yhd{A>uD_)$9G&O_fC;-lQAVm zT30GjhyANKITdeRrANp!qlA1hLPnZH%@}E%BSbl~yw-XMNv|%a^15(RyES;uA`M7R zIp4SD>|Ji-XOWUC@C96(28GE!1AV zMhZ@LWhPWg<=tu?Bs#ErQp|zlq)Y9N95cDqh5d+FUv9n{|3$vo(%^qd0~oH`ZI>vr ztPHl>jV(yA5_GUD`CD?VSFIt%*sjs7c3+BFy=upZ!GI{wb~MK3pjC^*d^V$JVLQUOY<0KsDq2>8-^Ve?FM-PUBY&*43RyjYb3SXA-dFjUL3k zP4!?Sybm`siJmX`I{y84CwvvS_Z@^FC^$$jh@)T}C5*GR{l53!^9 zKDhg<@+9FA@66Ie|I_&Q54!W{(fB}!>8m&y=4`WUwSCi#rsc&gX;I@ z7%>OV4+rGTeN~;DTtBgA(T}j1`HBP9|G~*oe4Xc%xp}u zd+$B--Sd6toO|!woNIusu{XL5QI~~?mh4KTlwP5WJIo*IINTQ6)6(7!nP&jtsr{-Z z3reh^W%urey?b7P%npE=)#mbiVi#n#1N=pME<~b|mNX?{?CDD;A@e)}k0NmMN=1Uw zD~l$Ix{JHJ(^Nw+BvmniFCZ|A!1|T$lB%Q_uf~cFDXoh>As$C{+E5WFxdYQ;)KIl0 zkN=ms2^IFB!!0Wns+!a*S%GXr*xLx(v=Y`Q=zXR*3Zmj%K!zq-xuY5GMUYE|4WVZ# z!&DYUxyaHrLm#lpMPZcD1(uHX2}|lrd5eq7ywS3{c++j(XqZ%+OPIQ>TFU4Wp?P(w zsIqK{lmZF~QI>SeBc%gl3qoP*;Y{qK`yJvQK@csSF)s7vS^&;c5HBxA343LK!~T0oztQI3OA}M@@qg z_%^`D6;QG0Uo3+UzkzCWu88k64W=Zh!G27X#iqezy6_+-3x)p1V8py7L=YOGrj$f~ zjb@Az54t!s23tA{o1#NZYNC#!3%8ji<;kHaJm(3CnZfPy0ALJ)WkcUwrWm47M3lz^B~WGG}OdTCtY#VPP>3ata5e@(CbKuN zf$lrQ!`OfC?!m>y#ZLYh=?;*yY=7+xg`OaD7bc9rF}^T5f0zBcjQntsTOi?u#r=VP z=m*laa5T%^YqtQki zoC}%XB)eiG8!1gTn{B&7!n01YSvy&PaI-FCj7gTUkqwt7o5{9iNO;CcHe)BNCESb) zS$TmhJA`Y?#&@nXUp`xyK*D(^W!_F%N4UHTWra!Ew~X>u5{IQ(r?Xi)hlHn{tkZVZ z4TPI^VXZV-k1uCEy(;TeHcRJ_@RXBv%Feola8oXC)wxSNo4bbXw`l(f?Z2V@U%q{u7JI@-^n{Ufx0 ziQ}7S{{`DW(f*ic#u>h9d>daq-psS(9JXD2&A5#AchP B{ki}E literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/FILESTRM.obj b/CODE/RP/MUNGA/opt/FILESTRM.obj new file mode 100644 index 0000000000000000000000000000000000000000..182fb62b95efe27c925addbfc4f297a39ac2f8b6 GIT binary patch literal 3913 zcmb7H&ujHi3_f9MGAq0V8E25Q6s7p3DHY}6A%K5i8rRSNz;vY98cIE&hFSv z4waB1q@-I_IUrP3Mam%@ddr~)j$1(DTJHVm1|QOdHVWjDxHS)g8*>gqG@T0p(auzBZ+gP zXJP#ez>8O{y_MC6Vf`I|-{~&EP@Zed7M4C*C>CM;6asG|u)kfAVk~N`h9bIrFr8%z zMR3!o0Z$_^hrna)bVZXJVoYrilGy-#NBIgjQ`hi5*02W;Xu1W z)8dQVbL1q#K0(;gc345N3pH^BB5?sAVKFau6yZe#1w>dV3-t(-EJ6jyvMpiX5jBeh zBZ~pBa;~7%)$hfYXH9IB)&Mr!$3||Fwg5M6&GeK}iBMbvGHNuH$X-B2XBxLXMlw4S zY&M4l+z1GP0$j+MMxHM=V4-tn&h!P%%-v}i4a+Hln9om& zTtIjYQ}tDmjG%xjYRS}GFqOs)PZlL$HdsFw%u=wa8v4o6fY_p=7V~0DK?`dYrW9*j zWR&t0P#!8n2$ z!a}HorR2Okoj_D#D0<=u?i&labF;=e))gsz~ z^@pK+ zIteffvi( z>LGHj#&6d3N~vfqP<5?d7{f4+F%2;H6dsPk_JM3qrB8OH?WJsVdn3DV`+FQeW#8ET zExYeg7mi^Z*RuN`6|*tedJMRmePkwhQ~M^0rfqXPo+t9Am1yi~7cMk5u%ThV7hB7B zT+`>(YtS}YYp85;_1#x;WAP1xOK$rvYDv1N<*1*iU8on};V@J{b~`E&+3l=EWj9iZ z$xZGG1>4-BP8+n4ztwC@jHMX(BedH+I^05VRod6eKD_-I=PUmhq VavNLd!zTwGxY#FHf#9G%_!o(`DnI}L literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/FILESTUB.obj b/CODE/RP/MUNGA/opt/FILESTUB.obj new file mode 100644 index 0000000000000000000000000000000000000000..ced95a216bdf0920a0fa5e5b8520ae3d3964a0d4 GIT binary patch literal 2882 zcma);TWcFf6vvM&+0la`2GcfaE>%*ec5qP(ZC*+q5?@jREmo{c(judbc4xJNXD{6y zIrc*!pgsuH2R)Qh3V{~%(r?hmLi%A+=x1npj&{Y$(u~pvNvoaT{?GrMIWw~_N^sr& zqN#W+St|;gUf1ui=7Wb{?N@8{o$_v_0{wLWxVRHUlKFONcYC{Zr~E1OHvwM1?b*i- z?>6*r0{mUtD&BY>1GTL?P2pRzYx8D&7Js77LLQf0=-)`8%kxk(R!k9dC1uuU7!lCu z^>p;znNi2`l_cOJ1jvylVMj+6VF>*X5qyN;6;zt34D&mZCltv!dbub-$0G0( z@D_p=g4gEd!a(@yGdmNcuo{2NaePljrx_^p;0d=>5KR>SZ{!Vh*hayt^A3YZbVQm6 zP2{(T(L~PF#bvRZm?MbHX&@Exw02bC4nmp=E7qP=m~0WHu@y%uKE|e?=^~6GYOoW_ zWfS*{)Es_Jjiyzj7Eh^Bn&eHBW-No$8MO%2RWqahxfWRjGLK6Ur-~G|t`BQr17`&x zNRxsU_>Smgm@!i(S*k`MU42L;ys5?TRG+EGy|xUj<1DCYP7&f$c~a#x<@E!5s*7p} zX}V};rjGPdQuwJYnt-O>zfe44xTrG!l&Ge*m}tb)+EUR>ONFyA(W0Orc5wp^HGVbjv zLRTCEns;v|v3C{$79Al3TthE(%)EoU)ATWuG%55yNXOrs8Al7k$9&903)c)4+3Ye_ zc5(=rgV<8ENure6xHMx!1RnDRc7_>o#?`_@%4{`D##D3>yj?{KPpI*+Y$~e96z=!t zf;cir&TP}E-156}d@36On>%9*3rdOznV>FY`i36A&t$93aQvTt-^rsK{Imtjt=j&R zT4DEKZy&Gs?$_=Y=xb%~%fo|urO?``R`d9QpD)1gFCn)C<12u|^5p755#W~&|NnvYhu-rw=;nKW{#zN;R}TkY7ayfs_}KWFHO;_8Pd5fHFT-fP aksod0=WZi6YBiQdr;Wns$Hp=YDCB>Wd&*e= literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/INTORGN.obj b/CODE/RP/MUNGA/opt/INTORGN.obj new file mode 100644 index 0000000000000000000000000000000000000000..551eab2eb9df8ca24a1b915b1141db23919f586d GIT binary patch literal 4647 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 h_2wQ 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/MODE.obj b/CODE/RP/MUNGA/opt/MODE.obj new file mode 100644 index 0000000000000000000000000000000000000000..b5415bf8280e1abfacf5a0a270f973f9b9d839e5 GIT binary patch literal 2656 zcma);%WE4~6vmGpwiW6=i1Tn-J5^dGBqW%ClTBB0Y|$2KqSUhKLqfTlxg%YC=i!+< zioFYzfP%8{DwIONi)^~+N{3*aILbmTCGBF4gfxW;QEp|W^wiQ?c)8VyU_a*;O(UA9&g#V zp!Ws9J6dT1*sjT!I-WO_diMyS&(6AFPFu#*4V1Ewx_XxKUB#4eok;FFf(C+%XF<;u zj#@S&jsz*JMvz&SV=I3*0fipyaznZPiQ@Z4E@9*r3ND;===!29;zX!;KOv?mUWWyp z$Q(grP6H{QpQ>;hAx(u9Yn@b>Y!Rig75FOHR#8O4D53`I8Xb1xev+ESN7SgT8nxh* z8l_3zG-(FXjh#_PsjixiIwMD963A>WMGz}e*iC&{BT#-)5P~!*7_MW9c7mm5$|Q@` zC}c+;QVILiFwk6SGPSwglCH6x1WoHHLi|*oR5?v~osl`MA*4A)W1VW~rKE6TThxHM z-oH@XXE;=ee@awSTTImFac!w+X`{lK7im#Y>XW8uCU1pp*RmoI?`^}wrb#qVdne;U z(@xej_ZhT?r^8OvXkIjGU6UymQItVS2Rs?ZX_B!NDdjUGJ{;GOD&8zyyMniumT|u> z97BdCucIaW;}{TnS7YYV7{erX0qGe_XbNJp$;wXlonR+D7XiZ0y$SCPUNDxf%N zMYWm2`+a&rEa@^F<#eFwgi=lfOl}P=r1#B4ge2$`GW~%bK071_I_0N7dA7)*6ui6% zQ_WiChgyCWA3AWowo+Tk)5rAM*WW+ftmc~!Ha2qjhF@pk_W&|k7_Kfrekxi4%oG6r zI1e9|*YSR}&K%a}ei^cP_-z`dk8{UacrgzjluIp>OJ3UXx=?6R_YB(u*vGnOE{$AT zY8lEe?SvAaeqetA_b-m^o3!7(K->6RmsuRyuJJ&9>ja891~2XIbng*%2eIoT7@6G| z4#an^yB&IHY}fEYSw{Te31k2^`~UPSg*W&=K!0=gc{SfSjJ|s|P;=4u|5j!*YNq;@ zm>(O5`?&unUJAIR^+vz(Nr(3OmDvdT<*&lCLHN;|+%dj}=+BMA<-eB)&*yLfuP(z; zp*F}I74hTsovrNAH?{2RM_V~KmUkaj literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/MOTION.obj b/CODE/RP/MUNGA/opt/MOTION.obj new file mode 100644 index 0000000000000000000000000000000000000000..41b03fe5a02476948f59b9e00ae98076645353ca GIT binary patch literal 3218 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 H1_#K0G`aza literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/NODE.obj b/CODE/RP/MUNGA/opt/NODE.obj new file mode 100644 index 0000000000000000000000000000000000000000..9ede06b7babe4dbba24854ec07a93b5628856f91 GIT binary patch literal 2744 zcma)8&u<$=6n>jHj-`emgjygp!7U~Vsu~KRJ#cdCM1TaXi5&}CM`pY`YY(0Mk=?OH zZ%7Eqk~!pr5K^Taa^coL!BUX;Be?p|NSwKr_q^+F?94i~VrzEi+wXnvd+$y5r>n4H zeO6aIl&lf>b*JODSpEKk?VZh1xeUEG0pRs}ULcukfQ4JnA?(kv+euPTL(C`5w&(66?lp%;kgm;0|c4~Ts;r;J>jY?DFlKz!$OTkLsb4*>&0liPL~oz+>;Q z4yP>yX&hFpId+(25lSN~3{?17MG*-`5jC)`*=A$)v)F7t!A51(u!U#XC{5C)Ni&pQ ztc+TOeAQIcooJC+K<02M!kCf5?&-stp$Za12&75D^jurC5?E@cOtP4bLbmlGm2l1s z!}t139qu%xXFg7XrqvWd{7jzYoW@?)v(9u;6+xOVnyS>ko=OTgmPG}q>-7u81BOGD z=%++A-eRHwkG&<+(nf_dKjNaGR3}Y)SiIS3dA1z^XN*gzo{YzZrk$i|&KZ=3-Qgr` zG%p(4x)xI`LQw`O74T&zPLqVCP^o~KahAH;O$xpD;{CU#_ECaxF`slq180UzPFEQ!OL(&= z5Fka95cycf+fy=x=P*}bXQV^yky}{Bbg4-)X{HPBViqYJp+bt2W~##!p7-g7*wSM- z%IScH+mUi6z~c5uLVDdSgb)RFA=5YX=(XU&hE84^=8+11+kk~eb?4h^riAYkxZb{7 zy_=z*?Dpro5BAEL#=S~q9>4JWBK&y(#vF`R0GWmHYB2}!>=I;)_wl?c!rT%(yAG?- z)h;)==yKXAc@EayDjW#E3&tY+k%jDw`4@BWYZERN3r&klUO2$L7JV>+dX;E6?#R{QOt$Z>$qQ|K!pB$>A&R|MHJoiyr#{Uh@36vt+2n=<+)xL$3W3 zc$$af*J=yHE7gH)xq2_ US2f^h2?p31NV+vZ+CHw~e>k_2qyPW_ literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/NORMAL.obj b/CODE/RP/MUNGA/opt/NORMAL.obj new file mode 100644 index 0000000000000000000000000000000000000000..56ab1784907d27a9b681f3148ac418a5d8c037db GIT binary patch literal 2621 zcma)8&ube;6n>6nN0dMfX;ZsxTqSjljlr}w=^-aMwkb7Ltk_maTN!n7 z#=Zr75o`iJl~O45&`bY}5dQ%_+Lzu6HspU$-rHRvMVj3P^kbR%=6m1!-g~?Id=@^p zA67LFB&+$Ys@ql#R(-s^Q(F6BdA(eQ&TRnr@R8?BrtHG{(o*5U^4HM$3g9aHWc{hT z7~!r3UfmrH(pEwra%;KSYC&fX;F?Yt#3;{qnT%myBJ2smJ{zTDsv&udnn#p_sM%4J z?`fumr(z&xac!B^wLGEps@*4~um(crILg)jQ6EU@8i1Ip_WT~>`$o?2#q&i&B#GR| zM1I1!pN?kSWI;0)M<5bs0BN5m-jTx%1Q{IGtlo2&WD&|xuE5v9fsP{*j3OFfhgOsI z)Mv3d{2ewbtAQ;TV52lin<33WdWkY>5$ZQXq0~Dqk_BWgmm)|QDQv|Y)(W)WH-tcj z6f93UqS1$?X38W>*eGPv98wE+U>JTeXXf zT{KjweKVC5Dv?D6sG9W)&3%SL)z?pn8ob3seV%wrrlpMvXRVlvf>NCf?P2qJyWu%b z49pmpKp*$Ug{GaP8Sa884ZFkbv(da5Y&*1>W-*E~NU16#;szO<^ZSyKh!VkxQ(3wpzcZM)bV((-DEPdRt-W_D5wjWxuK&sjkuvR z9&&?kBI8H~zb(K-ZEy40UT%GRV-v48*7nwN^fS5f-OhHUoU1+B-5tj-{C*Su>A=_x zh^_!~6TPdOd4NAAVX`~ky#X&4VZONLI70Cf!;U*DeyujhXCkG@$M+yFRz2r#x< zd>p-!6iaQXMN1ynq5}b^6W_*rqet=Z3Lah>KAdsr8NPb`^#aBKD&d=O^Hx}y3QPG* zxcK0*n7i1T`uEjkF@LdD!2cOs-O5GFA0^9k`2S;$*7MQ&bh5q>zM`G{{_E3IPsbocSK%$8 Cnu|yP literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/ORIGIN.obj b/CODE/RP/MUNGA/opt/ORIGIN.obj new file mode 100644 index 0000000000000000000000000000000000000000..fe704d2dbc170ccdb3bda2a1c2e9a4b50c1b9d21 GIT binary patch literal 3839 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/RAY.obj b/CODE/RP/MUNGA/opt/RAY.obj new file mode 100644 index 0000000000000000000000000000000000000000..1f60d513df7996aa5a31af42b32a8879ac0f0bd5 GIT binary patch literal 3844 zcmb_ePiWg#7=MoA)D)Kn)~;ETbjg}+T?=7d=oWTznyBqcMIHZ9)-9>~Y)iIQSyH9v zkQ@qyFqWbkdg{htV}~?!u)_|6^)|8ucG{pN2MM~&jAkS(hi>GMfg$^zB*%^;dlUvy zEb0B;@B4kf?|V=0RwsHX^X@p|bqOambv$2?vv@o@bfted5<#;sAcPK{RWu39nV#WO zr+UuxzlmmFL1?YXv^1B01I@mQ&^o>A-b=44qD%%d{W(=dvweWe0PFHih#yha* zp-Xww$%>Z8l0$bKqEcAr-l!@hTN70D&Y>WSWRg!mpSWJv6A#NZJY7{b>a7gRS;j)hChFlWB&zYQx74&oONGa(!$pJAI(f85 zhEEl;iXb?^Cd)-9)0O2yS38yFvE73-=#G4qjjk6D+a@!ZUlmCSMYAuv<45YoL4qhlK8+DcSToe*#wvA^5tU{X0FcBKMfA8bI_hMIN*>E1bVg%{ zV7moXY%H~!Oe51p<-b`ZF)tFG#%W|~9uwH_8yg}>3WlZJ7?6|;5*!4Y05ZH_OK4oT z3_vIa?LzF`(Dq@A8Mul+D6VtFDD|c z$+NMTA1?ISKJ<0S?`uK!9YU>v%H6&oLZ7#xwr&4*3%YY3SOlEX;YYur5!4mtoDcO# zcqo(UyP-`DR$h?P==iSDSQ<-wJw`yiRZy&uqN|P6^Ym09Y(XNTDoyW#2q=_Hl7f~} z&e3uqbQiq#b%djMIvmlIk3eGI4MBY;VjmVq;2?_b_5@0qLkM(}4}CCv9)`o=bE2F{x~h^xs;VhCovYPV8RLvXyD<^mE`*A)P_)Qyj;?_gG_w>k7K@3^XoRagU;WTnomjl<&VxBIg9$|_ zrh+IAhb(5(3|h>Vd7*V>!D7nhh2YA9J<*=G#my{j8Eg<{LRa*E8J>cr0{Ui zycjed!QC+n)xTd^Ft3HIiL%jlo7sX0zjpPxaf4>}Gm!jS>C1!new_K;_wnPxeyhzY znK#RT2N74VT$xxr^8KShTf;_-8#5-_jhi4LIK~y3jmS;{=Ry#e-JputXO1Fv6Cxj& z1IKK#4LZy`bA};VI&7T}nU_N=>(&GaE1PWD3OoS3$!@{BPRnn0e*=%8PY+swZ{haO zZm_}fS5g2BO!Lny1fmGW~TL-vFbueYCwDOPDxjhhx zR=Tl$dti(+677||;Mrh0B1Ym+)L^?Dl*KHY?DEV~yPceAvL+>aVzN(G7WN3*@!0nE ziv*fG%C*g%J=X?5d+;{%~7g+6&`&O^Qm4|Bz-hINgtbPi=B`$FPFD@|O f%lZB|8TZX&u4VoK*E;_Yu3zB#n`=P^Y@X;}xZ;V) literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/RECT2D.obj b/CODE/RP/MUNGA/opt/RECT2D.obj new file mode 100644 index 0000000000000000000000000000000000000000..f8f05691adc557572e535072165eec0768dc6292 GIT binary patch literal 4316 zcmb7GPfQ%w8UL1j#$!A+RIzIywu6(!Hic3Hwkma#2v|13M8s=$*)E?_MXa>dg#H9WHtT1*;%u&Z?`To zp5eXU_xt_6KW}D!eF{$Gf4RVQ*VHo3>O!$(Eolog@mOkjVlb9S!1{9l&^~TEre@`P zV*UL+7YEP7dN06t%_DQ^VjrxZ0r-c3cciW8x|i4+z}zkO485@1*^!N8@tL) z^Q|&It1{IkE3b>~7)wTw$cqS@M_6}#BFmb)Tro!=GA99XM-OU86<$J+q{3XwRx3=l z2qkHk>u~oSUQr|%DN0~#xn-^Dz8PCV-@`_2m9V)rY?LN>lcedIcHoRUN_CZV)Y>y5 z&45}_Hw`ynB-vTHY|iD*Zb1knNg-!j1!HL!)-Y4e)B-k=T$W36qgZnoekISes28)Q zoqK0jv{6qHq}Sw0m6Md$vhy`lltPeXiuQGCQBGwVR$z-7upswuaNW`HA+qbA5|z{z z6Ls{Uwp6r6M@83GD_kT>eUgkvUeA`6>_VXeY;s&&ezSU9=(LkH$#Vv+;dB&t+337T z%C?r*xK=??1`Rr}YLV?+ke3>CStOPA*j zyBP%nOe0H(p1?-uJ{yKz)GPxhqcNo5R|~t?*y?UFjf!sA|C_}$iUxN{r%_Rh8pr2- zGg~gnHz1O~V44!|<~@xd~&<$jhsNViDLGfx-VLh@^U9 zN0!-}wo}wh<6XHLgf7F*88}@hmeO5*$#S`7<@Csn>uV5dgPlHzj7GAiyNqS}MR2C1 z4ZQ{*wnFO<;U8MyHxoEY?sbR5k4J-$Do3t<$%NKSroe3z)J%q#oUHvCohpEh69A!O zqcb>F{`ctc1hV9~6G3bEvoVOlDLAGrRA z4AmInLn(rfAbemC{E~&QQ5PM{qb`In>MTa}R0~pD)LMnV5faaG=;R*${XL4{f!rK! zLGY~j=g7AruG|Cs1H6Q?cy|NWa7E0jUWb_N@DfZ+AN3{`G2Q7+s{8h*JG@CIW{+ZI z?S4|kF;*3eifD^YDYq3d#iCQ{E%sUHVav!@cfR7Ud>#@?bW*u}NKCTmq~}t zPp{lV@hIWAh~i* z%qlbAVSVBKFO|eI+&ty^1Ld-K7d|=;AOAb8e*7d=Zu{gwTK(h*-5gJ=uz3o~2%_1+ zzT^0`J-Y8HVun5XD^3uGZk~ZMj-6k;X@58n)D`abI>jZ1xbW9FNhs(8@jbH_*xlcS zz!`?v{%?@b2lhgl)dAbL@B7I1?WZ_Y#`n%%!mjr1igf$-6ss!tLAkX8Op8*7So9kl z{{5r>cp(vEbRA>jkJo(hpF;Vd4Et(;y~S$4DJbLn4jo)crr#pok|Ltw-lKnsBx~PJ zvhbh0_>%|mC+~mx`0pno)z0`=@fU#(zV}*v2j6?IG4bcjwYRTQHx9v8U;6OYQ2GdL zwnO=lFH!B)W)8}2{tB{IWLI7lE?XH8VN_drxpo@7_+v5sIQ>@D($ihC d;Cna*TQ8*5t>N^KwxW1_9j^(T2Z6nY{{r0>n)?6% literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/RETICLE.obj b/CODE/RP/MUNGA/opt/RETICLE.obj new file mode 100644 index 0000000000000000000000000000000000000000..3217a4a1d7b67b22ccfbc5bdbb9494c8ebdce359 GIT binary patch literal 3888 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/SFESKT.obj b/CODE/RP/MUNGA/opt/SFESKT.obj new file mode 100644 index 0000000000000000000000000000000000000000..c6c4b32b22ddd7521f372836eeabf164c34599a6 GIT binary patch literal 4389 zcmb`KPi)gx9LIlYLu(+6mbOr!Eolj?42GyE6EF__4`>WRZA?2_GRJ;tJRCbXP6nGM zO+rYmyaT6cnugRvt7$t`+GWQ`McN(hw$mgdfi&&7YxjHp6FZ5Waahz^$$KCFe&65s z{oZr(^$-k5mzNAuQiP0NTq=~+6=8{;n`J-Z&Q7P(u-XFv`=>Nr5mYHTefo6r!r61M zdII2e>pNHY!YNoi4)EqSzB}5SL{L{0ayDNq!s#7r91d29XlS|@@oh7wP+=AWhPbNf@`~&hGJ@DAh#hGz zBrlZmjyMWYaUqbQ6W2THF!egbVMEAz4pUi_3XxUPjnV_d$w)DpF$AlKdBIcPDq4=z zMWf3a60H=7M$4qyLdq;DnyZYq2=z5&Mb)|%X$1-eqR1sTB29ZIJgrzVbl(sPg_Iy_ zYEEA9vB*jVMR23hl=<+KhFl12hEKyQEs#Q1(ZmOS(x^2>hy?1S&V|^kYEqz!ID|sF zs9~j+!$T>u>dK-EuoSLeHi$0ZrtlYolo>vZ=SEh%uq3OZQkKXPO2R*a31M}}Wezqlf`Yx%3J{IQMa%=MgKmVrh6qlR z!s;=1{!qg_N|05oCz{CMo}ng3t1KCkthEY(fFfrpk#uGBH^`8+f}qOS8PQ12b_-WA zTB=`6lwQW+tUzo( zYz;!cPt2-PRlM|DNj}?ISR*pvL-GR?S_QyA!|P%&_M>i?|_b-_MJBP=2F|5GmW|}VRI<8JLHe83@H1dsz3|$kh ziD;RD)=uSjmRFR|};Y^=5lgf&eEso#BM=uO}!;?}|6BNhO_-v@f^qQ6~ zkdrOx-dvk$%6hnwm?s6TVq1Hxamo|+fl~sUX#}tyqBl9^s)T1p0b;$u*79`XSpm=R zScwe;XB)MqDTU{G3^n5xuQ?lZiz1_lpld$D5`RN~jOC>s%EgL8Q9N&B2W_L( zzQ()Z$qVNE%ir+S1XyDkbNk-%w#z*I!x(ZVK7$(j&uk)QbUGgwebyZ?r z6M&^H*4LK*5$nv4(+mFNPg8thQOn!#d=fVH@%>gmSKVWc;br3ze{ka(zjtGiKeX{P zKWP2JRb$qlc-idck8CFSy_;kF(O0**wpTpYwt0_F!1@B7{it*OZMMX2H$(T4m#U$n{K`7&6*#jH5L&tmv@tOUQ` z>f*bsUcQ^!(Pj;B)pje%RpVBQtM0N!`2*G&zQ;Pp_gdq8pLLO|c34-qYNs{9RT*oB ztM0b0@dMTke#lC5F<9?~D*A#;j(wFjVJCfY5gn()*u#P0E8cLtZg|2Q#>aesp0S7f zq1s^&(=B3mX?)S%5wMO^o%K^pV2Y`qN(82M*H3kMQ~RL02Y?<__Urj>&$q*1VuA24 DvgWje literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/SLOT.obj b/CODE/RP/MUNGA/opt/SLOT.obj new file mode 100644 index 0000000000000000000000000000000000000000..fe638f0d8f54c641ff39f152e7be28d7231fdaae GIT binary patch literal 3609 zcma)8O>EO<7=E3mt@}giC=^->gsq#HkkGWkgmy}s7FNMZXi|%AEtwNLjf;PR{Uw7N z5<*I4CiO5)Xj&yE1!-tIaOAK zzB2}+(#K0owp1}^mY1}Oz9KGVE?>!>Nu|?J8v=m+Q--OEx|B$rKAkvs<^!m`1Ms5V z_f`b$eFydODz1+1bs*|1s(hwYE<^1-fR{x?9p8&G4JIu#m);M62YA zBM^xT0Wnkda))(zNx2TmFcb5BhDjEoLS$Jcvu-fgBf-dH2&`HtiN5-FY(;q&8_slCTIWW{L%`PA3tSIK`hF z!Q&-gIJcze1+^l{ODGBdWpoI&;~r+X1tY51JM91kcDsyzpmxk-IMl-6HYwCjc=p3B zc9fv#7*8}JhciP-j#g73{BJ(?2Kqg(a9E8FC?%_cqFAA>Qe(0J?c+HQNO}z5c4NAK*zJbR{$R6Ox1&4^Q?( zuXA@9k1E`W!?#_~wcW8DgZpD#UvfMz$*Melvs{INq=Ug7W{%&i!mxXvl`S@_TTIjo z^7t*>KkDNOge!lPagN>c*)&cy9C3~FNGe+L1=G-Io9G6UE|6Th4vzRcdt4myE#rCD z$=NwPwBcm(Q&}_2+f(#&Fopcc<=86-F+a%dOLMa5)cQA!x~bnU6fg>VwwnZ%8hNp5b^M54zCOL-x+(Ew`T^^ z_Co)B<^{!c_gVjMI4c15=I6_s>x2;ybng##$=kQ$6OFYCybE8nFU0RP*npkk=Y_P* zZ(rq+VHJEb{?$xB#|G`qbcskk7yNaP+n(Xm&felv6a>qguQm0jUsFsxcRjCVct@0n zK}qLb1L{e|?G#T!@ZG!Gk+ui758Qpmw+iX@RFiurHVn-Vgud^n@Z+Z3IHW_nNhf|^ zyTl{N&rJ~7qWup-2c2vRFTVSCdmEGSSIqu(E#-zxJ~3uH&EI>@I_)Wbd2^ycT1uxd z{8b5G2Lrmh&kmw#eHC_Y@td%*2=%vwuI6aA5o>;kmwHm@u3s18O(PqtGhv`!6FTeP z3%$*svJI~J3tsAf3Vi*Q(DA58=-Hah#vaWH`?kKy#tNzJm8u3 zrhn99bT~QqhrJNTMdCh{a-$QPu`CC;i6e{fTbd#O literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/SOCKET.obj b/CODE/RP/MUNGA/opt/SOCKET.obj new file mode 100644 index 0000000000000000000000000000000000000000..1532ac145b79564701ad0c156110f2e85addc516 GIT binary patch literal 4575 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 O#8kugaEU)X1j4`dAnn%x literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/SPLINE.obj b/CODE/RP/MUNGA/opt/SPLINE.obj new file mode 100644 index 0000000000000000000000000000000000000000..b6b7b888a3de4ee19d7e616dca6cce8c093c5609 GIT binary patch literal 3252 zcma)8-*3}a7`@A z_QJ$VA`hug6PmOiFPpUgU=Mp>0%`xi9&BksJkSXw9(X_#laSc?Vuz%yolVWx-rRfc z`Mz_$dtG1M!**5QpA(vE@&%_pS8G^{e6EoHcD8=2}kR3m>Ln|u;7)B!~NRj2=|f*GZKt4 z##FzoF7ZzF{n&JE9UHYZhRy9^BblTiMy6}pQDxLo@-?QT*199o56EkpX}A$1r7gv$ zRbAn94IxmB1l6{5W3dZMRLV^ru~EvU_>{t^^<0LF@k(o2tzz2hrEb!sD+rL*qm!JA zvDdPzJ*TJ$P|PXX(5d-&DqQ)fENZ}9eEo*d9F9xXt)GO(cnhJ97I{miC0!Mb*F!E! zN_~ns9#yTG=LI>(* zBa%slB~S^6t5Ki!0yT0_-n$dejf#3|&ahOoQPt*95UXl-cW{N z*SKZiWF$lMwp-|8a;aT0Nv0e2f3uiI%@8i-Niwy@1)lfGhUlivag~z+3s%E4`vR(( z-Yy}zZ&g5uf=(fiKhW(ri10x7dH(mlVGM$deSMIn7m7-`DCN#gC>T$S6~`p{H8k4Rg4R>UMb_v@9-MK-t_ih zz~ApFvcK&QApDd+6buLBlCMh9%$Ve#m4fp2U|jaq4s1;J&&ol0BpCGf`P+Q#4ASlW zFWhMVS^sIqL0fm1XZ!sZ}2KrsUS-L2qko zGUI(DwI+9YGjc0`G>6sgCT$4o!_7cDo9a#?ktst zS!jX|(iBcpQ8YaQO9rFK^i8n%P(_+x3uJ}paDgsBBLYETUfYV((6s)9@j zzoMwnhVW~m&Mb7^B%Rl8-z|9avZrKP%Hu$J>`!Nc`A32Bs6BXCxL$fVgNB~JPv%^^ zoe9!saDm#3PlI$e9Jjwd@suYm@zLzS U+CRnAU+H4%r(?4z=AlmZFG;v)h5!Hn literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/SRTSKT.obj b/CODE/RP/MUNGA/opt/SRTSKT.obj new file mode 100644 index 0000000000000000000000000000000000000000..04b1ace4afa4a99e9ea1e1eae10c6504084f94e8 GIT binary patch literal 4683 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 i|Ni}S8d3mh3==8GXKMs!0299v z9I8Y=1**s`1{&}JbiXupnI67 z934XUQjA%g!Y~JWXBNPedu{Xs-HS29!W6@>Num2qZ2x-7juM22@uVXRoEb`Ty2?;m z!kD3~kU=_leFt)eUVfx! zOZT_RxZm2)H?p+kw{AbYU#nz|&1yA+SKipZx2+omS|htrenh`%rQh&o9{&6pv^j`& z1<2+`yZJ)2+s?xm$40y3Cjj2&AwS3r=AegF)XuHn=F<2nzz2a*;ep9LY1Be)E&aB; zjBh%<3y4`*ukMACyCphl*OwZm4A6{J&^rrS=JbS_CL%x+^f0&DnF(99)sdF}%)@^d z32_C5pPxWTVeW*eqssANVnsCACEDTy2o*onOGrZYg9>N>zh`kf$kBRO+yAus&+1?M z<-)5|ukK`@9`<@Yycd1H&)p&jUhrd!)(?LV27||k!~MU}9^NfLU(@IM^LTxyYyCAn z)8EiDaBu=J&j2sBXoWvc0#>tt?oj|;2giT}6u&3yyBzfAbd7FeNuansesiCA{sShV BYajps literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA/opt/TRACE.obj b/CODE/RP/MUNGA/opt/TRACE.obj new file mode 100644 index 0000000000000000000000000000000000000000..14aeadd13712f7731e297abe78267afc581c72dd GIT binary patch literal 2271 zcma);O>fgc5Qc{)O?%^j_$DRgOGT9;B-9JHG_5!`v?(AI6gKucS#`Z@*_(*oI9lS4 z5dVOGMt?<_sW)<(>>8vbvXm$9yz}mi<8MuP7`_=8o=G-LlR-RHV>aj?ce;n|Zm$RV zEdaQ=uT#lX*y`@?w)WbuAb$q%r}Bs5ef$#g7XTL@@M>$dL?k57Od7W*Ndoy(1m7X( z@WRws@`56{$Ss#@!;H|X0G}fmAlO{3n`oiT>#!80vJQVNid1aUuO&z=IlvhYj85l@ z|63UYycnV2qg97G6=Pu=d4kv{#2&0-6P8U1a|Dq&2V_!iv!jH^2ssiqY&1`pY!T(K zm8B*-Get$hsGe`4@fh^`y zWLA;Np1R8hIKX8f1UXs=w2H*I#Jrs{$*dZcoVZIG5icym7k8&Ik4I7mXJt{}nIgm& z`lRF>@hTlIOi>>p#}qA{)MvMp6w2D70~omd3&T@}OI7-(MjhE=qbax9QfR(a;Vdb% zs3@J2V?07WnvQi86=21>WafOnF0}1r&2gVWYu9gYv@ed>W+5}Is7W1oP9Tv}+a?+F zNSTxc_MEnnYVB-p-^csLDA*ea707AG2WSaj91B9eWtlrm43juJRX||Q6RZPy(<QgZF!XAd%DzSJ@8?)l|w#Amq`N1^>B)h>!$LA#)G( z)e}UyM4nk)c*3Zm7W~+O^-w b05{gaUe(vSzm zI2q%~tKYz*313DNzXLu`yUmt%wwScdr2Xyx`9E*l{hWsd_eIt4NU~ZORQ;A}uxj~W zt57Oew$}>#`w-s%fNR@2luWt#!s=>%W9>P_PXK;jb**^oKZSS+;LjU8-5Ut4Ur`B5V7}&-5ti7ENXVm5k%%JkO_HGJF0L4Axnh~tM@8QwurLW zib4||nQlbFD53>xJ5APeKT6Hxm(-}O7PY8PjnX7QY)7q9uHB3<&W;!rUBSn8eu`1vus;z&H@k zCkk@|3f&=v_(Agft%2Xsf>4-GHc`W!p(1CyjEpPvCSi`iDwWU`7b^wla-_`*aKC#$GFGkCwxE{G>J!&S}(YN{pWNWkS@$3k}BTtrBM zrjXeOy7PFDZX3<2W!o-4K1`q-d|83XT6yPPIak;#?%=t&Ro=?c$5e6mV6U>Dt8JG` z6ZnR&)9_;!#>Sy@0?1AFPSZ00-=<*dV&Y;P&Yl5`Ep1jJ9=^m|z~(MDukp``&aad( zg2|Hj#FvlTcoCejp_i)Jv4~aI?qrcRA^kG*P4eN)H*x06 zvfhNH5J?Z>K}w6#LqQ7t1A6GeA6w|Tr{qvuWD81r*n@{X2=;w56DFJeCJNci$L7iN zJn!?q?_{nYgem9alH!raDq*AKH)V~LiWkmWOJ-rNu&@BFy#TQ1bP#$>I@5*O+36E= zN1^pTz|&WJRV?`*K+@7m98qhk7xJ!t8XS*FHYaWkLDErJs)Pe1& zFi=d1K*m6lwe_-%KuC4mNeM|-L&#iL`YK#WfmDYEh&8An>@&Wu@(enxBH`rrQi4#_ zL{iAR2>SwIZ*PaySyYeB5s1ubKq}-(c9d`pL7IdWtM(HnTZGcsib54#QL!SyNKpe@ zw(G3#eiWO_x3E!LHEhuU8_EDrmclYCWgbh|NV2Y%RKg!vhOhLM`rNO2fqf+v&FU$F_&}YMoF-lwI0I8; zAxJYtL!Bz?sXQSQThxG(-oH>hWVlqRe=1ayEfyN`BwGqCYgIUF#9SmwebS7F!>i3& z;JPtz#JWW4T7O+=+sT^d_J-DQI{cK4_C*uhvcnXMQB*-j2O3^8DU*z4P^pmFNuLfO zYWhh2(0;scRP7TbA#Jbe@Df_W7e_&89Y`?yhA_;-*%<|})wKrdKx-;tcw>km9#Uu> zOg?{e=yS9nB-WFSsNl{}$k{F<<%nPu1p+)#CB$@MkpPFgJqy`=a}YulG=)q*(7lI< zc%Vo8`fqv27(+I=eFVlUmU-FA6)w)3c%DCHoyyVM#Qdk9Uo0-{!<-u@!K1aHbGgS4x`lk_Tpq9G7v1q+@k<^4Vs&k^Ti$G&n>WnoUGw>$ zlQU0AbagG?nYxdMzy7|v=k~+ZC&t%*G%vj-+4;>I=Qq0M#z?Z<@%#Ud|AL<3%l1Fz pM|g$npZxsWy^r9|epsKij33P + + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Disable interrupts, saving the old state of interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + ;-------------------------------------------------------------- + ; Set up for timing loop + ;-------------------------------------------------------------- + mov dx,JOYPORT + xor cx,cx + ;-------------------------------------------------------------- + ; Clear the port and start reading + ;-------------------------------------------------------------- + mov ah,PC_Joystick_Mask ;load AH with all bits set, clear al + xor al,al + out dx,al ;trigger the timers + +check_again: + ;-------------------------------------------------------------- + ; Read the port, check for changes + ;-------------------------------------------------------------- + in al,dx ;read the status bits + and al,PC_Joystick_Mask ;remove non-analog bits + + xor al,ah ;check for a change + jz short no_change ;no change, hang out + ;-------------------------------------------------------------- + ; See what changed + ;-------------------------------------------------------------- + test al,XBIT1 + jz short no_x1_change + mov PC_Joystick1_Raw_X,cx +no_x1_change: + test al,YBIT1 + jz short no_y1_change + mov PC_Joystick1_Raw_Y,cx +no_y1_change: + test al,XBIT2 + jz short no_x2_change + mov PC_Joystick2_Raw_X,cx +no_x2_change: + test al,YBIT2 + jz short no_y2_change + mov PC_Joystick2_Raw_Y,cx +no_y2_change: + ;-------------------------------------------------------------- + ; See if we have read all the bits + ;-------------------------------------------------------------- + xor ah,al + jz short read_done + ;-------------------------------------------------------------- + ; Increment the count and check again + ;-------------------------------------------------------------- +no_change: + inc cx + cmp cx,2048 ;arbitrary limit + jnz check_again + ;-------------------------------------------------------------- + ; All done with analog values. Re-enable interrupts + ;-------------------------------------------------------------- +read_done: + DPMI_RESTORE_PREV_INT ;pops ax! + ;-------------------------------------------------------------- + ; Read the buttons + ;-------------------------------------------------------------- + in al,dx ;read the status bits + not al ;invert the bits (so 1=closed) + and al,BUTTONBITS ;remove extraneous bits + mov PC_Joystick_Buttons,al ;save the result + ;-------------------------------------------------------------- + ; Return + ;-------------------------------------------------------------- +END_C_PROC + +END_CODE + + END diff --git a/CODE/RP/MUNGA_L4/L4APP.HPP b/CODE/RP/MUNGA_L4/L4APP.HPP new file mode 100644 index 0000000..0247a0e --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4APP.HPP @@ -0,0 +1,237 @@ +//===========================================================================// +// File: l4app.hpp // +// Project: MUNGA Brick: L4Application // +// Contents: Interface specification for L4Application // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4APP_HPP) +# define L4APP_HPP + +# if !defined(APP_HPP) +# include +# endif + + class DPLRenderer; + class L4AudioRenderer; + class L4GaugeRenderer; + class L4NetworkManager; + class LBE4ControlsManager; + class L4IcomManager; + + //########################################################################## + //######################## L4Application ############################# + //########################################################################## + + class L4Application: + public Application + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, and Testing + // + public: + L4Application( + ResourceFile *resource_file, + ApplicationID application_ID, + ClassID class_ID=L4ApplicationClassID, + SharedData &shared_data=DefaultData + ); + ~L4Application(); + + Logical + TestInstance() const; + + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Command line parsing + // + public: + typedef Logical + (*TokenParser)(int *argument, int argc, char *argv[]); + static Logical + ParseToken( + int *argument, + int argc, + char *argv[] + ); + static Logical + ParseCommandLine( + int argc, + char *argv[], + TokenParser parser = &L4Application::ParseToken + ); + + static int + GetMissionReviewMode() + {return missionReviewMode;} + + static Logical + GetSeeSolids() + {return seeSolids;} + static unsigned long + GetNetworkCommonFlatAddress() + {return networkCommonFlatAddress;} + static CString + GetEggNotationFileName() + {return eggNotationFileName;} + static CString + GetRIOPlaybackFileName() + {return rioPlaybackFileName;} + static CString + GetRIORecordingFileName() + {return rioRecordingFileName;} + + protected: + static Logical + seeSolids; + static CString + eggNotationFileName; + static unsigned long + networkCommonFlatAddress; + static int + missionReviewMode; + static CString + rioPlaybackFileName; + static CString + rioRecordingFileName; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Execution control + // + public: + void + Initialize(); + void + InitializeTillConsole(); + + Entity* + MakeAndLinkViewpointEntity(Entity__MakeMessage *message); + + Entity* + MakeViewpointEntity(Entity__MakeMessage *message); + + void + Terminate(); + + void + TeslaCoil(Logical lights_on); + + void + PilotIllumination(Logical lights_on); // includes 'Tesla coil' + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Module accesors + // + public: + DPLRenderer* + GetVideoRenderer(); + + L4AudioRenderer* + GetAudioRenderer(); + + L4GaugeRenderer* + GetGaugeRenderer(); + + L4NetworkManager* + GetNetworkManager() + {return (L4NetworkManager*)Application::GetNetworkManager();} + LBE4ControlsManager* + GetControlsManager() + {return (LBE4ControlsManager*)Application::GetControlsManager();} + L4IcomManager* + GetIntercomManager() + {return (L4IcomManager*)Application::GetIntercomManager();} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public data + // + public: + char + *divisionParameters; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Module Creation + // + protected: + ModeManager* + MakeModeManager(); + + ControlsManager* + MakeControlsManager(); + + IcomManager* + MakeIntercomManager(); + + NetworkManager* + MakeNetworkManager(); + + VideoRenderer* + MakeVideoRenderer(); + + AudioRenderer* + MakeAudioRenderer(); + + GaugeRenderer* + MakeGaugeRenderer(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + enum + { + LightsOutMessageID = Application::NextMessageID, + NextMessageID + }; + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void + LightsOutMessageHandler(Receiver::Message *message); + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + void // HACK - the 'int' is actually 'ControlsKey' + KeyCommandMessageHandler(ReceiverDataMessageOf *message); + }; + + extern L4Application * &l4_application; + + //~~~~~~~~~~~~~~~~~~~~~ L4Application inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline DPLRenderer* + L4Application::GetVideoRenderer() + { + Check(this); + return (DPLRenderer*)videoRenderer; + } + + inline L4AudioRenderer* + L4Application::GetAudioRenderer() + { + Check(this); + return (L4AudioRenderer*)audioRenderer; + } + + inline L4GaugeRenderer* + L4Application::GetGaugeRenderer() + { + Check(this); + return (L4GaugeRenderer*)gaugeRenderer; + } + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4APP.TCP b/CODE/RP/MUNGA_L4/L4APP.TCP new file mode 100644 index 0000000..d0bb29e --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4APP.TCP @@ -0,0 +1,82 @@ +//===========================================================================// +// File: l4app.tcp // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/09/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "l4app.thp" +#include "entity.thp" +#include "registry.hpp" + +//########################################################################## +//####################### L4TestApplication ########################## +//########################################################################## + +// +//############################################################################# +//############################################################################# +// +L4TestApplication::L4TestApplication(StreamableResourceFile *resource_file): + L4Application(resource_file, (ApplicationID)0) +{ +} + +// +//############################################################################# +//############################################################################# +// +L4TestApplication::~L4TestApplication() +{ +} + +// +//############################################################################# +//############################################################################# +// +Registry* + L4TestApplication::MakeRegistry() +{ + return new Registry; +} + +// +//############################################################################# +//############################################################################# +// +Entity* + L4TestApplication::MakeViewpointEntity(Entity::MakeMessage *message) +{ + return TestEntity::Make(message); +} + +//########################################################################## +//########################## L4TestMission ########################### +//########################################################################## + +// +//############################################################################# +//############################################################################# +// +L4TestMission::L4TestMission( + NotationFile *notation_file, + StreamableResourceFile *resources +): + Mission(notation_file, resources) +{ +} + +// +//############################################################################# +//############################################################################# +// +L4TestMission::~L4TestMission() +{ +} + + diff --git a/CODE/RP/MUNGA_L4/L4APP.THP b/CODE/RP/MUNGA_L4/L4APP.THP new file mode 100644 index 0000000..2449e63 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4APP.THP @@ -0,0 +1,50 @@ +//===========================================================================// +// File: l4app.thp // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/09/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4APP_THP) +# define L4APP_THP + +# if !defined(L4APP_HPP) +# include +# endif + +# if !defined(MISSION_HPP) +# include +# endif + + class L4TestApplication: + public L4Application + { + public: + L4TestApplication(StreamableResourceFile *resource_file); + ~L4TestApplication(); + + private: + Registry* + MakeRegistry(); + + Entity* + MakeViewpointEntity(Entity__MakeMessage*); + }; + + class L4TestMission: + public Mission + { + public: + L4TestMission( + NotationFile *notation_file, + StreamableResourceFile *resources + ); + ~L4TestMission(); + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4ASM.INC b/CODE/RP/MUNGA_L4/L4ASM.INC new file mode 100644 index 0000000..e76b9cf --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4ASM.INC @@ -0,0 +1,386 @@ +;=========================================================================== +; File: L4ASM.inc +; Project: MUNGA +; Contents: Assembler-dependent macros +;--------------------------------------------------------------------------- +; Date Who Modification +; -------- --- ----------------------------------------------------------- +; 03/01/95 CPB Initial coding +;--------------------------------------------------------------------------- +; Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved +; PROPRIETARY and CONFIDENTIAL +;=========================================================================== +.xcref +?insideprocdef = 0 +?insidelocal = 0 + +;----------------------------------------------------------------- +; Generate assembler error message, stop assembly +;----------------------------------------------------------------- +.xcref ?error +?error macro msg + %out E R R O R ----- msg + .err +endm + + .386p + .model flat,c ;; just now added ,c + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; HIDEOUS UGLY HACK to get around borland bug!!!!!!!!!!!!! +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +ifndef __WATCOMC__ + __BCPLUSPLUS__ = 1 +endif + +;----------------------------------------------------------------- +; Begin the data segment +;----------------------------------------------------------------- +BEGIN_DATA MACRO + _DATA SEGMENT DWORD USE32 +ENDM + +;----------------------------------------------------------------- +; End the data segment +;----------------------------------------------------------------- +END_DATA MACRO + _DATA ENDS +ENDM + +;----------------------------------------------------------------- +; Begin the code segment +;----------------------------------------------------------------- +BEGIN_CODE MACRO + _TEXT SEGMENT DWORD USE32 +ENDM +;----------------------------------------------------------------- +; End the code segment +;----------------------------------------------------------------- +END_CODE MACRO + if ?insideprocdef + ?error + endif + + _TEXT ENDS +ENDM + +;----------------------------------------------------------------- +; Parse/Save/Restore multiple registers +;----------------------------------------------------------------- +?ax = 0000000000000001b +?eax = 0000000000000010b +?bx = 0000000000000100b +?ebx = 0000000000001000b +?cx = 0000000000010000b +?ecx = 0000000000100000b +?dx = 0000000001000000b +?edx = 0000000010000000b +?si = 0000000100000000b +?esi = 0000001000000000b +?di = 0000010000000000b +?edi = 0000100000000000b +?ds = 0001000000000000b +?es = 0010000000000000b +?fs = 0100000000000000b +?gs = 1000000000000000b + + +BUILDREGS MACRO reglist,bitval + ifb + exitm + endif + + irp areg, + ifidni , + bitval = bitval or ?ax + elseifidni , + bitval = bitval or ?eax + elseifidni , + bitval = bitval or ?bx + elseifidni , + bitval = bitval or ?ebx + elseifidni , + bitval = bitval or ?cx + elseifidni , + bitval = bitval or ?ecx + elseifidni , + bitval = bitval or ?dx + elseifidni , + bitval = bitval or ?edx + elseifidni , + bitval = bitval or ?si + elseifidni , + bitval = bitval or ?esi + elseifidni , + bitval = bitval or ?di + elseifidni , + bitval = bitval or ?edi + elseifidni , + bitval = bitval or ?ds + elseifidni , + bitval = bitval or ?es + elseifidni , + bitval = bitval or ?fs + elseifidni , + bitval = bitval or ?gs + else + ?error + endif + endm +ENDM + +PUSHREGS MACRO bits + if (bits and ?ax) + push ax + endif + if (bits and ?eax) + push eax + endif + if (bits and ?bx) + push bx + endif + if (bits and ?ebx) + push ebx + endif + if (bits and ?cx) + push cx + endif + if (bits and ?ecx) + push ecx + endif + if (bits and ?dx) + push dx + endif + if (bits and ?edx) + push edx + endif + if (bits and ?si) + push si + endif + if (bits and ?esi) + push esi + endif + if (bits and ?di) + push di + endif + if (bits and ?edi) + push edi + endif + if (bits and ?ds) + push ds + endif + if (bits and ?es) + push es + endif + if (bits and ?fs) + push fs + endif + if (bits and ?gs) + push gs + endif +ENDM + +POPREGS MACRO bits + if (bits and ?gs) + pop gs + endif + if (bits and ?fs) + pop fs + endif + if (bits and ?es) + pop es + endif + if (bits and ?ds) + pop ds + endif + if (bits and ?edi) + pop edi + endif + if (bits and ?di) + pop di + endif + if (bits and ?esi) + pop esi + endif + if (bits and ?si) + pop si + endif + if (bits and ?edx) + pop edx + endif + if (bits and ?dx) + pop dx + endif + if (bits and ?ecx) + pop ecx + endif + if (bits and ?cx) + pop cx + endif + if (bits and ?ebx) + pop ebx + endif + if (bits and ?bx) + pop bx + endif + if (bits and ?eax) + pop eax + endif + if (bits and ?ax) + pop ax + endif +ENDM + +;----------------------------------------------------------------- +; Begin a public "C" accessable routine +;----------------------------------------------------------------- +BEGIN_C_PROC MACRO name,regs + + if ?insideprocdef + ?error + endif + + ifdef __BCPLUSPLUS__ +;; _&name& PROC C NEAR + name PROC C NEAR +;; PUBLIC _&name& + PUBLIC name + + ENDNAME ¯o +;; _&name& &ENDP + name &ENDP + &endm + endif + + ifdef __WATCOMC__ + &name&_ PROC C NEAR ; NOTE no trailing '_' for stack-based fcn! + PUBLIC &name&_ + + ENDNAME ¯o + &name&_ &ENDP + &endm + endif + + ?argoffset = 8 + ?localoffset = 0 + ?regbits = 0 + ?insideprocdef = 1 + ?stackframerequired = 0 + ?stackframebuilt = 0 + BUILDREGS , +ENDM + +;----------------------------------------------------------------- +; Declare an input parameter +;----------------------------------------------------------------- +?DEF_ARG1 macro argname,argtype,ofst + argname EQU + ?stackframerequired = 1 +endm + +?DEF_ARG macro argname,argtype,argsize + ife ?insideprocdef + ?error + else + .xcref + ?DEF_ARG1 argname,,%?argoffset + ?argoffset = ?argoffset+argsize + .cref + endif +endm + +ARG_BYTE macro n + ?DEF_ARG ,,4 ;; NOTE: promoted to 32-bit INT +ENDM + +ARG_WORD macro n +?DEF_ARG ,,4 ;; NOTE: promoted to 32-bit INT +endm + +ARG_DWORD macro n + ?DEF_ARG ,,4 ;; NOTE: promoted to 32-bit INT +endm + +ARG_CPTR macro n + ?DEF_ARG ,,4 ;; NOTE: promoted to 32-bit INT +endm + +ARG_DPTR macro n + ?DEF_ARG ,,4 ;; NOTE: promoted to 32-bit INT +endm + +;----------------------------------------------------------------- +; Declare a local variable +;----------------------------------------------------------------- +?DEF_LOCAL1 macro lname,argtype,ofst + lname EQU + ?stackframerequired = 1 +endm + +?DEF_LOCAL macro localname,localtype,localsize + ife ?insideprocdef + ?error + else + .xcref + ?localoffset = ?localoffset+localsize + ?DEF_LOCAL1 localname,,%?localoffset + .cref + endif +endm + +LOCAL_BYTE macro n + ?DEF_LOCAL ,,4 +endm + +LOCAL_WORD macro n + ?DEF_LOCAL ,,4 +endm + +LOCAL_DWORD macro n + ?DEF_LOCAL ,,4 +endm + +LOCAL_CPTR macro n + ?DEF_LOCAL ,,4 +endm + +LOCAL_DPTR macro n + ?DEF_LOCAL ,,4 +endm + +BUILD_STACK_FRAME macro + ife ?insideprocdef + ?error + else + ENTER ?localoffset,0 + PUSHREGS ?regbits + ?stackframebuilt = 1 + endif +ENDM + +;----------------------------------------------------------------- +; End a public "C" accessable routine +;----------------------------------------------------------------- +END_C_PROC MACRO + ife ?insideprocdef + ?error <'END_C_PROC' mismatch> + else + if ?stackframerequired + ife ?stackframebuilt + ?error <'BUILD_STACK_FRAME' required in procedure> + endif + endif + + POPREGS ?regbits + if ?stackframebuilt + LEAVE + endif + ret + + ENDNAME + purge ENDNAME + ?insideprocdef = 0 + endif +ENDM + + diff --git a/CODE/RP/MUNGA_L4/L4AUDHDW.CPP b/CODE/RP/MUNGA_L4/L4AUDHDW.CPP new file mode 100644 index 0000000..7c39097 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDHDW.CPP @@ -0,0 +1,1006 @@ +//===========================================================================// +// File: l4audhdw.hh // +// Project: MUNGA Brick: Audio Manager // +// Contents: Spec for audio manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/25/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDHDW_HPP) +# include +#endif + +#if defined(AUDIO_HARDWARE) +# include +#endif + +#if defined(TRACE_AUDIO_RENDERER_MIDI) + BitTrace Audio_Renderer_MIDI("Audio Renderer MIDI"); +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MPU Emulation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define _inp inportb +#define _outp outportb + +#define MPUPort(x) ((x)+mpuAddx) +#define SBCPort(x) ((x)+srcAddx) + +/* DSP defines */ +#define MPU_ACK_OK 0xfe +#define MPU_RESET_CMD 0xff +#define MPU_ENTER_UART 0x3f + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDIMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + MIDIMessage::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ostream& + operator << ( + ostream &strm, + const MIDIMessage &midi_message + ) +{ + Check(&midi_message); + + strm << "["; + strm << (int)(midi_message.message[0] & 0x0F) << ","; + strm << (int)(midi_message.message[0] >> 4) << ","; + strm << (int)midi_message.message[1] << ","; + strm << (int)midi_message.message[2] << "]"; + + return strm; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioChannel::AudioChannel( + AudioChannelType audio_channel_type, + MIDIChannel midi_channel, + AudioCard *audio_card +) +{ + audioChannelType = audio_channel_type; + midiChannel = midi_channel; + voicesUsed = 0; + Check(audio_card); + audioCard = audio_card; +} + +// +//############################################################################# +//############################################################################# +// +AudioChannel::~AudioChannel() +{ + Verify(voicesUsed == 0); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioChannel::TestInstance() const +{ + Plug::TestInstance(); + Verify(voicesUsed >=0 && voicesUsed <= AWE_VOICE_COUNT); + Check(audioCard); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// AudioCard +//############################################################################# +// +AudioCard::AudioCard(): + idleChannelSocket(NULL), + percussionChannelSocket(NULL) +{ + MIDIChannel channel; + + idleVoices = AWE_VOICE_COUNT; + for (channel = 0; channel < AWE_CHANNEL_COUNT; channel++) + { + AudioChannel *audio_channel; + + if (channel == AWE_PERCUSSIVE_CHANNEL) + { + audio_channel = + new AudioChannel( + PercussionAudioChannelType, + channel, + this + ); + Register_Object(audio_channel); + Check(&percussionChannelSocket); + percussionChannelSocket.Add(audio_channel); + } + else + { + audio_channel = + new AudioChannel( + InstrumentAudioChannelType, + channel, + this + ); + Register_Object(audio_channel); + Check(&idleChannelSocket); + idleChannelSocket.Add(audio_channel); + } + } +} + +// +//############################################################################# +// ~AudioCard +//############################################################################# +// +AudioCard::~AudioCard() +{ + // + // Delete the idle channels + // + { + ChainIteratorOf iterator(&idleChannelSocket); + + Check(&iterator); + Verify(idleVoices == AWE_VOICE_COUNT); + Verify(iterator.GetSize() == AWE_CHANNEL_COUNT - 1); + iterator.DeletePlugs(); + } + + // + // Delete the percussive channel + // + { + ChainIteratorOf iterator(&percussionChannelSocket); + + Check(&iterator); + Verify(idleVoices == AWE_VOICE_COUNT); + Verify(iterator.GetSize() == 1); + iterator.DeletePlugs(); + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioCard::TestInstance() const +{ + Node::TestInstance(); + Verify(idleVoices >= 0 && idleVoices <= AWE_VOICE_COUNT); + Check(&idleChannelSocket); + return True; +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + AudioCard::Initialize() +{ +#ifdef AUDIO_HARDWARE + Tell("AudioCard::Initialize - Start\n"); + + WORD wError; + + // + // Set the selector of the pointer to the driver memory for the + // MIDI driver to _NULL. this will tell the load driver routine + // to allocate new memory for the MIDI driver + // + #if defined(__BCPLUSPLUS__) + sSOSMIDIInitDriver.lpDriverMemory.sel = _NULL; + #else + sSOSMIDIInitDriver.lpDriverMemory = _NULL; + #endif + + // + // Setup the port for the MIDI driver to use + // + // sSOSMIDIHardware.wPort = _MIDI_DRIVER_PORT; + sSOSMIDIHardware.wPort = emuAddx; + + // + // Load and initialize the MIDI driver + // + wError = sosMIDIInitDriver( + _MIDI_DRIVER_TYPE, + &sSOSMIDIHardware, + &sSOSMIDIInitDriver, + &wDriverHandle + ); + if (wError) + { + cout << sosGetErrorString(wError); + Fail("AudioCard::Initialize - sosMIDIInitDriver failed\n"); + } + + Tell("AudioCard::Initialize - Finish\n"); +#endif +} + +// +//############################################################################# +// Close +//############################################################################# +// +void + AudioCard::Close() +{ +#ifdef AUDIO_HARDWARE + Check(this); + + sosMIDIAWE32ReleaseSBKFiles(wDriverHandle); + + // + // Reset the midi driver + // + sosMIDIResetDriver(wDriverHandle); + + // + // Uninitialize the midi driver and tell it to free the memory allocated + // for the driver + // + sosMIDIUnInitDriver(wDriverHandle, _TRUE); +#endif +} + +// +//############################################################################# +// GetEnvironmentSettings +//############################################################################# +// +void + AudioCard::GetEnvironmentSettings(char *env_str) +{ + WORD src_addx = 0xffff; + WORD irq_interrupt = 0xffff; + WORD dma_channel = 0xffff; + WORD mpu_addx = 0xffff; + WORD emu_addx = 0xffff; + + const char *sz_blaster; + + sz_blaster = getenv(env_str); + Check_Pointer(sz_blaster); + + while (*sz_blaster) { + if (*sz_blaster == 'a' || *sz_blaster == 'A') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + src_addx = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'i' || *sz_blaster == 'I') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + irq_interrupt = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'd' || *sz_blaster == 'D') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + dma_channel = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'e' || *sz_blaster == 'E') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + emu_addx = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'p' || *sz_blaster == 'P') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + mpu_addx = GetHexWord(&sz_blaster); + } + } + + // + // Skip until blank or end of string + // + while (*sz_blaster && *sz_blaster != ' ') + ++sz_blaster; + while (*sz_blaster == ' ') + ++sz_blaster; + } + + if (emu_addx == 0xffff) + emu_addx = (WORD)(src_addx + 0x400); + + srcAddx = src_addx; + irqInterrupt = irq_interrupt; + dmaChannel = dma_channel; + mpuAddx = mpu_addx; + emuAddx = emu_addx; + + #if DEBUG_LEVEL>0 + Tell("AudioCard::GetEnvironmentSettings: " << env_str << "\n"); + #if 0 + Dump(srcAddx); + Dump(irqInterrupt); + Dump(dmaChannel); + Dump(mpuAddx); + Dump(emuAddx); + #endif + printf(" srcAddx = %x\n", (unsigned)srcAddx); + printf(" irqInterrupt = %x\n", (unsigned)irqInterrupt); + printf(" dmaChannel = %x\n", (unsigned)dmaChannel); + printf(" mpuAddx = %x\n", (unsigned)mpuAddx); + printf(" emuAddx = %x\n", (unsigned)emuAddx); + #endif +} + +// +//############################################################################# +// InitMIDIReceive +// Initializes Sound Blaster to ready to receive data state. +//############################################################################# +// +Logical + AudioCard::InitMIDIReceive() +{ +#if 0 + volatile DWORD dwCount; + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; + _inp(MPUPort(0)); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; + _inp(MPUPort(0)); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_ENTER_UART); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; + if (!dwCount) return True; + if (_inp(MPUPort(0)) != MPU_ACK_OK) return True; + + // mask MPU-401 interrupt + _outp(SBCPort(0x4), 0x83); + _outp(SBCPort(0x5), _inp(SBCPort(0x5)) & ~0x04); +#endif + return False; +} + +// +//############################################################################# +// CloseMIDIReceive +//############################################################################# +// +void + AudioCard::CloseMIDIReceive() +{ +#if 0 + volatile DWORD dwCount; + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + for (dwCount=0; dwCount<0x2000; dwCount++) ; + _inp(MPUPort(0)); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + for (dwCount=0; dwCount<0x2000; dwCount++) ; + _inp(MPUPort(0)); +#endif +} + +// +//############################################################################# +// IsMIDIAvailable +//############################################################################# +// +Logical + AudioCard::IsMIDIAvailable() +{ +#if 0 + return ((_inp(MPUPort(1)) & 0x80) == 0); +#endif + return False; +} + +// +//############################################################################# +// GetMIDIByte +//############################################################################# +// +MIDIValue + AudioCard::GetMIDIByte() +{ +#if 0 + return (_inp(MPUPort(0))); +#endif + return (MIDIValue)0; +} + +// +//############################################################################# +// InitializeChannels +//############################################################################# +// +void + AudioCard::InitializeChannels() +{ + Check(this); + + // + // Initialize idle channels + // + { + ChainIteratorOf iterator(&idleChannelSocket); + AudioChannel *channel; + + Check(&iterator); + Verify(iterator.GetSize() == (AWE_CHANNEL_COUNT-1)); + while ((channel = iterator.ReadAndNext()) != NULL) + { + Check(channel); + channel->SendPitchBendRange(MIDI_PITCH_BEND_RANGE); + } + } + + // + // Initialize percussive channels + // + { + ChainIteratorOf iterator(&percussionChannelSocket); + AudioChannel *channel; + + Check(&iterator); + Verify(iterator.GetSize() == 1); + channel = iterator.GetCurrent(); + Check(channel); + channel->SendPitchBendRange(MIDI_PITCH_BEND_RANGE); + } +} + +// +//############################################################################# +// LoadSBK +//############################################################################# +// +int + AudioCard::LoadSBK(const char *file_name) +{ +#ifdef AUDIO_HARDWARE + Check(this); + Check_Pointer(file_name); + + int ret; + + Tell("AudioCard::LoadSBK - " << file_name << "\n"); + ret = sosMIDIAWE32SetSBKFile(wDriverHandle, file_name); + Verify_And_Dump(ret >= 0, ret); + Tell("AudioCard::LoadSBK - Finished\n"); + return ret; +#else + return 1; +#endif +} + +// +//############################################################################# +// ReleaseAllBanks +//############################################################################# +// +void + AudioCard::ReleaseAllBanks() +{ +#ifdef AUDIO_HARDWARE + Check(this); + sosMIDIAWE32ReleaseSBKFiles(wDriverHandle); +#endif +} + +// +//############################################################################# +// MIDI methods +//############################################################################# +// + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendPitchBend( + MIDIChannel channel, + MIDIPitchBend pitch_bend + ) +{ + MIDIMessage + message( + MIDI_PITCH_BEND_STATUS, + channel, + (MIDIValue)((pitch_bend+8192)%128), + (MIDIValue)((pitch_bend+8192)/128) + ); + SendMIDIMessage(&message, 3); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendPitchBendRange( + MIDIChannel channel, + MIDIValue sensitivity + ) +{ + SendController(channel, (MIDIValue)101, (MIDIValue)0); + SendController(channel, (MIDIValue)100, (MIDIValue)0); + SendController(channel, (MIDIValue)6, sensitivity); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendNRPN( + MIDIChannel channel, + MIDIValue param_number, + MIDINRPNValue value + ) +{ + // + // Set sound parameter + // + SendController(channel, (MIDIValue)99, (MIDIValue)127); + SendController(channel, (MIDIValue)98, param_number); + + // + // Set parameter value + // + SendController(channel, (MIDIValue)6, (MIDIValue)((value+8192)/128) ); + SendController(channel, (MIDIValue)38, (MIDIValue)((value+8192)%128) ); +} + +// +//############################################################################# +//############################################################################# +// +#define SYSEX_MACRO_LENGTH 11 + +Byte + chorus_sysex[SYSEX_MACRO_LENGTH] = + { + 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x38, 0x00, 0x00, 0xF7 + }; + +Byte + reverb_sysex[SYSEX_MACRO_LENGTH] = + { + 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x30, 0x00, 0x00, 0xF7 + }; + +void + AudioCard::SelectEffect( + MIDIEffectType type, + MIDIValue effect + ) +{ + switch (type) + { + case ChorusMIDIEffectType: + chorus_sysex[8] = effect; + SendSysex(chorus_sysex, SYSEX_MACRO_LENGTH); + break; + + case ReverbMIDIEffectType: + reverb_sysex[8] = effect; + SendSysex(reverb_sysex, SYSEX_MACRO_LENGTH); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendSysex( + void *data, + size_t length + ) +{ +#ifdef AUDIO_HARDWARE + WORD wError; + + // + // Note - HMI can specify sysex channel via F0, F1, ..., FF + // + #if defined(__BCPLUSPLUS__) + wError = sosMIDISendMIDIData( + wDriverHandle, + (char*)data, + length + ); + #else + wError = sosMIDISendMIDIData( + wDriverHandle, + (Byte*)data, + length + ); + #endif + if (wError != _ERR_NO_ERROR) + { + Fail("AudioCard::SendSysex - wError != _ERR_NO_ERROR"); + } +#endif +} + +#if 0 +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendMIDIMessage(MIDIMessage *midi_message) +{ +#ifdef AUDIO_HARDWARE + SET_AUDIO_RENDERER_MIDI(); + + Check(midi_message); + + #if 0 + long now = Now(); + Tell(now << "\t" << (int)srcAddx << "\t" << *midi_message << "\t"); + Tell(idleVoices << "\n"); + #endif + + switch (midi_message->message[0] >> 4) { + case MIDI_NOTE_ON_STATUS: + case MIDI_NOTE_OFF_STATUS: + case MIDI_POLYKEY_STATUS: + case MIDI_CONTROLLER_STATUS: + case MIDI_PITCH_BEND_STATUS: + #if DEBUG_LEVEL>0 + { + Word wError = sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 3 + ); + Verify(wError == _ERR_NO_ERROR); + } + #else + sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 3 + ); + #endif + break; + + case MIDI_PROGRAM_CHANGE_STATUS: + case MIDI_CHANNEL_PRESSURE_STATUS: + #if DEBUG_LEVEL>0 + { + Word wError = sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 2 + ); + Verify(wError == _ERR_NO_ERROR); + } + #else + sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 2 + ); + #endif + break; + + default: + // + // Should never reach here + // + Fail("Should never reach here"); + break; + } + CLEAR_AUDIO_RENDERER_MIDI(); +#endif +} +#endif + +// +//############################################################################# +// Channel methods +//############################################################################# +// + +// +//############################################################################# +//############################################################################# +// +AudioChannel* + AudioCard::RequestAudioChannel(AudioVoiceCount voice_count) +{ + Check(this); + + // + // Monitor resource usage + // + #if 0 + #if DEBUG_LEVEL>0 + { + ChainIteratorOf iterator(&idleChannelSocket); + + if (voice_count > idleVoices || iterator.GetSize() == 0) + { + Tell("RequestAudioChannel - voices: " << idleVoices); + Tell(" channels: " << iterator.GetSize()); + Tell("\n"); + } + } + #endif + #endif + + // + // Are there enough voices to allocate + // + if (voice_count > idleVoices) + return NULL; + + // + // Allocate a channel + // + ChainIteratorOf iterator(&idleChannelSocket); + AudioChannel *audio_channel; + + Check(&iterator); + if ((audio_channel = iterator.GetCurrent()) != NULL) + { + Check(audio_channel); + iterator.Remove(); + idleVoices -= voice_count; + audio_channel->SetVoicesUsed(voice_count); + + return audio_channel; + } + return NULL; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::ReleaseAudioChannel(AudioChannel *audio_channel) +{ + Check(this); + Check(audio_channel); + + #if 0 + Tell("AudioCard::ReleaseAudioChannel - Released channel\n"); + Tell(" "); + Dump((int)audio_channel->GetChannelNumber()); + #endif + + // + // Add to idle list + // + idleVoices += audio_channel->GetVoicesUsed(); + Verify(idleVoices > 0 && idleVoices <= AWE_VOICE_COUNT); + audio_channel->SetVoicesUsed(0); + + idleChannelSocket.Add(audio_channel); +} + +// +//############################################################################# +// GetHexWord +//############################################################################# +// +WORD + AudioCard::GetHexWord(const char ** s) +{ + WORD n = 0; + + while (**s) { + if (**s >= '0' && **s <= '9') + n = (WORD)(n * 16 + (*(*s)++ - '0')); + else + if (**s >= 'a' && **s <= 'f') + n = (WORD)(n * 16 + (*(*s)++ - 'a') + 10); + else + if (**s >= 'A' && **s <= 'F') + n = (WORD)(n * 16 + (*(*s)++ - 'A') + 10); + else + break; + } + return n; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// AudioHardware +//############################################################################# +// +AudioHardware::AudioHardware() +{ +} + +// +//############################################################################# +// ~AudioHardware +//############################################################################# +// +AudioHardware::~AudioHardware() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioHardware::TestInstance() const +{ + Node::TestInstance(); + Check(&frontCard); + Check(&rearCard); + return True; +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + AudioHardware::Initialize() +{ +#ifdef AUDIO_HARDWARE + Tell("AudioHardware::Initialize - Start\n"); + + #if 0 + // + // initialize the TIMER system and tell it to call the DOS timer + // at a rate of 19 times/second. the actual rate is 18.2, but + // 19 is a good approximation. + // + if (getenv(TIMER_ENV) == NULL) // L4Time is not setting up timer + { + sosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL); + } + #endif + + // + // initialize the MIDI system + // + sosMIDIInitSystem((PSTR)_SOS_DRIVER_PATH, _SOS_DEBUG_NORMAL); + + // + // initialize the cards + // + frontCard.GetEnvironmentSettings(FRONT_CARD_ENV_VAR); + rearCard.GetEnvironmentSettings(REAR_CARD_ENV_VAR); + frontCard.Initialize(); + rearCard.Initialize(); + + // + // Setup standard channel attributes + // + frontCard.InitializeChannels(); + rearCard.InitializeChannels(); + + Tell("AudioHardware::Initialize - Finish\n"); +#endif +} + +// +//############################################################################# +// Close +//############################################################################# +// +void + AudioHardware::Close() +{ +#ifdef AUDIO_HARDWARE + Check(this); + + // + // Close the cards + // + frontCard.Close(); + rearCard.Close(); + + #if 0 + // + // Uninitialize the TIMER system and pass it the value to write to the + // timer chip to reset the timer, 0 is equivalent to 18.2 times/second + // which is the DOS clock rate. the calculation for the value to pass + // is 1193180/RATE. + // + if (getenv(TIMER_ENV) == NULL) // L4Time is not setting up timer + { + sosTIMERUnInitSystem(0); + } + sosTIMERUnInitSystem(0); + #endif + + // + // Uninitialize the MIDI system + // + sosMIDIUnInitSystem(); +#endif +} + +#ifdef TEST_CLASS +# include "l4audhdw.tcp" +#endif diff --git a/CODE/RP/MUNGA_L4/L4AUDHDW.HPP b/CODE/RP/MUNGA_L4/L4AUDHDW.HPP new file mode 100644 index 0000000..e972435 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDHDW.HPP @@ -0,0 +1,821 @@ +//===========================================================================// +// File: l4audhdw.hh // +// Project: MUNGA Brick: Audio Manager // +// Contents: Spec for audio manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/25/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4AUDHDW_HPP) +# define L4AUDHDW_HPP + +# define AUDIO_HARDWARE + +# if !defined(STYLE_HPP) +# include +# endif + +# ifdef AUDIO_HARDWARE +# ifndef _SOS_MIDI_DEFINED +# include +# endif +# else + typedef Byte BYTE; + typedef Word WORD; +# endif + +# if !defined(NODE_HPP) +# include +# endif + +# if !defined(SCHAIN_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + + #if defined(TRACE_AUDIO_RENDERER_MIDI) + extern BitTrace Audio_Renderer_MIDI("Audio Renderer MIDI"); + #define SET_AUDIO_RENDERER_MIDI() Audio_Renderer_MIDI.Set() + #define CLEAR_AUDIO_RENDERER_MIDI() Audio_Renderer_MIDI.Clear() + #else + #define SET_AUDIO_RENDERER_MIDI() + #define CLEAR_AUDIO_RENDERER_MIDI() + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef unsigned char MIDIStatus; + typedef unsigned char MIDIChannel; + typedef unsigned char MIDIValue; + typedef int MIDIPitchBend; + typedef int MIDINRPNValue; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI status ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define MIDI_CHANNEL_COUNT (16) + + #define MIDI_NOTE_OFF_STATUS ((MIDIValue)0x8) // 8 + #define MIDI_NOTE_ON_STATUS ((MIDIValue)0x9) // 9 + #define MIDI_POLYKEY_STATUS ((MIDIValue)0xa) // 10 + #define MIDI_CONTROLLER_STATUS ((MIDIValue)0xb) // 11 + #define MIDI_PROGRAM_CHANGE_STATUS ((MIDIValue)0xc) // 12 + #define MIDI_CHANNEL_PRESSURE_STATUS ((MIDIValue)0xd) // 13 + #define MIDI_PITCH_BEND_STATUS ((MIDIValue)0xe) // 14 + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI controllers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define MIDI_MAX_CONTROL_VALUE ((MIDIValue)127) + #define MIDI_MIN_CONTROL_VALUE ((MIDIValue)0) + + #define MIDI_LEFT_PAN_VALUE ((MIDIValue)0) + #define MIDI_CENTER_PAN_VALUE ((MIDIValue)63) + #define MIDI_RIGHT_PAN_VALUE ((MIDIValue)127) + + #define MIDI_VOLUME_CONTROL ((MIDIValue)7) + #define MIDI_PAN_CONTROL ((MIDIValue)10) + #define MIDI_REVERB_CONTROL ((MIDIValue)91) + #define MIDI_CHORUS_CONTROL ((MIDIValue)93) + #define MIDI_CONTROL_RESET ((MIDIValue)121) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI notes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define MIDI_DEFAULT_NOTE ((MIDIValue)60) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI pitch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define MIDI_PITCH_BEND_MAX ((MIDIPitchBend)8191) + #define MIDI_PITCH_BEND_RANGE ((MIDIValue)24) + #define MIDI_PITCH_BEND_CENTS (24*100) + #define MIDI_PITCH_PER_CENTS ((Scalar)MIDI_PITCH_BEND_MAX / \ + (Scalar)MIDI_PITCH_BEND_CENTS) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE NRPN ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define AWE_VOL_ATTACK_TIME_NRPN ((MIDIValue)11) + #define AWE_PITCH_NRPN ((MIDIValue)16) + #define AWE_FILTER_CUTOFF_NRPN ((MIDIValue)21) + + #define AWE_VOL_ATTACK_TIME_RANGE ((MIDINRPNValue)5940) // 0...5.9 secs + #define AWE_FILTER_CUTOFF_RANGE ((MIDINRPNValue)127) // 100...8000 Hz + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE effects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef enum { + ChorusMIDIEffectType, + ReverbMIDIEffectType + } MIDIEffectType; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE resources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define AWE_VOICE_COUNT (32) + #define AWE_CHANNEL_COUNT (16) + #define AWE_PERCUSSIVE_CHANNEL (9) + + // + // Driver type to use + // + #define _MIDI_DRIVER_TYPE _MIDI_AWE32 + + // + // Path to the driver file + // + #define _SOS_DRIVER_PATH _NULL + + // + // AWE environment variables + // + #define FRONT_CARD_ENV_VAR "AWE_FRONT" + #define REAR_CARD_ENV_VAR "AWE_REAR" + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDIMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + #define MIDI_MESSAGE_SIZE (3) + + class MIDIMessage SIGNATURED + { + friend class AudioCard; + friend ostream& + operator << ( + ostream &strm, + const MIDIMessage &midi_message + ); + + public: + MIDIMessage( + MIDIStatus status, + MIDIChannel channel, + MIDIValue byte1, + MIDIValue byte2 = 0 + ); + ~MIDIMessage() {} + + Logical + TestInstance() const; + + private: + MIDIValue + message[MIDI_MESSAGE_SIZE]; + }; + + inline MIDIMessage::MIDIMessage( + MIDIStatus status, + MIDIChannel channel, + MIDIValue byte1, + MIDIValue byte2 + ) + { + message[0] = (MIDIValue)((status << 4) | channel); + message[1] = byte1; + message[2] = byte2; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef enum + { + InstrumentAudioChannelType = 0, + PercussionAudioChannelType + } AudioChannelType; + + class AudioCard; + + class AudioChannel: + public Plug + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioChannel( + AudioChannelType audio_channel_type, + MIDIChannel midi_channel, + AudioCard *audio_card + ); + ~AudioChannel(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- + // + AudioChannelType + GetAudioChannelType() + {return audioChannelType;} + MIDIChannel + GetChannelNumber() + {return midiChannel;} + void + SetVoicesUsed(AudioVoiceCount voices_used) + {voicesUsed = voices_used;} + AudioVoiceCount + GetVoicesUsed() + {return voicesUsed;} + + // + //-------------------------------------------------------------------- + // MIDI methods + //-------------------------------------------------------------------- + // + void + SendNoteOn( + MIDIValue key, + MIDIValue velocity + ); + void + SendNoteOff( + MIDIValue key, + MIDIValue velocity + ); + void + SendProgramChange( + MIDIValue program + ); + void + SendController( + MIDIValue controller, + MIDIValue value + ); + void + SendPolyKeyPressure( + MIDIValue key, + MIDIValue value + ); + void + SendChannelPressure( + MIDIValue value + ); + void + SendPitchBend( + MIDIPitchBend pitch_bend + ); + void + SendPitchBendRange( + MIDIValue sensitivity + ); + void + SendNRPN( + MIDIValue paramNumber, + MIDINRPNValue value + ); + void + SelectEffect( + MIDIEffectType type, + MIDIValue effect + ); + void + SelectBank( + MIDIValue bank + ); + + // + //-------------------------------------------------------------------- + // Release + //-------------------------------------------------------------------- + // + void + Release(); + + private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + AudioChannelType + audioChannelType; + MIDIChannel + midiChannel; + AudioVoiceCount + voicesUsed; + AudioCard + *audioCard; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioCard: + public Node + { + friend class AudioHardware; + + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioCard(); + ~AudioCard(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // Public methods + //-------------------------------------------------------------------- + // + void + Initialize(); + void + Close(); + void + GetEnvironmentSettings(char *env_str); + + Logical + InitMIDIReceive(); + void + CloseMIDIReceive(); + Logical + IsMIDIAvailable(); + MIDIValue + GetMIDIByte(); + + void + InitializeChannels(); + int + LoadSBK(const char *file_name); + void + ReleaseAllBanks(); + + // + //-------------------------------------------------------------------- + // MIDI methods + //-------------------------------------------------------------------- + // + void + SendNoteOn( + MIDIChannel channel, + MIDIValue key, + MIDIValue velocity + ); + void + SendNoteOff( + MIDIChannel channel, + MIDIValue key, + MIDIValue velocity + ); + void + SendProgramChange( + MIDIChannel channel, + MIDIValue program + ); + void + SendController( + MIDIChannel channel, + MIDIValue controller, + MIDIValue value + ); + void + SendPolyKeyPressure( + MIDIChannel channel, + MIDIValue key, + MIDIValue value + ); + void + SendChannelPressure( + MIDIChannel channel, + MIDIValue value + ); + void + SendPitchBendRange( + MIDIChannel channel, + MIDIValue sensitivity + ); + void + SendPitchBend( + MIDIChannel channel, + MIDIPitchBend pitch_bend + ); + void + SendSysex( + void *data, + size_t length + ); + void + SendNRPN( + MIDIChannel channel, + MIDIValue paramNumber, + MIDINRPNValue value + ); + void + SelectEffect( + MIDIEffectType type, + MIDIValue effect + ); + void + SelectBank( + MIDIChannel channel, + MIDIValue bank + ); + void + SendMIDIMessage( + MIDIMessage *midi_message, + Word length + ); + + // + //-------------------------------------------------------------------- + // Channel methods + //-------------------------------------------------------------------- + // + AudioChannel* + RequestAudioChannel(AudioVoiceCount voice_count); + void + ReleaseAudioChannel(AudioChannel *audio_channel); + + private: + // + //-------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------- + // + WORD + GetHexWord(const char ** s); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + + // + // Card addresses + // + WORD srcAddx; + WORD irqInterrupt; + WORD dmaChannel; + WORD mpuAddx; + WORD emuAddx; + + // + // Structure for the MIDI driver initialization function + // Structure for the MIDI driver hardware + // + #ifdef AUDIO_HARDWARE + _SOS_MIDI_INIT_DRIVER sSOSMIDIInitDriver; + _SOS_MIDI_HARDWARE sSOSMIDIHardware; + #endif + + // + // Handle for the loaded MIDI driver + // + WORD wDriverHandle; + + // + // Number of free voices + // + AudioVoiceCount + idleVoices; + + // + // Idle channels + // + ChainOf + idleChannelSocket; + ChainOf + percussionChannelSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class AudioHardware: + public Node + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioHardware(); + ~AudioHardware(); + + Logical + TestInstance() const; + static Logical + TestClass(); + static Logical + ProfileClass(); + + // + //-------------------------------------------------------------------- + // Public methods + //-------------------------------------------------------------------- + // + void + Initialize(); + void + Close(); + + // + //-------------------------------------------------------------------- + // Card Access + //-------------------------------------------------------------------- + // + AudioCard* + GetFrontCard(); + + AudioCard* + GetRearCard(); + + private: + // + //-------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + AudioCard + frontCard; + AudioCard + rearCard; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline void + AudioCard::SendMIDIMessage( + MIDIMessage *midi_message, + Word length + ) + { + #ifdef AUDIO_HARDWARE + SET_AUDIO_RENDERER_MIDI(); + + Check_Signature(midi_message); + #if DEBUG_LEVEL>0 + switch (midi_message->message[0] >> 4) + { + case MIDI_NOTE_ON_STATUS: + case MIDI_NOTE_OFF_STATUS: + case MIDI_POLYKEY_STATUS: + case MIDI_CONTROLLER_STATUS: + case MIDI_PITCH_BEND_STATUS: + Verify(length == 3); + break; + + case MIDI_PROGRAM_CHANGE_STATUS: + case MIDI_CHANNEL_PRESSURE_STATUS: + Verify(length == 2); + break; + default: + Fail("Should never reach here"); + break; + } + #endif + + #if DEBUG_LEVEL>0 + { + Word wError = sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + length + ); + Verify(wError == _ERR_NO_ERROR); + } + #else + sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + length + ); + #endif + CLEAR_AUDIO_RENDERER_MIDI(); + #endif + } + + // + //-------------------------------------------------------------------- + // MIDI methods + //-------------------------------------------------------------------- + // + inline void + AudioCard::SendNoteOn( + MIDIChannel channel, + MIDIValue key, + MIDIValue velocity + ) + { + MIDIMessage message(MIDI_NOTE_ON_STATUS, channel, key, velocity); + SendMIDIMessage(&message, 3); + } + + inline void + AudioCard::SendNoteOff( + MIDIChannel channel, + MIDIValue key, + MIDIValue velocity + ) + { + MIDIMessage message(MIDI_NOTE_OFF_STATUS, channel, key, velocity); + SendMIDIMessage(&message, 3); + } + + inline void + AudioCard::SendProgramChange( + MIDIChannel channel, + MIDIValue program + ) + { + MIDIMessage message(MIDI_PROGRAM_CHANGE_STATUS, channel, program); + SendMIDIMessage(&message, 2); + } + + inline void + AudioCard::SendController( + MIDIChannel channel, + MIDIValue controller, + MIDIValue value + ) + { + MIDIMessage message(MIDI_CONTROLLER_STATUS, channel, controller, value); + SendMIDIMessage(&message, 3); + } + + inline void + AudioCard::SendPolyKeyPressure( + MIDIChannel channel, + MIDIValue key, + MIDIValue value + ) + { + MIDIMessage message(MIDI_POLYKEY_STATUS, channel, key, value); + SendMIDIMessage(&message, 3); + } + + inline void + AudioCard::SendChannelPressure( + MIDIChannel channel, + MIDIValue value + ) + { + MIDIMessage message(MIDI_CHANNEL_PRESSURE_STATUS, channel, value); + SendMIDIMessage(&message, 2); + } + + inline void + AudioCard::SelectBank( + MIDIChannel channel, + MIDIValue bank + ) + { + SendController(channel, (MIDIValue)0, bank); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // + //-------------------------------------------------------------------- + // MIDI methods + //-------------------------------------------------------------------- + // + inline void + AudioChannel::SendNoteOn( + MIDIValue key, + MIDIValue velocity + ) + { + Check(audioCard); + audioCard->SendNoteOn(midiChannel,key,velocity); + } + + inline void + AudioChannel::SendNoteOff( + MIDIValue key, + MIDIValue velocity + ) + { + Check(audioCard); + audioCard->SendNoteOff(midiChannel,key,velocity); + } + + inline void + AudioChannel::SendProgramChange( + MIDIValue program + ) + { + Check(audioCard); + audioCard->SendProgramChange(midiChannel,program); + } + + inline void + AudioChannel::SendController( + MIDIValue controller, + MIDIValue value + ) + { + Check(audioCard); + audioCard->SendController(midiChannel,controller,value); + } + + inline void + AudioChannel::SendPolyKeyPressure( + MIDIValue key, + MIDIValue value + ) + { + Check(audioCard); + audioCard->SendPolyKeyPressure(midiChannel,key,value); + } + + inline void + AudioChannel::SendChannelPressure( + MIDIValue value + ) + { + Check(audioCard); + audioCard->SendChannelPressure(midiChannel,value); + } + + inline void + AudioChannel::SendPitchBend( + MIDIPitchBend pitch_bend + ) + { + Check(audioCard); + audioCard->SendPitchBend(midiChannel,pitch_bend); + } + + inline void + AudioChannel::SendPitchBendRange( + MIDIValue sensitivity + ) + { + Check(audioCard); + audioCard->SendPitchBendRange(midiChannel,sensitivity); + } + + inline void + AudioChannel::SelectEffect( + MIDIEffectType type, + MIDIValue effect + ) + { + Check(audioCard); + audioCard->SelectEffect(type,effect); + } + + inline void + AudioChannel::SendNRPN( + MIDIValue paramNumber, + MIDINRPNValue value + ) + { + Check(audioCard); + audioCard->SendNRPN(midiChannel,paramNumber,value); + } + + inline void + AudioChannel::SelectBank( + MIDIValue bank + ) + { + Check(audioCard); + audioCard->SelectBank(midiChannel,bank); + } + + inline void + AudioChannel::Release() + { + Check(audioCard); + audioCard->ReleaseAudioChannel(this); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline AudioCard* + AudioHardware::GetFrontCard() + { + Check(this); + return &frontCard; + } + + inline AudioCard* + AudioHardware::GetRearCard() + { + Check(this); + return &rearCard; + } + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4AUDHDW.TCP b/CODE/RP/MUNGA_L4/L4AUDHDW.TCP new file mode 100644 index 0000000..c79b5ff --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDHDW.TCP @@ -0,0 +1,1854 @@ +//===========================================================================// +// File: audhdw.thh // +// Project: MUNGA Brick: Audio Manager // +// Contents: Spec for audio manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/25/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#include +#include + +#define BUILD_NOISE_PHASE_TEST +//#define BUILD_TONE_PHASE_TEST +//#define BUILD_LOUDNESS_TEST +//#define BUILD_CHAN_TEST +//#define BUILD_SND_PLAY + +// +//############################################################################# +// TonePhaseTest +//############################################################################# +// +class TonePhaseTest SIGNATURED +{ +public: + typedef enum + { + InPhase = 1, + OutOfPhase, + FrontSpeakers, + RearSpeakers, + StartTone, + PrintMenu, + StopCurrentTest + } Command; + + TonePhaseTest(AudioHardware *audio_hardware); + Logical TestInstance() const; + void Run(); + void DoCommand(Command command); + + AudioHardware *audioHardware; + Command phaseCommand; + Command positionCommand; + short program; + Logical runningTest; +}; + +TonePhaseTest::TonePhaseTest(AudioHardware *audio_hardware) +{ + Check(audio_hardware); + audioHardware = audio_hardware; + phaseCommand = InPhase; + positionCommand = FrontSpeakers; + program = 0; + runningTest = False; +} + +Logical + TonePhaseTest::TestInstance() const +{ + Check(audioHardware); + return True; +} + +void + TonePhaseTest::Run() +{ + Check(this); + + Logical quit_test = False; + int input_char; + + // + // Load SBKs + // + Check(audioHardware); + audioHardware->GetFrontCard()->LoadSBK("tonephaz.sbk"); + audioHardware->GetRearCard()->LoadSBK("tonephaz.sbk"); + + DoCommand(PrintMenu); + + while (!quit_test) + { + // + // Get event from keyboard + // + if (kbhit()) + { + input_char = getch(); + if (input_char == '' && !runningTest) + { + quit_test = True; + continue; + } + else if (input_char == '' && runningTest) + { + DoCommand(StopCurrentTest); + DoCommand(PrintMenu); + } + else + { + Command input_command = (Command)(input_char - '0'); + + if (input_command >= InPhase && input_command <= StartTone) + { + DoCommand(StopCurrentTest); + DoCommand(input_command); + } + } + } + } +} + +void + TonePhaseTest::DoCommand(Command command) +{ + Check(this); + + Logical start_test = False; + + // + // Do the command + // + switch (command) + { + case InPhase: + Tell("In Phase\n"); + phaseCommand = InPhase; + break; + + case OutOfPhase: + Tell("Out Of Phase\n"); + phaseCommand = OutOfPhase; + break; + + case FrontSpeakers: + Tell("Front speakers\n"); + positionCommand = FrontSpeakers; + break; + + case RearSpeakers: + Tell("Rear speakers\n"); + positionCommand = RearSpeakers; + break; + + case StartTone: + Tell("Start Tone\n"); + if (phaseCommand == InPhase) + program = 0; + else + program = 1; + start_test = True; + break; + + case PrintMenu: + // + // Print menu + // + Tell("\n"); + Tell("<1> In Phase\n"); + Tell("<2> Out Of Phase\n"); + Tell("<3> Front speakers\n"); + Tell("<4> Rear speakers\n"); + Tell("<5> Start Tone\n"); + Tell(" to end\n\n"); + break; + + case StopCurrentTest: + if (runningTest) + { + Tell("End current test\n"); + if (positionCommand == FrontSpeakers) + { + audioHardware->GetFrontCard()->SendNoteOff(0, 60, 0); + } + else + { + audioHardware->GetRearCard()->SendNoteOff(0, 60, 0); + } + runningTest = False; + } + break; + } + + if (start_test) + { + if (positionCommand == FrontSpeakers) + { + audioHardware->GetFrontCard()->SendController(0, 121, 1); // Reset + audioHardware->GetFrontCard()->SendController(0, 0, 1); // Bank + audioHardware->GetFrontCard()->SendController(0, 91, 0); // Reverb + audioHardware->GetFrontCard()->SendController(0, 93, 0); // Chorus + audioHardware->GetFrontCard()->SendProgramChange(0, program); + audioHardware->GetFrontCard()->SendNoteOn(0, 60, 127); + } + else + { + audioHardware->GetRearCard()->SendController(0, 121, 1); // Reset + audioHardware->GetRearCard()->SendController(0, 0, 1); // Bank + audioHardware->GetRearCard()->SendController(0, 91, 0); // Reverb + audioHardware->GetRearCard()->SendController(0, 93, 0); // Chorus + audioHardware->GetRearCard()->SendProgramChange(0, program); + audioHardware->GetRearCard()->SendNoteOn(0, 60, 127); + } + runningTest = True; + } +} + +// +//############################################################################# +// NoisePhaseTest +//############################################################################# +// +class NoisePhaseTest SIGNATURED +{ +public: + typedef enum + { + InPhase = 1, + OutOfPhase, + FrontSpeakers, + RearSpeakers, + AllSpeakers, + LowNoise, + MidNoise, + HighNoise, + PrintMenu, + StopCurrentTest + } Command; + + NoisePhaseTest(AudioHardware *audio_hardware); + Logical TestInstance() const; + void Run(); + void DoCommand(Command command); + + AudioHardware *audioHardware; + Command phaseCommand; + Command positionCommand; + short program; + Logical runningTest; +}; + +NoisePhaseTest::NoisePhaseTest(AudioHardware *audio_hardware) +{ + Check(audio_hardware); + audioHardware = audio_hardware; + phaseCommand = InPhase; + positionCommand = FrontSpeakers; + program = 0; + runningTest = False; +} + +Logical + NoisePhaseTest::TestInstance() const +{ + Check(audioHardware); + return True; +} + +void + NoisePhaseTest::Run() +{ + Check(this); + + Logical quit_test = False; + int input_char; + + // + // Load SBKs + // + Check(audioHardware); + audioHardware->GetFrontCard()->LoadSBK("noizphaz.sbk"); + audioHardware->GetRearCard()->LoadSBK("noizphaz.sbk"); + + DoCommand(PrintMenu); + + while (!quit_test) + { + // + // Get event from keyboard + // + if (kbhit()) + { + input_char = getch(); + if (input_char == '' && !runningTest) + { + quit_test = True; + continue; + } + else if (input_char == '' && runningTest) + { + DoCommand(StopCurrentTest); + DoCommand(PrintMenu); + } + else + { + Command input_command = (Command)(input_char - '0'); + + if (input_command >= InPhase && input_command <= HighNoise) + { + DoCommand(StopCurrentTest); + DoCommand(input_command); + } + } + } + } +} + +void + NoisePhaseTest::DoCommand(Command command) +{ + Check(this); + + Logical start_test = False; + + // + // Do the command + // + switch (command) + { + case InPhase: + Tell("In Phase\n"); + phaseCommand = InPhase; + break; + + case OutOfPhase: + Tell("Out Of Phase\n"); + phaseCommand = OutOfPhase; + break; + + case FrontSpeakers: + Tell("Front speakers\n"); + positionCommand = FrontSpeakers; + break; + + case RearSpeakers: + Tell("Rear speakers\n"); + positionCommand = RearSpeakers; + break; + + case AllSpeakers: + Tell("All speakers\n"); + positionCommand = AllSpeakers; + break; + + case LowNoise: + Tell("Start Low noise\n"); + if (phaseCommand == InPhase) + program = 4; + else + program = 5; + start_test = True; + break; + + case MidNoise: + Tell("Start Med noise\n"); + if (phaseCommand == InPhase) + program = 2; + else + program = 3; + start_test = True; + break; + + case HighNoise: + Tell("Start High noise\n"); + if (phaseCommand == InPhase) + program = 0; + else + program = 1; + start_test = True; + break; + + case PrintMenu: + // + // Print menu + // + Tell("\n"); + Tell("<1> In Phase\n"); + Tell("<2> Out Of Phase\n"); + Tell("<3> Front speakers\n"); + Tell("<4> Rear speakers\n"); + Tell("<5> All speakers\n"); + Tell("<6> Start Low noise\n"); + Tell("<7> Start Med noise\n"); + Tell("<8> Start High noise\n"); + Tell(" to end\n\n"); + break; + + case StopCurrentTest: + if (runningTest) + { + Tell("End current test\n"); + + if (positionCommand == FrontSpeakers || positionCommand == AllSpeakers) + { + audioHardware->GetFrontCard()->SendNoteOff(0, 60, 0); + } + if (positionCommand == RearSpeakers || positionCommand == AllSpeakers) + { + audioHardware->GetRearCard()->SendNoteOff(0, 60, 0); + } + runningTest = False; + } + break; + } + + if (start_test) + { + if (positionCommand == FrontSpeakers || positionCommand == AllSpeakers) + { + audioHardware->GetFrontCard()->SendController(0, 121, 1); // Reset + audioHardware->GetFrontCard()->SendController(0, 0, 1); // Bank + audioHardware->GetFrontCard()->SendController(0, 91, 0); // Reverb + audioHardware->GetFrontCard()->SendController(0, 93, 0); // Chorus + audioHardware->GetFrontCard()->SendProgramChange(0, program); + audioHardware->GetFrontCard()->SendNoteOn(0, 60, 127); + } + if (positionCommand == RearSpeakers || positionCommand == AllSpeakers) + { + audioHardware->GetRearCard()->SendController(0, 121, 1); // Reset + audioHardware->GetRearCard()->SendController(0, 0, 1); // Bank + audioHardware->GetRearCard()->SendController(0, 91, 0); // Reverb + audioHardware->GetRearCard()->SendController(0, 93, 0); // Chorus + audioHardware->GetRearCard()->SendProgramChange(0, program); + audioHardware->GetRearCard()->SendNoteOn(0, 60, 127); + } + runningTest = True; + } +} + +// +//############################################################################# +// LoudnessTest +//############################################################################# +// +#define AWE_VOL_ENV_VAR "AWE_MASTER_VOLUME" + +class LoudnessTest SIGNATURED +{ +public: + typedef enum + { + SetLevel = 1, + PlayNoise, + StopNoise, + PrintMenu + } Command; + + LoudnessTest(AudioHardware *audio_hardware); + Logical TestInstance() const; + void Run(); + void DoCommand(Command command); + + AudioHardware *audioHardware; + Command command; + Logical runningTest; + int currentVolume; +}; + +LoudnessTest::LoudnessTest(AudioHardware *audio_hardware) +{ + char *loudness_environment; + + if ((loudness_environment = getenv(AWE_VOL_ENV_VAR)) == NULL) + currentVolume = 160; + else + currentVolume = atoi(loudness_environment); + + Check(audio_hardware); + audioHardware = audio_hardware; + command = PlayNoise; + runningTest = False; +} + +Logical + LoudnessTest::TestInstance() const +{ + Check(audioHardware); + return True; +} + +void + LoudnessTest::Run() +{ + Check(this); + + Logical quit_test = False; + int input_char; + + // + // Load SBKs + // + Check(audioHardware); + audioHardware->GetFrontCard()->LoadSBK("loudness.sbk"); + audioHardware->GetRearCard()->LoadSBK("loudness.sbk"); + + DoCommand(PrintMenu); + DoCommand(PlayNoise); + + while (!quit_test) + { + // + // Get event from keyboard + // + if (kbhit()) + { + input_char = getch(); + if (input_char == '') + { + DoCommand(StopNoise); + quit_test = True; + } + else + { + Command input_command = (Command)(input_char - '0'); + + if (input_command == SetLevel) + { + DoCommand(StopNoise); + DoCommand(SetLevel); + quit_test = True; + } + } + } + } +} + +void + LoudnessTest::DoCommand(Command command) +{ + Check(this); + + // + // Do the command + // + switch (command) + { + case PlayNoise: + audioHardware->GetFrontCard()->SendController(0, 121, 1); // Reset + audioHardware->GetFrontCard()->SendController(0, 0, 1); // Bank + audioHardware->GetFrontCard()->SendController(0, 91, 0); // Reverb + audioHardware->GetFrontCard()->SendController(0, 93, 0); // Chorus + audioHardware->GetFrontCard()->SendProgramChange(0, 0); + audioHardware->GetFrontCard()->SendNoteOn(0, 60, 127); + + audioHardware->GetRearCard()->SendController(0, 121, 1); // Reset + audioHardware->GetRearCard()->SendController(0, 0, 1); // Bank + audioHardware->GetRearCard()->SendController(0, 91, 0); // Reverb + audioHardware->GetRearCard()->SendController(0, 93, 0); // Chorus + audioHardware->GetRearCard()->SendProgramChange(0, 0); + audioHardware->GetRearCard()->SendNoteOn(0, 60, 127); + break; + + case StopNoise: + audioHardware->GetFrontCard()->SendNoteOff(0, 60, 0); + audioHardware->GetRearCard()->SendNoteOff(0, 60, 0); + break; + + case SetLevel: + { + // + // Read the specified input level + // + int input_level = -1; + + while (input_level < 0 || 255 < input_level) + { + Tell( + "\nSet Level (0-255) (Current Level=" << + currentVolume << + "): " + ); + cin >> input_level; + if (input_level < 0 || 255 < input_level) + { + Tell("Valid entries are 0 to 255.\n"); + } + } + + // + // Write the bat file + // + ofstream output_file("setvol.bat", ios::out); + + Verify(output_file); + output_file << "set " << AWE_VOL_ENV_VAR "=" << input_level << "\n"; + } + break; + + case PrintMenu: + // + // Print menu + // + Tell("\n"); + Tell("Current Level=" << currentVolume << "\n"); + Tell("\n"); + Tell("<1> Set Level\n"); + Tell(" to end\n\n"); + break; + } +} + +// +//############################################################################# +// TestClass +//############################################################################# +// +#define RAD360 (6.28318) + +Logical + AudioHardware::TestClass() +{ + AudioHardware audio_hardware; + + audio_hardware.Initialize(); + + // + //-------------------------------------------------------------------------- + // Noise Phase Test + //-------------------------------------------------------------------------- + // + #if defined(BUILD_NOISE_PHASE_TEST) + { + NoisePhaseTest noise_phase_test(&audio_hardware); + + noise_phase_test.Run(); + } + #endif + + // + //-------------------------------------------------------------------------- + // Tone Phase Test + //-------------------------------------------------------------------------- + // + #if defined(BUILD_TONE_PHASE_TEST) + { + TonePhaseTest tone_phase_test(&audio_hardware); + + tone_phase_test.Run(); + } + #endif + + // + //-------------------------------------------------------------------------- + // Loudness Test + //-------------------------------------------------------------------------- + // + #if defined(BUILD_LOUDNESS_TEST) + { + LoudnessTest loudness_test(&audio_hardware); + + loudness_test.Run(); + } + #endif + + // + //------------------------------------------------------------------ + // Revised Speaker Channel Test + //------------------------------------------------------------------ + // + #if defined(BUILD_CHAN_TEST) + { + clock_t end_time; + MIDIValue channel; + MIDIValue panValue; + MIDIValue program; + int speakSelect, front, rear, waitTime; + + speakSelect = 1; + waitTime = 4; + + // + // Load SBKs + // + audio_hardware.frontCard.LoadSBK("chantest.sbk"); + audio_hardware.rearCard.LoadSBK("chantest.sbk"); + + // + // Init channels + // + channel = 0; + { + // + // Set to second bank + // + + // Card 1 + audio_hardware.frontCard.SendController(channel, 121, 1); // Reset + audio_hardware.frontCard.SendController(channel, 0, 1); // Bank + audio_hardware.frontCard.SendController(channel, 91, 0); // Reverb + audio_hardware.frontCard.SendController(channel, 93, 0); // Chorus + + // Card 2 + audio_hardware.rearCard.SendController(channel, 121, 1); // Reset + audio_hardware.rearCard.SendController(channel, 0, 1); // Bank + audio_hardware.rearCard.SendController(channel, 91, 0); // Reverb + audio_hardware.rearCard.SendController(channel, 93, 0); // Chorus + } + + // + // Cycle through speaker channels + // + Tell("\n"); + Tell("<1> rear-left\n"); + Tell("<2> rear-center\n"); + Tell("<3> rear-right\n"); + Tell("<4> front & rear-left\n"); + Tell("<5> front & rear-center\n"); + Tell("<6> front & rear-right\n"); + Tell("<7> front-left\n"); + Tell("<8> front-center\n"); + Tell("<9> front-right\n"); + Tell(" to end\n\n"); + while (speakSelect != -1) + { + switch (speakSelect){ + case 1: + front = 0; + rear = 1; + panValue = 0; + Tell("Tones in rear-left\n"); + break; + case 2: + front = 0; + rear = 1; + panValue = 63; + Tell("Tones in rear-center\n"); + break; + case 3: + front = 0; + rear = 1; + panValue = 127; + Tell("Tones in rear-right\n"); + break; + case 4: + front = 1; + rear = 1; + panValue = 0; + Tell("Tones in front & rear-left\n"); + break; + case 5: + front = 1; + rear = 1; + panValue = 63; + Tell("Tones in front & rear-center\n"); + break; + case 6: + front = 1; + rear = 1; + panValue = 127; + Tell("Tones in front & rear-right\n"); + break; + case 7: + front = 1; + rear = 0; + panValue = 0; + Tell("Tones in front-left\n"); + break; + case 8: + front = 1; + rear = 0; + panValue = 63; + Tell("Tones in front-center\n"); + break; + case 9: + front = 1; + rear = 0; + panValue = 127; + Tell("Tones in front-right\n"); + break; + default: + break; + }; + + // Set Speaker Channel + if (front){ + //audio_hardware.frontCard.SendController(0, 121, 1); // Reset + //audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 0); // Pgm + audio_hardware.frontCard.SendController(0, 10, panValue); // Pan + } + if (rear) { + //audio_hardware.rearCard.SendController(0, 121, 1); // Reset + //audio_hardware.rearCard.SendController(0, 0, 1); // Bank + audio_hardware.rearCard.SendProgramChange(0, 0); // Pgm + audio_hardware.rearCard.SendController(0, 10, panValue); // Pan + } + + // Play tones + for (program = 0; program < 7; program++) + { + // + // Set program + // + audio_hardware.frontCard.SendProgramChange(0, program); + audio_hardware.rearCard.SendProgramChange(0, program); + + // + // Play note + // + if (front) + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + if (rear) + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + end_time = clock() + waitTime*CLOCKS_PER_SEC; + while (clock() < end_time) + { + } + + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + + if (kbhit()) + { + switch (getch()){ + case '': + speakSelect = -1; + break; + case '1': + speakSelect = 1; + break; + case '2': + speakSelect = 2; + break; + case '3': + speakSelect = 3; + break; + case '4': + speakSelect = 4; + break; + case '5': + speakSelect = 5; + break; + case '6': + speakSelect = 6; + break; + case '7': + speakSelect = 7; + break; + case '8': + speakSelect = 8; + break; + case '9': + speakSelect = 9; + break; + default: + break; + }; + break; + } + } + } + } + #endif + + // + //------------------------------------------------------------------ + // Sound Play Test + // + // Requires "test.sbk" + //------------------------------------------------------------------ + // + #if defined(BUILD_SND_PLAY) + { + MIDIValue channel; + MIDIValue progSelect; + int noteIsOn, prognum; + char ch; + + Tell("AudioHardware::TestClass\n"); + + // + // Load SBKs + // + audio_hardware.frontCard.LoadSBK("test.sbk"); + audio_hardware.rearCard.LoadSBK("test.sbk"); + + // + // Init channel + // Set to second bank + // + channel = 0; + + // Card 1 + audio_hardware.frontCard.SendController( + channel, MIDI_CONTROL_RESET, 1 + ); + audio_hardware.frontCard.SendController( + channel, MIDI_PAN_CONTROL, MIDI_CENTER_PAN_VALUE + ); + audio_hardware.frontCard.SendController( + channel, MIDI_REVERB_CONTROL, MIDI_MIN_CONTROL_VALUE + ); + audio_hardware.frontCard.SendController( + channel, MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE + ); + audio_hardware.frontCard.SelectBank(channel, 1); + + // Card 2 + audio_hardware.rearCard.SendController( + channel, MIDI_CONTROL_RESET, 1 + ); + audio_hardware.rearCard.SendController( + channel, MIDI_PAN_CONTROL, MIDI_CENTER_PAN_VALUE + ); + audio_hardware.rearCard.SendController( + channel, MIDI_REVERB_CONTROL, MIDI_MIN_CONTROL_VALUE + ); + audio_hardware.rearCard.SendController( + channel, MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE + ); + audio_hardware.rearCard.SelectBank(channel, 1); + + // + // Select program number + // + Tell("\nPlay program number (-1 to quit): "); + cin >> prognum; + progSelect = (MIDIValue)prognum; + Tell("\nPress to start or stop playing.\n"); + Tell("Hit to select a new program.\n"); + while (prognum != -1) + { + // Set Program + audio_hardware.frontCard.SendProgramChange(channel, progSelect); + audio_hardware.rearCard.SendProgramChange(channel, progSelect); + + audio_hardware.frontCard.SendNoteOn(channel, 60, 127); + audio_hardware.rearCard.SendNoteOn(channel, 60, 127); + noteIsOn = 1; + ch = (char)getch(); + + while (ch != ''){ + if (ch == ' ') + if (noteIsOn){ + Tell(" Note off\n"); + audio_hardware.frontCard.SendNoteOff(channel, 60, 0); + audio_hardware.rearCard.SendNoteOff(channel, 60, 0); + noteIsOn = 0; + } else { + Tell(" Note on\n"); + audio_hardware.frontCard.SendNoteOn(channel, 60, 127); + audio_hardware.rearCard.SendNoteOn(channel, 60, 127); + noteIsOn = 1; + } + ch = (char)getch(); + } + audio_hardware.frontCard.SendNoteOff(channel, 60, 0); + audio_hardware.rearCard.SendNoteOff(channel, 60, 0); + Tell("\nPlay program number (-1 to quit): "); + cin >> prognum; + progSelect = (MIDIValue)prognum; + } + } + #endif + + // + //------------------------------------------------------------------ + // Sequence through channels and notes + //------------------------------------------------------------------ + // + #if 0 + { + MIDIValue channel; + MIDIValue key; + + // + // Init channels + // + for (channel = 0; channel < 16; channel++) { + // + // Set to first bank, first program + // + + // Card 1 + audio_hardware.frontCard.SendController(channel, 0, 0); + audio_hardware.frontCard.SendProgramChange(channel, 0); + + // Card 2 + audio_hardware.rearCard.SendController(channel, 0, 0); + audio_hardware.rearCard.SendProgramChange(channel, 0); + } + + // + // Play sequence of keys + // + Tell("Sequence through channels and notes - Press ESC to stop\n"); + + for (channel = 0; channel < 16; channel++) + { + for (key = 60; key < 60+12; key++) + { + clock_t next_key_time; + + Tell("channel " << (int)channel << " key " << (int)key << "\n"); + + // Card 1 + audio_hardware.frontCard.SendNoteOn(channel, key, 127); + + // Card 2 + audio_hardware.rearCard.SendNoteOn(channel, key, 127); + + next_key_time = clock() + CLOCKS_PER_SEC/10; + while (clock() < next_key_time) + { + } + } + + for (key = 60; key < 60+12; key++) { + // Card 1 + audio_hardware.frontCard.SendNoteOff(channel, key, 127); + + // Card 2 + audio_hardware.rearCard.SendNoteOff(channel, key, 127); + } + + if (kbhit()) + { + if (getch() == '') + break; + } + } + } + #endif + + // + //------------------------------------------------------------------ + // Sequence through programs + //------------------------------------------------------------------ + // + #if 0 + { + clock_t end_time; + MIDIValue channel; + MIDIValue program; + + // + // Init channels + // + for (channel = 0; channel < 16; channel++) + { + // + // Set to second bank + // + + // Card 1 + audio_hardware.frontCard.SendController(channel, 121, 1); // Reset + audio_hardware.frontCard.SendController(channel, 0, 1); + + // Card 2 + audio_hardware.rearCard.SendController(channel, 121, 1); // Reset + audio_hardware.rearCard.SendController(channel, 0, 1); + } + + // + // Sequence through programs + // + for (program = 0; program < 128; program++) + { + // + // Set program + // + audio_hardware.frontCard.SendProgramChange(0, program); + audio_hardware.rearCard.SendProgramChange(0, program); + + Tell("Program " << (int)program << "\n"); + + // + // Play note + // + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + end_time = clock() + 8*CLOCKS_PER_SEC; + while (clock() < end_time) + { + } + + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + } + #endif + + // + //------------------------------------------------------------------ + // Test front volume controller + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_time, period, end_time; + float fvol; + MIDIValue vol; + + // + // Modulate volume + // + Tell("Volume should be modulated in the front\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + period = 2*CLOCKS_PER_SEC; + start_time = clock(); + end_time = start_time + 4*period; + while (clock() < end_time) + { + fvol = sin(RAD360 * (float)(clock() - start_time) / (float)period); + fvol += 1.0; + fvol *= 63.0; + vol = fvol; + + // Card 1 + audio_hardware.frontCard.SendController(0, 7, vol); + + Tell(" vol " << (int)vol); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendController(0, 7, 127); + Tell("\n"); + } + #endif + + // + //------------------------------------------------------------------ + // Test rear volume controller + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_time, period, end_time; + float fvol; + MIDIValue vol; + + // + // Modulate volume + // + Tell("Volume should be modulated in the rear\n"); + + // Card 2 + audio_hardware.rearCard.SendController(0, 121, 1); // Reset + audio_hardware.rearCard.SendController(0, 0, 1); // Bank + audio_hardware.rearCard.SendProgramChange(0, 2); // Pgm + audio_hardware.rearCard.SendController(0, 10, 63); // Pan Center + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + period = 2*CLOCKS_PER_SEC; + start_time = clock(); + end_time = start_time + 4*period; + while (clock() < end_time) + { + fvol = sin(RAD360 * (float)(clock() - start_time) / (float)period); + fvol += 1.0; + fvol *= 63.0; + vol = fvol; + + // Card 2 + audio_hardware.rearCard.SendController(0, 7, vol); + + Tell(" vol " << (int)vol); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + // Card 2 + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendController(0, 7, 127); + Tell("\n"); + } + #endif + + // + //------------------------------------------------------------------ + // Test pan controller + //------------------------------------------------------------------ + // + #if 0 + { + clock_t end_time; + + // Card 1 + audio_hardware.frontCard.SendController(0, 91, 0); // Reverb + audio_hardware.frontCard.SendController(0, 93, 0); // Chorus + + // Card 2 + audio_hardware.rearCard.SendController(0, 91, 0); // Reverb + audio_hardware.rearCard.SendController(0, 93, 0); // Chorus + + // + // Pan left + // + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 0); // Pgm + audio_hardware.frontCard.SendController(0, 10, 0); // Pan left + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + // Card 2 + audio_hardware.rearCard.SendController(0, 121, 1); // Reset + audio_hardware.rearCard.SendController(0, 0, 1); // Bank + audio_hardware.rearCard.SendProgramChange(0, 0); // Pgm + audio_hardware.rearCard.SendController(0, 10, 0); // Pan left + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + Tell("Note should be panned left\n"); + + end_time = clock() + 4*CLOCKS_PER_SEC; + while (clock() < end_time) + { + } + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + + // Card 2 + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + + // + // Pan Right + // + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 1); // Pgm + audio_hardware.frontCard.SendController(0, 10, 127); // Pan right + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + // Card 2 + audio_hardware.rearCard.SendController(0, 121, 1); // Reset + audio_hardware.rearCard.SendController(0, 0, 1); // Bank + audio_hardware.rearCard.SendProgramChange(0, 1); // Pgm + audio_hardware.rearCard.SendController(0, 10, 127); // Pan right + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + Tell("Note should be panned right\n"); + + end_time = clock() + 4*CLOCKS_PER_SEC; + while (clock() < end_time) + { + } + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + + // Card 2 + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + } + #endif + + // + //------------------------------------------------------------------ + // Test pitch bend + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_time, period, end_time; + float fpitch; + MIDIPitchBend pitch; + + // + // Modulate pitch + // + Tell("Pitch should be modulated\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + // Card 2 + audio_hardware.rearCard.SendController(0, 121, 1); // Reset + audio_hardware.rearCard.SendController(0, 0, 1); // Bank + audio_hardware.rearCard.SendProgramChange(0, 2); // Pgm + audio_hardware.rearCard.SendController(0, 10, 63); // Pan Center + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + period = 2*CLOCKS_PER_SEC; + start_time = clock(); + end_time = start_time + 4*period; + while (clock() < end_time) + { + fpitch = sin(RAD360 * (float)(clock() - start_time) / (float)period); + fpitch += 1.0; + fpitch *= 8191.0; + pitch = fpitch; + + // Card 1 + audio_hardware.frontCard.SendPitchBend(0, pitch); + + // Card 2 + audio_hardware.rearCard.SendPitchBend(0, pitch); + + Tell("pitch " << (int)pitch << "\n"); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendPitchBend(0, 8192); + + // Card 2 + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendPitchBend(0, 8192); + } + #endif + + // + //------------------------------------------------------------------ + // Test pitch NRPN + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_time, period, end_time; + float fpitch; + MIDINRPNValue pitch; + + // + // Modulate pitch + // + Tell("Pitch should be modulated\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + // Card 2 + audio_hardware.rearCard.SendController(0, 121, 1); // Reset + audio_hardware.rearCard.SendController(0, 0, 1); // Bank + audio_hardware.rearCard.SendProgramChange(0, 2); // Pgm + audio_hardware.rearCard.SendController(0, 10, 63); // Pan Center + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + period = 2*CLOCKS_PER_SEC; + start_time = clock(); + end_time = start_time + 4*period; + while (clock() < end_time) + { + fpitch = sin(RAD360 * (float)(clock() - start_time) / (float)period); + fpitch *= 8191.0; + pitch = fpitch; + + // Card 1 + audio_hardware.frontCard.SendNRPN(0, 16, pitch); + + // Card 2 + audio_hardware.rearCard.SendNRPN(0, 16, pitch); + + Tell("pitch " << (int)pitch << "\n"); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendNRPN(0, 16, 0); + + // Card 2 + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendNRPN(0, 16, 0); + } + #endif + + // + //------------------------------------------------------------------ + // Test filter cutoff NRPN + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_time, period, end_time; + float fcutoff; + MIDINRPNValue cutoff; + + // + // Modulate filter cutoff + // + Tell("Filter cutoff should be modulated\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + // Card 2 + audio_hardware.rearCard.SendController(0, 121, 1); // Reset + audio_hardware.rearCard.SendController(0, 0, 1); // Bank + audio_hardware.rearCard.SendProgramChange(0, 2); // Pgm + audio_hardware.rearCard.SendController(0, 10, 63); // Pan Center + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + period = 2*CLOCKS_PER_SEC; + start_time = clock(); + end_time = start_time + 4*period; + while (clock() < end_time) + { + fcutoff = sin(RAD360 * (float)(clock() - start_time) / (float)period); + fcutoff += 1.0; + fcutoff *= 63.0; + cutoff = fcutoff; + + // Card 1 + audio_hardware.frontCard.SendNRPN(0, 21, cutoff); + + // Card 2 + audio_hardware.rearCard.SendNRPN(0, 21, cutoff); + + Tell("cutoff " << (int)cutoff << "\n"); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendNRPN(0, 21, 127); + + // Card 2 + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendNRPN(0, 21, 127); + } + #endif + + // + //------------------------------------------------------------------ + // Test reverb and chorus settings + //------------------------------------------------------------------ + // + #if 0 + { + clock_t end_time; + int i; + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 0); // Bank + audio_hardware.frontCard.SendProgramChange(0, 0); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + + // Card 2 + audio_hardware.rearCard.SendController(0, 121, 1); // Reset + audio_hardware.rearCard.SendController(0, 0, 0); // Bank + audio_hardware.rearCard.SendProgramChange(0, 0); // Pgm + audio_hardware.rearCard.SendController(0, 10, 63); // Pan Center + + // Card 1 + audio_hardware.frontCard.SendController(0, 91, 127); // Reverb + audio_hardware.frontCard.SendController(0, 93, 0); // Chorus + + // Card 2 + audio_hardware.rearCard.SendController(0, 91, 127); // Reverb + audio_hardware.rearCard.SendController(0, 93, 0); // Chorus + + for (i = 0; i < 8; i++) + { + #pragma warn -sig + audio_hardware.frontCard.SelectEffect(ReverbMIDIEffectType, i); // Reverb + audio_hardware.rearCard.SelectEffect(ReverbMIDIEffectType, i); // Reverb + #pragma warn +sig + + Tell("Reverb " << i << "\n"); + + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + end_time = clock() + 3*CLOCKS_PER_SEC; + while (clock() < end_time) + { + } + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + + // Card 1 + audio_hardware.frontCard.SendController(0, 91, 0); // Reverb + audio_hardware.frontCard.SendController(0, 93, 127); // Chorus + + // Card 2 + audio_hardware.rearCard.SendController(0, 91, 0); // Reverb + audio_hardware.rearCard.SendController(0, 93, 127); // Chorus + + for (i = 0; i < 8; i++) + { + #pragma warn -sig + audio_hardware.frontCard.SelectEffect(ChorusMIDIEffectType, i); // Chorus + audio_hardware.rearCard.SelectEffect(ChorusMIDIEffectType, i); // Chorus + #pragma warn +sig + + Tell("Chorus " << i << "\n"); + + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + audio_hardware.rearCard.SendNoteOn(0, 60, 127); + + end_time = clock() + 3*CLOCKS_PER_SEC; + while (clock() < end_time) + { + } + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.rearCard.SendNoteOff(0, 60, 0); + + if (kbhit()) + { + if (getch() == '') + break; + } + } + } + #endif + + // + // Close down + // + audio_hardware.Close(); + + return True; +} + +// +//############################################################################# +// ProfileClass +//############################################################################# +// +#define RAD360 (6.28318) + +Logical + AudioHardware::ProfileClass() +{ + AudioHardware audio_hardware; + + Tell("AudioHardware::ProfileClass\n"); + + // + // Init the audio hardware + // + audio_hardware.Initialize(); + + audio_hardware.frontCard.LoadSBK("test.sbk"); + audio_hardware.rearCard.LoadSBK("test.sbk"); + + // + //------------------------------------------------------------------ + // Sequence through channels and notes + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_timer, total_timer; + int number_of_calls; + MIDIValue channel; + MIDIValue key; + + // + // Init channels + // + for (channel = 0; channel < 16; channel++) { + // + // Set to first bank, first program + // + + // Card 1 + audio_hardware.frontCard.SendController(channel, 0, 0); + audio_hardware.frontCard.SendProgramChange(channel, 0); + + // Card 2 + audio_hardware.rearCard.SendController(channel, 0, 0); + audio_hardware.rearCard.SendProgramChange(channel, 0); + } + + // + // Play sequence of keys + // + Tell("Sequence through channels and notes\n"); + + total_timer = 0; + start_timer = clock(); + for (channel = 0; channel < 16; channel++) + { + for (key = 0; key < 128; key++) + { + // Card 1 + audio_hardware.frontCard.SendNoteOn(channel, key, 127); + + // Card 2 + audio_hardware.rearCard.SendNoteOn(channel, key, 127); + } + + for (key = 0; key < 128; key++) { + // Card 1 + audio_hardware.frontCard.SendNoteOff(channel, key, 127); + + // Card 2 + audio_hardware.rearCard.SendNoteOff(channel, key, 127); + } + } + total_timer += clock() - start_timer; + number_of_calls = 16 * 2 * 128 * 2; + Tell("Calls " << number_of_calls << " Duration " << total_timer << "\n"); + Tell( + "Calls 1000 Duration " << + (Scalar)total_timer / (Scalar)number_of_calls << + " secs\n" + ); + } + #endif + + // + //------------------------------------------------------------------ + // Test front volume controller + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_timer, total_timer; + int number_of_calls, i; + + // + // Modulate volume + // + Tell("Volume modulated in the front\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + number_of_calls = 100000; + i = 0; + total_timer = 0; + start_timer = clock(); + while (i < number_of_calls) + { + // Card 1 + audio_hardware.frontCard.SendController(0, 7, (MIDIValue)i); + i++; + } + total_timer += clock() - start_timer; + Tell("Calls " << number_of_calls << " Duration " << total_timer << "\n"); + Tell( + "Calls 1000 Duration " << + (Scalar)total_timer / (Scalar)number_of_calls << + " secs\n" + ); + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendController(0, 7, 127); + } + #endif + + // + //------------------------------------------------------------------ + // Test pitch bend + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_timer, total_timer; + int number_of_calls, i; + + // + // Modulate pitch + // + Tell("Pitch modulated\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + number_of_calls = 100000; + i = 0; + total_timer = 0; + start_timer = clock(); + while (i < number_of_calls) + { + audio_hardware.frontCard.SendPitchBend(0, i); + i++; + } + total_timer += clock() - start_timer; + Tell("Calls " << number_of_calls << " Duration " << total_timer << "\n"); + Tell( + "Calls 1000 Duration " << + (Scalar)total_timer / (Scalar)number_of_calls << + " secs\n" + ); + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendPitchBend(0, 8192); + } + #endif + + // + //------------------------------------------------------------------ + // Test pitch NRPN + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_timer, total_timer; + int number_of_calls, i; + + // + // Modulate pitch + // + Tell("Pitch NRPN modulated\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + number_of_calls = 100000; + i = 0; + total_timer = 0; + start_timer = clock(); + while (i < number_of_calls) + { + audio_hardware.frontCard.SendNRPN(0, 16, i); + i++; + } + total_timer += clock() - start_timer; + Tell("Calls " << number_of_calls << " Duration " << total_timer << "\n"); + Tell( + "Calls 1000 Duration " << + (Scalar)total_timer / (Scalar)number_of_calls << + " secs\n" + ); + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendNRPN(0, 16, 0); + } + #endif + + // + //------------------------------------------------------------------ + // Test filter NRPN + //------------------------------------------------------------------ + // + #if 0 + { + clock_t start_timer, total_timer; + int number_of_calls, i; + + // + // Modulate pitch + // + Tell("Filter NRPN modulated\n"); + + // Card 1 + audio_hardware.frontCard.SendController(0, 121, 1); // Reset + audio_hardware.frontCard.SendController(0, 0, 1); // Bank + audio_hardware.frontCard.SendProgramChange(0, 2); // Pgm + audio_hardware.frontCard.SendController(0, 10, 63); // Pan Center + audio_hardware.frontCard.SendNoteOn(0, 60, 127); + + number_of_calls = 100000; + i = 0; + total_timer = 0; + start_timer = clock(); + while (i < number_of_calls) + { + audio_hardware.frontCard.SendNRPN(0, 21, i); + i++; + } + total_timer += clock() - start_timer; + Tell("Calls " << number_of_calls << " Duration " << total_timer << "\n"); + Tell( + "Calls 1000 Duration " << + (Scalar)total_timer / (Scalar)number_of_calls << + " secs\n" + ); + + // Card 1 + audio_hardware.frontCard.SendNoteOff(0, 60, 0); + audio_hardware.frontCard.SendNRPN(0, 21, 127); + } + #endif + + // + // Close down + // + audio_hardware.Close(); + + return True; +} + + diff --git a/CODE/RP/MUNGA_L4/L4AUDIO.CPP b/CODE/RP/MUNGA_L4/L4AUDIO.CPP new file mode 100644 index 0000000..0fbf625 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDIO.CPP @@ -0,0 +1,2329 @@ +//===========================================================================// +// File: l4audio.cc // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDIO_HPP) +# include +#endif + +#if !defined(L4AUDLVL_HPP) +# include +#endif + +#if !defined(L4APP_HPP) +# include +#endif + +#if !defined(L4AUDRND_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +//############################################################################# +//####################### L4AudioSpatialization ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +L4AudioSpatialization::L4AudioSpatialization() +{ + azimuthOfSource = 0.0f; + + frontLeftScale = 0.0f; + frontRightScale = 0.0f; + rearLeftScale = 0.0f; + rearRightScale = 0.0f; + + frontLeftDelay = 0.0f; + frontRightDelay = 0.0f; + rearLeftDelay = 0.0f; + rearRightDelay = 0.0f; + + quadrant = Quadrant1; +} + +// +//############################################################################# +//############################################################################# +// +L4AudioSpatialization::~L4AudioSpatialization() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioSpatialization::TestInstance() const +{ + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSpatialization::CalculateSpatialization(Radian azimuth_of_source) +{ + azimuthOfSource = azimuth_of_source; + + // + //--------------------------------------------------------------- + // Make azimuth usable for channel volume calculations + //--------------------------------------------------------------- + // + #define DEG_90 (90.0f*(RAD_PER_DEG)) + #define DEG_180 (180.0f*(RAD_PER_DEG)) + #define DEG_360 (360.0f*(RAD_PER_DEG)) + + azimuthOfSource = DEG_180 + azimuthOfSource; + if (azimuthOfSource > DEG_180) + azimuthOfSource = azimuthOfSource - DEG_360; + Verify( + azimuthOfSource <= DEG_180 && + azimuthOfSource >= -DEG_180 + ); + + // + //--------------------------------------------------------------- + // Channel volume scale and ITD calculations + //--------------------------------------------------------------- + // + + // + // Get audio head constants + // + L4AudioRenderer *audio_renderer; + AudioHead *audio_head; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + // + // Init channel volume scale variables + // + const Radian azimuth_max = 45.0*RAD_PER_DEG; // HACK - should come from audio.ini + Scalar tangent_ratio; + + frontLeftScale = 0.0f; + frontRightScale = 0.0f; + rearLeftScale = 0.0f; + rearRightScale = 0.0f; + + // + // Init ITD parameters + // + const Scalar itd_delay = audio_head->GetITDDifference(); + + frontLeftDelay = 0.0f; + frontRightDelay = 0.0f; + rearLeftDelay = 0.0f; + rearRightDelay = 0.0f; + + // + //--------------------------------------------------------------- + // Quadrant 1 + //--------------------------------------------------------------- + // + if ( + azimuthOfSource > -azimuth_max && + azimuthOfSource < azimuth_max + ) + { + quadrant = Quadrant1; + + // volume scale + Verify(!Small_Enough(tan(azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(azimuth_max)) * 0.5f; + + frontLeftScale = Sqrt(0.5f + tangent_ratio); + frontRightScale = Sqrt(0.5f - tangent_ratio); + Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f); + Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > 0.0f) + { + frontLeftDelay = itd_delay * tangent_ratio * 2.0f; + } + else + { + frontRightDelay = itd_delay * -tangent_ratio * 2.0f; + } + } + // + //--------------------------------------------------------------- + // Quadrant 2 + //--------------------------------------------------------------- + // + else if ( + azimuthOfSource > azimuth_max && + azimuthOfSource < (DEG_180 - azimuth_max) + ) + { + quadrant = Quadrant2; + + // volume scale + azimuthOfSource = azimuthOfSource - DEG_90; + + Verify(!Small_Enough(tan(DEG_90 - azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(DEG_90 - azimuth_max)) * 0.5f; + + rearLeftScale = Sqrt(0.5f + tangent_ratio); + frontLeftScale = Sqrt(0.5f - tangent_ratio); + Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f); + Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > 0.0f) + { + rearLeftDelay = itd_delay * tangent_ratio * 2.0f; + } + else + { + frontLeftDelay = itd_delay * -tangent_ratio * 2.0f; + } + } + // + //--------------------------------------------------------------- + // Quadrant 3 + //--------------------------------------------------------------- + // + else if ( + azimuthOfSource > (DEG_180 - azimuth_max) || + azimuthOfSource < (-DEG_180 + azimuth_max) + ) + { + quadrant = Quadrant3; + + // volume scale + azimuthOfSource = azimuthOfSource - DEG_180; + + Verify(!Small_Enough(tan(azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(azimuth_max)) * 0.5f; + + rearRightScale = Sqrt(0.5f + tangent_ratio); + rearLeftScale = Sqrt(0.5f - tangent_ratio); + Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f); + Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > -azimuth_max) + { + rearLeftDelay = -(itd_delay * tangent_ratio * 2.0f); + } + else + { + rearRightDelay = -(itd_delay * -tangent_ratio * 2.0f); + } + + #if 0 + Tell( + "azimuthOfSource " << azimuthOfSource << + " rearRightDelay " << rearRightDelay << + " rearLeftDelay " << rearLeftDelay << + "\n" + ); + #endif + } + // + //--------------------------------------------------------------- + // Quadrant 4 + //--------------------------------------------------------------- + // + else + { + quadrant = Quadrant4; + + Verify( + azimuthOfSource > (-DEG_180 + azimuth_max) && + azimuthOfSource < -azimuth_max + ); + + // volume scale + azimuthOfSource = azimuthOfSource + DEG_90; + + Verify(!Small_Enough(tan(DEG_90 - azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(DEG_90 - azimuth_max)) * 0.5f; + + frontRightScale = Sqrt(0.5f + tangent_ratio); + rearRightScale = Sqrt(0.5f - tangent_ratio); + Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f); + Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > 0.0f) + { + frontRightDelay = itd_delay * tangent_ratio * 2.0f; + } + else + { + rearRightDelay = itd_delay * -tangent_ratio * 2.0f; + } + } + + #if 0 + Tell( + "FL " << frontLeftScale << + " FR " << frontRightScale << + " RL " << rearLeftScale << + " RR " << rearRightScale << + "\n" + ); + #endif + + #if 0 + Tell( + "Quadrant " << quadrant << + " FL " << frontLeftDelay << + " FR " << frontRightDelay << + " RL " << rearLeftDelay << + " RR " << rearRightDelay << + "\n" + ); + #endif + + Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f); + Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f); + Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f); + Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f); +} + +//############################################################################# +//######################### L4AudioLocation ############################# +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +L4AudioLocation::L4AudioLocation( + PlugStream *stream, + Entity *entity +): + AudioLocation(stream, entity) +{ + L4AudioLocationX(); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioLocation::L4AudioLocationX() +{ + // + // Get audio renderer frame duration + // + Check(application) + L4AudioRenderer *audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + + Time frame_duration = + audio_renderer->GetCalibrationFrameDuration(); + + // + // Init ITD pitch offset variables + // + lastITDFrameTime = Now(); + lastITDFrameTime -= frame_duration; + + currentFrontLeftDelay = 0.0f; + currentFrontRightDelay = 0.0f; + currentRearLeftDelay = 0.0f; + currentRearRightDelay = 0.0f; + + frontLeftITDPitchOffset = 0.0f; + frontRightITDPitchOffset = 0.0f; + rearLeftITDPitchOffset = 0.0f; + rearRightITDPitchOffset = 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +L4AudioLocation::~L4AudioLocation() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioLocation::TestInstance() const +{ + AudioLocation::TestInstance(); + Check(&spatialization); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioLocation::UpdateSpatialModelImplementation(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + + // + //--------------------------------------------------------------- + // Call inherited method + //--------------------------------------------------------------- + // + AudioLocation::UpdateSpatialModelImplementation(audio_head); + + // + //--------------------------------------------------------------- + // Catch case of head == source + //--------------------------------------------------------------- + // + if (IsHeadSource()) + { + spatialization.frontLeftScale = 1.0f; + spatialization.frontRightScale = 1.0f; + spatialization.rearLeftScale = 1.0f; + spatialization.rearRightScale = 1.0f; + + frontLeftITDPitchOffset = 0.0f; + frontRightITDPitchOffset = 0.0f; + rearLeftITDPitchOffset = 0.0f; + rearRightITDPitchOffset = 0.0f; + return; + } + + // + //--------------------------------------------------------------- + // Calculate channel spatialization + //--------------------------------------------------------------- + // + spatialization.CalculateSpatialization(GetAzimuthOfSource()); + + // + //--------------------------------------------------------------- + // Calculate ITD pitch offsets + //--------------------------------------------------------------- + // + const Scalar itd_pitch_offset_constant = + 0.003831f / 0.000002f; // period / delay // HACK - should come from audio head + + Time itd_delta_time; + + itd_delta_time = Now(); + itd_delta_time -= lastITDFrameTime; + lastITDFrameTime = Now(); + + frontLeftITDPitchOffset = 0.0f; + frontRightITDPitchOffset = 0.0f; + rearLeftITDPitchOffset = 0.0f; + rearRightITDPitchOffset = 0.0f; + + if (!Small_Enough((Scalar)itd_delta_time)) + { + if (currentFrontLeftDelay != spatialization.frontLeftDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + frontLeftITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.frontLeftDelay - currentFrontLeftDelay) / + (Scalar)itd_delta_time; + currentFrontLeftDelay = spatialization.frontLeftDelay; + } + if (currentFrontRightDelay != spatialization.frontRightDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + frontRightITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.frontRightDelay - currentFrontRightDelay) / + (Scalar)itd_delta_time; + currentFrontRightDelay = spatialization.frontRightDelay; + } + if (currentRearLeftDelay != spatialization.rearLeftDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + rearLeftITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.rearLeftDelay - currentRearLeftDelay) / + (Scalar)itd_delta_time; + currentRearLeftDelay = spatialization.rearLeftDelay; + } + if (currentRearRightDelay != spatialization.rearRightDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + rearRightITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.rearRightDelay - currentRearRightDelay) / + (Scalar)itd_delta_time; + currentRearRightDelay = spatialization.rearRightDelay; + } + } + + #if 0 + Tell( + "Quadrant " << spatialization.quadrant << + " FL " << frontLeftITDPitchOffset << + " FR " << frontRightITDPitchOffset << + " RL " << rearLeftITDPitchOffset << + " RR " << rearRightITDPitchOffset << + "\n" + ); + #endif + + // + //--------------------------------------------------------------- + // Check for source "between ears" + //--------------------------------------------------------------- + // + const Scalar ear_radius = + audio_head->GetDistanceBetweenEars() * 0.5; + Scalar distance_to_source_listener_plane = + GetDistanceToSourceListenerPlane(); + + if (distance_to_source_listener_plane < ear_radius) + { + Verify(!Small_Enough(ear_radius)); + + const Scalar proportion = + 0.5f * + (ear_radius - distance_to_source_listener_plane) / + ear_radius; + + Scalar powerA, powerB; + + #if DEBUG_LEVEL>0 + if (!(proportion >= 0.0f && proportion <= 1.0f)) + { + Dump(ear_radius); + Dump(distance_to_source_listener_plane); + Dump(proportion); + } + Verify(proportion >= 0.0f && proportion <= 1.0f); + #endif + + powerA = Sqrt(1.0f - proportion); + powerB = Sqrt(proportion); + Verify(powerA >= 0.0f && powerA <= 1.0f); + Verify(powerB >= 0.0f && powerB <= 1.0f); + + switch (spatialization.quadrant) + { + case L4AudioSpatialization::Quadrant1: + spatialization.rearLeftScale = spatialization.frontLeftScale * powerB; + spatialization.rearRightScale = spatialization.frontRightScale * powerB; + + spatialization.frontLeftScale *= powerA; + spatialization.frontRightScale *= powerA; + break; + + case L4AudioSpatialization::Quadrant2: + spatialization.rearRightScale = spatialization.rearLeftScale * powerB; + spatialization.frontRightScale = spatialization.frontLeftScale * powerB; + + spatialization.rearLeftScale *= powerA; + spatialization.frontLeftScale *= powerA; + break; + + case L4AudioSpatialization::Quadrant3: + spatialization.frontRightScale = spatialization.rearRightScale * powerB; + spatialization.frontLeftScale = spatialization.rearLeftScale * powerB; + + spatialization.rearRightScale *= powerA; + spatialization.rearLeftScale *= powerA; + break; + + case L4AudioSpatialization::Quadrant4: + spatialization.frontLeftScale = spatialization.frontRightScale * powerB; + spatialization.rearLeftScale = spatialization.rearRightScale * powerB; + + spatialization.frontRightScale *= powerA; + spatialization.rearRightScale *= powerA; + break; + } + + #if 0 + Tell( + "FL " << spatialization.frontLeftScale << + " FR " << spatialization.frontRightScale << + " RL " << spatialization.rearLeftScale << + " RR " << spatialization.rearRightScale << + "\n" + ); + #endif + } + + Verify(spatialization.frontLeftScale >= 0.0f && spatialization.frontLeftScale <= 1.0f); + Verify(spatialization.frontRightScale >= 0.0f && spatialization.frontRightScale <= 1.0f); + Verify(spatialization.rearLeftScale >= 0.0f && spatialization.rearLeftScale <= 1.0f); + Verify(spatialization.rearRightScale >= 0.0f && spatialization.rearRightScale <= 1.0f); +} + +//############################################################################# +//######################### AudioChannelSet ############################# +//############################################################################# + +AudioChannelSet AudioChannelSet::Null; + +// +//############################################################################# +//############################################################################# +// +AudioChannelSet::AudioChannelSet() +{ + for (int i = 0; i < AudioChannelSetSize; i++) + { + channels[i] = NULL; + enables[i] = False; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioChannelSet::TestInstance() const +{ + for (int i = 0; i < AudioChannelSetSize; i++) + { + if (channels[i] != NULL) + { + Verify(enables[i] == True); + Check(channels[i]); + } + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioChannelSet::EnableAll() +{ + // + // Must set all channels to null and all enables to True + // + for (int i = 0; i < AudioChannelSetSize; i++) + { + channels[i] = NULL; + enables[i] = True; + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioChannelSet::ReleaseAll() +{ + // + // Must release all channels without changing enable values + // + for (int i = 0; i < AudioChannelSetSize; i++) + { + if (channels[i] != NULL) + { + Check(channels[i]); + channels[i]->Release(); + channels[i] = NULL; + } + } +} + +//############################################################################# +//########################## L4AudioSource ############################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +L4AudioSource::L4AudioSource( + PlugStream *stream, + Entity *entity +): + AudioSource(stream, entity) +{ + L4AudioSourceX(); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::L4AudioSourceX() +{ +} + +// +//############################################################################# +//############################################################################# +// +L4AudioSource::~L4AudioSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioSource::TestInstance() const +{ + AudioSource::TestInstance(); + Check(&channelSet); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::StopMessageImplementation() +{ + Check(this); + + AudioSource::StopMessageImplementation(); + + // + // Request stop from renderer + // + Check(application); + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())-> + StopRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::SetAudioChannelSet(const AudioChannelSet &audio_channel_set) +{ + Check(this); + channelSet = audio_channel_set; +} + +// +//############################################################################# +//############################################################################# +// +const AudioChannelSet* + L4AudioSource::GetAudioChannelSet() +{ + Check(this); + return &channelSet; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::ReleaseChannels() +{ + Check(this); + channelSet.ReleaseAll(); +} + +//############################################################################# +//######################## DirectPatchSource ############################ +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +DirectPatchSource::DirectPatchSource( + PlugStream *stream, + Entity *entity +): + L4AudioSource(stream, entity) +{ + MemoryStream_Read(stream, &audioPosition); + channel = NULL; +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + L4AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, position); +} + +// +//############################################################################# +//############################################################################# +// +DirectPatchSource::~DirectPatchSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + DirectPatchSource::TestInstance() const +{ + L4AudioSource::TestInstance(); + if (channel != NULL) + { + Check(channel); + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::StartMessageImplementation() +{ + Check(this); + + L4AudioSource::StartMessageImplementation(); + + // + //-------------------------------------------------------------------------- + // Init channel set to requested channels + //-------------------------------------------------------------------------- + // + channelSet = AudioChannelSet::Null; + switch (audioPosition) + { + case FrontDirectPatchPosition: + case FrontLeftDirectPatchPosition: + case FrontRightDirectPatchPosition: + channelSet.EnableFrontLeft(True); + break; + + case RearDirectPatchPosition: + case RearLeftDirectPatchPosition: + case RearRightDirectPatchPosition: + channelSet.EnableRearLeft(True); + break; + } + + // + //-------------------------------------------------------------------------- + // Request start from renderer + //-------------------------------------------------------------------------- + // + Check(application); + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())-> + StartRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::StartImplementation() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------------- + // + L4AudioSource::StartImplementation(); + + // + //-------------------------------------------------------------------------- + // Remember the channel + //-------------------------------------------------------------------------- + // + Verify(channel == NULL); + switch (audioPosition) + { + case FrontDirectPatchPosition: + case FrontLeftDirectPatchPosition: + case FrontRightDirectPatchPosition: + channel = channelSet.GetFrontLeft(); + break; + + case RearDirectPatchPosition: + case RearLeftDirectPatchPosition: + case RearRightDirectPatchPosition: + channel = channelSet.GetRearLeft(); + break; + } + Check(channel); + + // + //-------------------------------------------------------------------------- + // Setup the channel + //-------------------------------------------------------------------------- + // + ExecuteWatchers(); + + // + // Turn the volume down while setting up the channel + // + channel->SendController(MIDI_VOLUME_CONTROL, MIDI_MIN_CONTROL_VALUE); + + // + // Set the channel to the bank and program + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->SetDistance(GetDistanceToSource()); + patch_resource->SetupPatch(channel); + + // + // Set the channel to default control values + // + channel->SendController(MIDI_REVERB_CONTROL, MIDI_MIN_CONTROL_VALUE); + channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE); + + switch (audioPosition) + { + case FrontDirectPatchPosition: + case RearDirectPatchPosition: + channel->SendController(MIDI_PAN_CONTROL, MIDI_CENTER_PAN_VALUE); + break; + case FrontLeftDirectPatchPosition: + case RearLeftDirectPatchPosition: + channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE); + break; + case FrontRightDirectPatchPosition: + case RearRightDirectPatchPosition: + channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE); + break; + } + + // + // Set midi history to default control values + // + lastMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastMIDIPitchBend = 0; // Set by force update + lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch load + + // + //-------------------------------------------------------------------------- + // Calculate attack time, velocity, and execute model + //-------------------------------------------------------------------------- + // + MIDIValue midi_velocity = + CalculateSourceAttackVolumeScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (UseSourceAttackTime()) + { + MIDINRPNValue midi_attack_time = + CalculateSourceAttackTime() * + (Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f; + + channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time); + } + + ExecuteModel(True); + + // + //-------------------------------------------------------------------------- + // Start note + //-------------------------------------------------------------------------- + // + channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity); + #if 0 + Tell("On " << (int)GetCurrentNoteValue() << "\n"); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::StopImplementation() +{ + Check(this); + + // + // Stop note + // + Check(channel); + channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE); + channel = NULL; +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::ExecuteModel(Logical force_update) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Apply pitch offset + //-------------------------------------------------------------------------- + // + const MIDIPitchBend pitch_resolution = 12; // HACK - should come from audio.ini + AudioPitchCents pitch_offset; + MIDIPitchBend midi_pitch_bend; + MIDIPitchBend pitch_difference; + + pitch_offset = CalculateSourcePitchOffset(); + midi_pitch_bend = (Scalar)pitch_offset * MIDI_PITCH_PER_CENTS + 0.5f; + Clamp(midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX); + pitch_difference = lastMIDIPitchBend - midi_pitch_bend; + + if ((Abs(pitch_difference) >= pitch_resolution) || force_update) + { + lastMIDIPitchBend = midi_pitch_bend; + Check(channel); + channel->SendPitchBend(midi_pitch_bend); + } + + // + //-------------------------------------------------------------------------- + // Apply filter scale + //-------------------------------------------------------------------------- + // + if (UseSourceBrightnessScale()) + { + const MIDINRPNValue filter_resolution = 2;// HACK - should come from audio.ini + Scalar filter_scale; + PatchResource *patch_resource; + MIDINRPNValue max_midi_filter_cutoff; + MIDINRPNValue midi_filter_cutoff; + MIDINRPNValue filter_difference; + + filter_scale = CalculateSourceBrightnessScale(); + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + max_midi_filter_cutoff = patch_resource->GetMaxMIDIFilterCutoff(); + midi_filter_cutoff = filter_scale * (Scalar)max_midi_filter_cutoff + 0.5f; + filter_difference = lastMIDIFilterCutoff - midi_filter_cutoff; + + if (Abs(filter_difference) >= filter_resolution) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + Check(channel); + channel->SendNRPN(AWE_FILTER_CUTOFF_NRPN, midi_filter_cutoff); + } + } + + // + //-------------------------------------------------------------------------- + // Apply volume scale + //-------------------------------------------------------------------------- + // + Scalar volume_scale; + const MIDIValue volume_resolution = 2; // HACK - should come from audio.ini + MIDIValue midi_volume; + int volume_difference; + + volume_scale = CalculateSourceVolumeScale(); + midi_volume = volume_scale * (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + volume_difference = lastMIDIVolume - midi_volume; + + if (Abs(volume_difference) >= volume_resolution) + { + lastMIDIVolume = midi_volume; + Check(channel); + channel->SendController(MIDI_VOLUME_CONTROL, midi_volume); + } +} + +//############################################################################# +//###################### Dynamic3DPatchSource ########################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +Dynamic3DPatchSource::Dynamic3DPatchSource( + PlugStream *stream, + Entity *entity +): + L4AudioSource(stream, entity) +{ +} + +// +//############################################################################# +//############################################################################# +// +Dynamic3DPatchSource::~Dynamic3DPatchSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Dynamic3DPatchSource::TestInstance() const +{ + L4AudioSource::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::StartMessageImplementation() +{ + Check(this); + + L4AudioSource::StartMessageImplementation(); + + // + // Init channel set to requested channels + // + channelSet.EnableAll(); + + // + // Request start from renderer + // + Check(application); + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())-> + StartRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::StartImplementation() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------------- + // + L4AudioSource::StartImplementation(); + + // + //-------------------------------------------------------------------------- + // Get application, renderer and head pointers + //-------------------------------------------------------------------------- + // + L4AudioRenderer *audio_renderer; + AudioHead *audio_head; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + // + //-------------------------------------------------------------------------- + // Setup the channel + //-------------------------------------------------------------------------- + // + ExecuteWatchers(); + + // + // Turn the volume down while setting up the channels + // + int i; + AudioChannel *channel; + + for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendController(MIDI_VOLUME_CONTROL, MIDI_MIN_CONTROL_VALUE); + } + + // + // Set the channels to the bank and program + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->SetDistance(GetDistanceToSource()); + for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + patch_resource->SetupPatch(channel); + } + + // + // Set the channels to default control values + // + MIDIValue midi_reverb_level = + audio_head->GetGlobalReverbScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendController(MIDI_REVERB_CONTROL, midi_reverb_level); + channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE); + } + + // + // Set the channels to correct pan + // + channel = channelSet.GetFrontLeft(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE); + + channel = channelSet.GetFrontRight(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE); + + channel = channelSet.GetRearLeft(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE); + + channel = channelSet.GetRearRight(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE); + + // + // Set midi history to default control values + // + lastFrontLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastFrontRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastFrontLeftMIDIPitchBend = 0; // Set by force update + lastFrontRightMIDIPitchBend = 0; // Set by force update + lastRearLeftMIDIPitchBend = 0; // Set by force update + lastRearRightMIDIPitchBend = 0; // Set by force update + lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch + + // + //-------------------------------------------------------------------------- + // Calculate attack time, velocity, and execute model + //-------------------------------------------------------------------------- + // + MIDIValue midi_velocity = + CalculateSourceAttackVolumeScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (UseSourceAttackTime()) + { + MIDINRPNValue midi_attack_time = + CalculateSourceAttackTime() * + (Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f; + + for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time); + } + } + + ExecuteModel(True); + + // + //-------------------------------------------------------------------------- + // Start note + //-------------------------------------------------------------------------- + // + for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity); + } +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::StopImplementation() +{ + Check(this); + + // + // Stop note + // + AudioChannel *channel; + for (int i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE); + } +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::ExecuteModel(Logical force_update) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------------- + // + L4AudioSource::Execute(); + + // + //-------------------------------------------------------------------------- + // Get audio resource + //-------------------------------------------------------------------------- + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + + // + //-------------------------------------------------------------------------- + // Get audio location + //-------------------------------------------------------------------------- + // + L4AudioLocation *audio_location; + + audio_location = Cast_Object(L4AudioLocation*, GetAudioLocation()); + Check(audio_location); + + // + //-------------------------------------------------------------------------- + // Render spatial model + //-------------------------------------------------------------------------- + // + AudioChannel *front_left_channel = channelSet.GetFrontLeft(); + AudioChannel *front_right_channel = channelSet.GetFrontRight(); + AudioChannel *rear_left_channel = channelSet.GetRearLeft(); + AudioChannel *rear_right_channel = channelSet.GetRearRight(); + + Check(front_left_channel); + Check(front_right_channel); + Check(rear_left_channel); + Check(rear_right_channel); + + // + // Apply distance attenuation to volume scale + // + Scalar volume_scale = CalculateSourceVolumeScale(); + + // + // Apply speaker scaling to volume and calculate MIDI volume + // + Scalar volume_temp; + MIDIValue front_left_midi_volume; + MIDIValue front_right_midi_volume; + MIDIValue rear_left_midi_volume; + MIDIValue rear_right_midi_volume; + + volume_temp = volume_scale * (Scalar)MIDI_MAX_CONTROL_VALUE; + + front_left_midi_volume = + audio_location->GetFrontLeftScale() * + volume_temp + 0.5f; + + front_right_midi_volume = + audio_location->GetFrontRightScale() * + volume_temp + 0.5f; + + rear_left_midi_volume = + audio_location->GetRearLeftScale() * + volume_temp + 0.5f; + + rear_right_midi_volume = + audio_location->GetRearRightScale() * + volume_temp + 0.5f; + + // + // Apply Doppler offset to pitch + // + Scalar pitch_offset; + + pitch_offset = CalculateSourcePitchOffset(); + pitch_offset += audio_location->GetDopplerCents(); + + // + // Apply ITD pitch offset and calculate MIDI pitch bend + // + MIDIPitchBend front_left_midi_pitch_bend; + MIDIPitchBend front_right_midi_pitch_bend; + MIDIPitchBend rear_left_midi_pitch_bend; + MIDIPitchBend rear_right_midi_pitch_bend; + + front_left_midi_pitch_bend = + (pitch_offset + audio_location->GetFrontLeftITDPitchOffset()) * + MIDI_PITCH_PER_CENTS + 0.5f; + + front_right_midi_pitch_bend = + (pitch_offset + audio_location->GetFrontRightITDPitchOffset()) * + MIDI_PITCH_PER_CENTS + 0.5f; + + rear_left_midi_pitch_bend = + (pitch_offset + audio_location->GetRearLeftITDPitchOffset()) * + MIDI_PITCH_PER_CENTS + 0.5f; + + rear_right_midi_pitch_bend = + (pitch_offset + audio_location->GetRearRightITDPitchOffset()) * + MIDI_PITCH_PER_CENTS + 0.5f; + + Clamp(front_left_midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX); + Clamp(front_right_midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX); + Clamp(rear_left_midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX); + Clamp(rear_right_midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX); + + // + // Apply high frequency scale to cutoff and calculate NRPN cutoff + // + Scalar filter_scale; + MIDINRPNValue max_midi_filter_cutoff; + MIDINRPNValue midi_filter_cutoff; + + filter_scale = CalculateSourceBrightnessScale(); + filter_scale *= audio_location->GetHighFreqCutoffScale(); + + max_midi_filter_cutoff = patch_resource->GetMaxMIDIFilterCutoff(); + midi_filter_cutoff = filter_scale * (Scalar)max_midi_filter_cutoff + 0.5f; + + // + //-------------------------------------------------------------------------- + // Send pitch bend + //-------------------------------------------------------------------------- + // + const MIDIPitchBend pitch_resolution = 2; + MIDIPitchBend pitch_difference; + + pitch_difference = front_left_midi_pitch_bend - lastFrontLeftMIDIPitchBend; + if (Abs(pitch_difference) >= pitch_resolution || force_update) + { + lastFrontLeftMIDIPitchBend = front_left_midi_pitch_bend; + front_left_channel->SendPitchBend(front_left_midi_pitch_bend); + } + + pitch_difference = front_right_midi_pitch_bend - lastFrontRightMIDIPitchBend; + if (Abs(pitch_difference) >= pitch_resolution || force_update) + { + lastFrontRightMIDIPitchBend = front_right_midi_pitch_bend; + front_right_channel->SendPitchBend(front_right_midi_pitch_bend); + } + + pitch_difference = rear_left_midi_pitch_bend - lastRearLeftMIDIPitchBend; + if (Abs(pitch_difference) >= pitch_resolution || force_update) + { + lastRearLeftMIDIPitchBend = rear_left_midi_pitch_bend; + rear_left_channel->SendPitchBend(rear_left_midi_pitch_bend); + } + + pitch_difference = rear_right_midi_pitch_bend - lastRearRightMIDIPitchBend; + if (Abs(pitch_difference) >= pitch_resolution || force_update) + { + lastRearRightMIDIPitchBend = rear_right_midi_pitch_bend; + rear_right_channel->SendPitchBend(rear_right_midi_pitch_bend); + } + + // + //-------------------------------------------------------------------------- + // Send MIDI volume + //-------------------------------------------------------------------------- + // + Logical front_left_turned_on = False; + Logical front_right_turned_on = False; + Logical rear_left_turned_on = False; + Logical rear_right_turned_on = False; + + if (front_left_midi_volume != lastFrontLeftMIDIVolume) + { + if (lastFrontLeftMIDIVolume == 0) + front_left_turned_on = True; + + lastFrontLeftMIDIVolume = front_left_midi_volume; + Check(front_left_channel); + front_left_channel->SendController( + MIDI_VOLUME_CONTROL, + front_left_midi_volume + ); + } + + if (front_right_midi_volume != lastFrontRightMIDIVolume) + { + if (lastFrontRightMIDIVolume == 0) + front_right_turned_on = True; + + lastFrontRightMIDIVolume = front_right_midi_volume; + Check(front_right_channel); + front_right_channel->SendController( + MIDI_VOLUME_CONTROL, + front_right_midi_volume + ); + } + + if (rear_left_midi_volume != lastRearLeftMIDIVolume) + { + if (lastRearLeftMIDIVolume == 0) + rear_left_turned_on = True; + + lastRearLeftMIDIVolume = rear_left_midi_volume; + Check(rear_left_channel); + rear_left_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_left_midi_volume + ); + } + + if (rear_right_midi_volume != lastRearRightMIDIVolume) + { + if (lastRearRightMIDIVolume == 0) + rear_right_turned_on = True; + + lastRearRightMIDIVolume = rear_right_midi_volume; + Check(rear_right_channel); + rear_right_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_right_midi_volume + ); + } + + // + //-------------------------------------------------------------------------- + // Send NRPN filter cutoff + //-------------------------------------------------------------------------- + // + const MIDIValue filter_resolution = 4; + MIDINRPNValue filter_difference; + Logical filter_changed; + + filter_difference = midi_filter_cutoff - lastMIDIFilterCutoff; + filter_changed = (Abs(filter_difference) >= filter_resolution); + + if ( + front_left_turned_on || + (filter_changed && front_left_midi_volume > 0) + ) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + Check(front_left_channel); + front_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + } + if ( + front_right_turned_on || + (filter_changed && front_right_midi_volume > 0) + ) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + Check(front_right_channel); + front_right_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + } + if ( + rear_left_turned_on || + (filter_changed && rear_left_midi_volume > 0) + ) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + Check(rear_left_channel); + rear_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + } + if ( + rear_right_turned_on || + (filter_changed && rear_right_midi_volume > 0) + ) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + Check(rear_right_channel); + rear_right_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + } +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + Dynamic3DPatchSource::CalculateSourceVolumeScale() +{ + Check(this); + + // + // Call inherited method to calculate volume scale + // + Scalar + volume_scale = L4AudioSource::CalculateSourceVolumeScale(); + + // + // Update the spatial model that will result in the value + // for distance related volume attenuation + // + Check(application); + Check(application->GetAudioRenderer()); + UpdateSpatialModel(application->GetAudioRenderer()->GetAudioHead()); + + // + // Apply distance attenuation to the volume scale + // + Check(GetAudioLocation()); + volume_scale *= GetAudioLocation()->GetDistanceVolumeScale(); + return volume_scale; +} + +//############################################################################# +//####################### Static3DPatchSource ########################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +Static3DPatchSource::Static3DPatchSource( + PlugStream *stream, + Entity *entity +): + L4AudioSource(stream, entity), + position(0.0f, 0.0f, 0.0f) +{ + MemoryStream_Read(stream, &useInternalSpatialization); +} + +// +//############################################################################# +//############################################################################# +// +Static3DPatchSource::~Static3DPatchSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + L4AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID); + + if (name_list->FindData("use_internal") != NULL) + { + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_internal); + } + else + { + Logical use_internal = True; + MemoryStream_Write(stream, &use_internal); + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + Static3DPatchSource::TestInstance() const +{ + L4AudioSource::TestInstance(); + if (useInternalSpatialization) + { + Check(&internalSpatialization); + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::SetPosition(const Vector3D &vector3D) +{ + position = vector3D; +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::StartMessageImplementation() +{ + Check(this); + + L4AudioSource::StartMessageImplementation(); + + // + //-------------------------------------------------------------------------- + // Get audio renderer + //-------------------------------------------------------------------------- + // + L4AudioRenderer *audio_renderer; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + + // + //-------------------------------------------------------------------------- + // Update spatial parameters + //-------------------------------------------------------------------------- + // + if (useInternalSpatialization) + { + // + //----------------------------------------------------------------------- + // Calculate azimuth of position + //----------------------------------------------------------------------- + // + Radian azimuth_of_source; + + if (Small_Enough(position.x) && Small_Enough(position.z)) + { + azimuth_of_source = 0.0f; + } + else + { + Verify(!(Small_Enough(position.x) && Small_Enough(position.z))); + azimuth_of_source = Arctan(position.x, position.z); + } + Verify(azimuth_of_source <= PI && azimuth_of_source >= -PI); + + internalSpatialization.CalculateSpatialization(azimuth_of_source); + } + else + { + UpdateSpatialModel(audio_renderer->GetAudioHead()); + Cast_Object(L4AudioLocation*, GetAudioLocation())->GetSpatialization( + &internalSpatialization + ); + } + + // + //-------------------------------------------------------------------------- + // Init channel set to required channels + //-------------------------------------------------------------------------- + // + channelSet.EnableFrontLeft(False); + channelSet.EnableFrontRight(False); + channelSet.EnableRearLeft(False); + channelSet.EnableRearRight(False); + + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + channelSet.EnableFrontLeft(True); + break; + + case L4AudioSpatialization::Quadrant2: + channelSet.EnableFrontLeft(True); + channelSet.EnableRearLeft(True); + break; + + case L4AudioSpatialization::Quadrant3: + channelSet.EnableRearLeft(True); + break; + + case L4AudioSpatialization::Quadrant4: + channelSet.EnableFrontRight(True); + channelSet.EnableRearRight(True); + break; + } + + // + //-------------------------------------------------------------------------- + // Request start from renderer + //-------------------------------------------------------------------------- + // + audio_renderer->StartRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::StartImplementation() +{ + Check(this); + + L4AudioSource::StartImplementation(); + + // + //-------------------------------------------------------------------------- + // Get audio head constants + //-------------------------------------------------------------------------- + // + L4AudioRenderer *audio_renderer; + AudioHead *audio_head; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + // + //-------------------------------------------------------------------------- + // Setup the channel + //-------------------------------------------------------------------------- + // + ExecuteWatchers(); + + // + // Turn the volume down while setting up the channels + // + int i; + AudioChannel *channel; + + for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendController(MIDI_VOLUME_CONTROL, MIDI_MIN_CONTROL_VALUE); + } + } + + // + // Set the channels to the bank and program + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->SetDistance(GetDistanceToSource()); + for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + patch_resource->SetupPatch(channel); + } + } + + // + // Set the channels to default control values + // + MIDIValue midi_reverb_level = + audio_head->GetGlobalReverbScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendController(MIDI_REVERB_CONTROL, midi_reverb_level); + channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE); + } + } + + // + // Set the channels to correct pan + // + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + { + const Radian azimuth_max = + 45.0*RAD_PER_DEG; // HACK - should come from head + const Scalar slope = + -(Scalar)MIDI_MAX_CONTROL_VALUE / (2.0f * azimuth_max); + const Scalar intercept = + (MIDI_MAX_CONTROL_VALUE * 0.5f); + MIDIValue + midi_pan; + + midi_pan = slope * GetAzimuthOfSource() + intercept; + Check(channelSet.GetFrontLeft()); + channelSet.GetFrontLeft()->SendController( + MIDI_PAN_CONTROL, + midi_pan + ); + } + break; + + case L4AudioSpatialization::Quadrant2: + { + Check(channelSet.GetFrontLeft()); + Check(channelSet.GetRearLeft()); + channelSet.GetFrontLeft()->SendController( + MIDI_PAN_CONTROL, + MIDI_MIN_CONTROL_VALUE + ); + channelSet.GetRearLeft()->SendController( + MIDI_PAN_CONTROL, + MIDI_MIN_CONTROL_VALUE + ); + } + break; + + case L4AudioSpatialization::Quadrant3: + { + const Radian azimuth_max = + 45.0*RAD_PER_DEG; // HACK - should come from head + const Scalar slope = + (Scalar)MIDI_MAX_CONTROL_VALUE / (2.0f * azimuth_max); + const Scalar intercept = + (MIDI_MAX_CONTROL_VALUE * 0.5f); + MIDIValue + midi_pan; + + midi_pan = slope * GetAzimuthOfSource() + intercept; + Check(channelSet.GetRearLeft()); + channelSet.GetRearLeft()->SendController( + MIDI_PAN_CONTROL, + midi_pan + ); + } + break; + + case L4AudioSpatialization::Quadrant4: + { + Check(channelSet.GetFrontRight()); + Check(channelSet.GetRearRight()); + channelSet.GetFrontRight()->SendController( + MIDI_PAN_CONTROL, + MIDI_MAX_CONTROL_VALUE + ); + channelSet.GetRearRight()->SendController( + MIDI_PAN_CONTROL, + MIDI_MAX_CONTROL_VALUE + ); + } + break; + } + + // + // Set midi history to default control values + // + lastFrontLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastFrontRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastMIDIPitchBend = 0; // Set by force update + lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch + + // + //-------------------------------------------------------------------------- + // Calculate attack time, velocity, and execute model + //-------------------------------------------------------------------------- + // + MIDIValue midi_velocity = + CalculateSourceAttackVolumeScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (UseSourceAttackTime()) + { + MIDINRPNValue midi_attack_time = + CalculateSourceAttackTime() * + (Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f; + + for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time); + } + } + } + + ExecuteModel(True); + + // + //-------------------------------------------------------------------------- + // Start note + //-------------------------------------------------------------------------- + // + for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity); + } + } +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::StopImplementation() +{ + Check(this); + + // + //------------------------------------------------------------ + // Stop note + //------------------------------------------------------------ + // + AudioChannel *channel; + + for (int i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE); + } + } +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::ExecuteModel(Logical force_update) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get audio resource + //-------------------------------------------------------------------------- + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + + // + //-------------------------------------------------------------------------- + // Render spatial model + //-------------------------------------------------------------------------- + // + AudioChannel *front_left_channel = channelSet.GetFrontLeft(); + AudioChannel *front_right_channel = channelSet.GetFrontRight(); + AudioChannel *rear_left_channel = channelSet.GetRearLeft(); + AudioChannel *rear_right_channel = channelSet.GetRearRight(); + + // + // Apply volume scale offset + // + Scalar volume_scale = CalculateSourceVolumeScale(); + + // + // Apply pitch offset and calculate MIDI pitch bend + // + Scalar pitch_offset; + MIDIPitchBend midi_pitch_bend; + + pitch_offset = CalculateSourcePitchOffset(); + midi_pitch_bend = pitch_offset * MIDI_PITCH_PER_CENTS + 0.5f; + Clamp(midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX); + + // + // Apply high frequency scale and calculate NRPN filter cutoff + // + Scalar filter_scale; + MIDINRPNValue max_midi_filter_cutoff; + MIDINRPNValue midi_filter_cutoff; + + filter_scale = CalculateSourceBrightnessScale(); + max_midi_filter_cutoff = patch_resource->GetMaxMIDIFilterCutoff(); + midi_filter_cutoff = filter_scale * (Scalar)max_midi_filter_cutoff + 0.5f; + + // + //-------------------------------------------------------------------------- + // Send pitch bend + //-------------------------------------------------------------------------- + // + const MIDIPitchBend pitch_resolution = 2; + MIDIPitchBend pitch_difference = midi_pitch_bend - lastMIDIPitchBend; + + if (Abs(pitch_difference) >= pitch_resolution || force_update) + { + lastMIDIPitchBend = midi_pitch_bend; + + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + Check(front_left_channel); + front_left_channel->SendPitchBend(midi_pitch_bend); + break; + + case L4AudioSpatialization::Quadrant2: + Check(front_left_channel); + front_left_channel->SendPitchBend(midi_pitch_bend); + Check(rear_left_channel); + rear_left_channel->SendPitchBend(midi_pitch_bend); + break; + + case L4AudioSpatialization::Quadrant3: + Check(rear_left_channel); + rear_left_channel->SendPitchBend(midi_pitch_bend); + break; + + case L4AudioSpatialization::Quadrant4: + Check(front_right_channel); + front_right_channel->SendPitchBend(midi_pitch_bend); + Check(rear_right_channel); + rear_right_channel->SendPitchBend(midi_pitch_bend); + break; + } + } + + // + //-------------------------------------------------------------------------- + // Send NRPN filter cutoff + //-------------------------------------------------------------------------- + // + if (UseSourceBrightnessScale()) + { + const MIDIValue filter_resolution = 2; + MIDINRPNValue filter_difference; + + filter_difference = midi_filter_cutoff - lastMIDIFilterCutoff; + + if (Abs(filter_difference) >= filter_resolution) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + Check(front_left_channel); + front_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + + case L4AudioSpatialization::Quadrant2: + Check(front_left_channel); + front_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + Check(rear_left_channel); + rear_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + + case L4AudioSpatialization::Quadrant3: + Check(rear_left_channel); + rear_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + + case L4AudioSpatialization::Quadrant4: + Check(front_right_channel); + front_right_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + Check(rear_right_channel); + rear_right_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + } + } + } + + // + //-------------------------------------------------------------------------- + // Send MIDI volume + //-------------------------------------------------------------------------- + // + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + { + MIDIValue front_left_midi_volume = + volume_scale * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (front_left_midi_volume != lastFrontLeftMIDIVolume) + { + lastFrontLeftMIDIVolume = front_left_midi_volume; + Check(front_left_channel); + front_left_channel->SendController( + MIDI_VOLUME_CONTROL, + front_left_midi_volume + ); + } + } + break; + + case L4AudioSpatialization::Quadrant2: + { + MIDIValue front_left_midi_volume = + volume_scale * GetFrontLeftScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + MIDIValue rear_left_midi_volume = + volume_scale * GetRearLeftScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (front_left_midi_volume != lastFrontLeftMIDIVolume) + { + lastFrontLeftMIDIVolume = front_left_midi_volume; + Check(front_left_channel); + front_left_channel->SendController( + MIDI_VOLUME_CONTROL, + front_left_midi_volume + ); + } + if (rear_left_midi_volume != lastRearLeftMIDIVolume) + { + lastRearLeftMIDIVolume = rear_left_midi_volume; + Check(rear_left_channel); + rear_left_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_left_midi_volume + ); + } + } + break; + + case L4AudioSpatialization::Quadrant3: + { + MIDIValue rear_left_midi_volume = + volume_scale * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (rear_left_midi_volume != lastRearLeftMIDIVolume) + { + lastRearLeftMIDIVolume = rear_left_midi_volume; + Check(rear_left_channel); + rear_left_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_left_midi_volume + ); + } + } + break; + + case L4AudioSpatialization::Quadrant4: + { + MIDIValue front_right_midi_volume = + volume_scale * GetFrontRightScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + MIDIValue rear_right_midi_volume = + volume_scale * GetRearRightScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (front_right_midi_volume != lastFrontRightMIDIVolume) + { + lastFrontRightMIDIVolume = front_right_midi_volume; + Check(front_right_channel); + front_right_channel->SendController( + MIDI_VOLUME_CONTROL, + front_right_midi_volume + ); + } + if (rear_right_midi_volume != lastRearRightMIDIVolume) + { + lastRearRightMIDIVolume = rear_right_midi_volume; + Check(rear_right_channel); + rear_right_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_right_midi_volume + ); + } + } + break; + } +} + + diff --git a/CODE/RP/MUNGA_L4/L4AUDIO.HPP b/CODE/RP/MUNGA_L4/L4AUDIO.HPP new file mode 100644 index 0000000..cb19ab7 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDIO.HPP @@ -0,0 +1,819 @@ +//===========================================================================// +// File: l4audio.hh // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4AUDIO_HPP) +# define L4AUDIO_HPP + +# if !defined(L4AUDHDW_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + +# if !defined(AUDLOC_HPP) +# include +# endif + +# if !defined(AUDSRC_HPP) +# include +# endif + + //########################################################################## + //####################### L4AudioSpatialization ###################### + //########################################################################## + + class L4AudioSpatialization SIGNATURED + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + enum Quadrant + { + Quadrant1, + Quadrant2, + Quadrant3, + Quadrant4 + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Contstruction, Destruction, & Testing + // + public: + L4AudioSpatialization(); + ~L4AudioSpatialization(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Spatialization calculations & results + // + public: + void + CalculateSpatialization(Radian azimuth_of_source); + + Radian + azimuthOfSource; + + Scalar + frontLeftScale, + frontRightScale, + rearLeftScale, + rearRightScale; + + Scalar + frontLeftDelay, + frontRightDelay, + rearLeftDelay, + rearRightDelay; + + Quadrant + quadrant; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~ L4AudioSpatialization inlines ~~~~~~~~~~~~~~~~~~~~ + + inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + L4AudioSpatialization::Quadrant *ptr + ) + { + return stream->ReadBytes(ptr, sizeof(*ptr)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const L4AudioSpatialization::Quadrant *ptr + ) + { + return stream->WriteBytes(ptr, sizeof(*ptr)); + } + + //########################################################################## + //######################### L4AudioLocation ########################## + //########################################################################## + + class L4AudioLocation: + public AudioLocation + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + L4AudioLocation( + PlugStream *stream, + Entity *entity + ); + void + L4AudioLocationX(); + ~L4AudioLocation(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Spatialization Accessors + // + public: + void + GetSpatialization(L4AudioSpatialization *the_spatialization) + {*the_spatialization = spatialization;} + + L4AudioSpatialization::Quadrant + GetQuadrant() + {return spatialization.quadrant;} + + Scalar + GetFrontLeftScale() + {return spatialization.frontLeftScale;} + Scalar + GetFrontRightScale() + {return spatialization.frontRightScale;} + Scalar + GetRearLeftScale() + {return spatialization.rearLeftScale;} + Scalar + GetRearRightScale() + {return spatialization.rearRightScale;} + + Scalar + GetFrontLeftITDPitchOffset() + {return frontLeftITDPitchOffset;} + Scalar + GetFrontRightITDPitchOffset() + {return frontRightITDPitchOffset;} + Scalar + GetRearLeftITDPitchOffset() + {return rearLeftITDPitchOffset;} + Scalar + GetRearRightITDPitchOffset() + {return rearRightITDPitchOffset;} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Spatialization Implementation + // + public: + void + UpdateSpatialModelImplementation(AudioHead *audio_head); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + L4AudioSpatialization + spatialization; + + Time + lastITDFrameTime; + + Scalar + currentFrontLeftDelay, + currentFrontRightDelay, + currentRearLeftDelay, + currentRearRightDelay; + + AudioPitchCents + frontLeftITDPitchOffset, + frontRightITDPitchOffset, + rearLeftITDPitchOffset, + rearRightITDPitchOffset; + }; + + //########################################################################## + //######################### AudioChannelSet ########################## + //########################################################################## + + #define AUDIO_CHANNEL_SET_LENGTH (4) + + typedef int AudioChannelSetIndex; + const AudioChannelSetIndex AudioChannelSetSize = AUDIO_CHANNEL_SET_LENGTH; + + class AudioChannelSet SIGNATURED + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, & Testing + // + public: + AudioChannelSet(); + ~AudioChannelSet() {} + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + RegisteredClass::ClassID class_ID, + ObjectID object_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Channel accesors + // + public: + void + SetFrontLeft(AudioChannel *audio_channel); + void + SetFrontRight(AudioChannel *audio_channel); + void + SetRearLeft(AudioChannel *audio_channel); + void + SetRearRight(AudioChannel *audio_channel); + + AudioChannel* + GetFrontLeft(); + AudioChannel* + GetFrontRight(); + AudioChannel* + GetRearLeft(); + AudioChannel* + GetRearRight(); + + void + SetNth( + AudioChannelSetIndex index, + AudioChannel *audio_channel + ); + AudioChannel* + GetNth(AudioChannelSetIndex index); + + void + ReleaseAll(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Enable accesors + // + public: + void + EnableFrontLeft(Logical flag); + void + EnableFrontRight(Logical flag); + void + EnableRearLeft(Logical flag); + void + EnableRearRight(Logical flag); + + Logical + IsFrontLeftEnabled(); + Logical + IsFrontRightEnabled(); + Logical + IsRearLeftEnabled(); + Logical + IsRearRightEnabled(); + + void + EnableNth( + AudioChannelSetIndex index, + Logical flag + ); + void + EnableAll(); + Logical + IsNthEnabled(AudioChannelSetIndex index); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Null channel set + // + public: + static AudioChannelSet + Null; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + AudioChannel + *channels[AUDIO_CHANNEL_SET_LENGTH]; + Logical + enables[AUDIO_CHANNEL_SET_LENGTH]; + }; + + //########################################################################## + //########################## L4AudioSource ########################### + //########################################################################## + + class L4AudioSource: + public AudioSource + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Destruction, Testing + // + public: + ~L4AudioSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // AudioChannelSet methods + // + public: + void + SetAudioChannelSet(const AudioChannelSet &audio_channel_set); + const AudioChannelSet* + GetAudioChannelSet(); + + void + ReleaseChannels(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected Constuction + // + protected: + L4AudioSource( + PlugStream *stream, + Entity *entity + ); + void + L4AudioSourceX(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected Implementations + // + protected: + void + StopMessageImplementation(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected Data + // + protected: + AudioChannelSet + channelSet; + }; + + //########################################################################## + //######################## DirectPatchSource ######################### + //########################################################################## + + enum DirectPatchPosition + { + FrontDirectPatchPosition = 0, + RearDirectPatchPosition = 1, + FrontLeftDirectPatchPosition = 2, + FrontRightDirectPatchPosition = 3, + RearLeftDirectPatchPosition = 4, + RearRightDirectPatchPosition = 5 + }; + + class DirectPatchSource: + public L4AudioSource + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + DirectPatchSource( + PlugStream *stream, + Entity *entity + ); + ~DirectPatchSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State implementations + // + public: + void + StartImplementation(); + void + StopImplementation(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected Implementations + // + protected: + void + StartMessageImplementation(); + + void + ExecuteModel(Logical force_update); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + DirectPatchPosition + audioPosition; + AudioChannel + *channel; + + MIDIValue + lastMIDIVolume; + MIDIPitchBend + lastMIDIPitchBend; + MIDINRPNValue + lastMIDIFilterCutoff; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ DirectPatchSource inlines ~~~~~~~~~~~~~~~~~~~~ + + inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + DirectPatchPosition *ptr + ) + { + return stream->ReadBytes(ptr, sizeof(*ptr)); + } + + inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const DirectPatchPosition *ptr + ) + { + return stream->WriteBytes(ptr, sizeof(*ptr)); + } + + //########################################################################## + //###################### Dynamic3DPatchSource ######################## + //########################################################################## + + class Dynamic3DPatchSource: + public L4AudioSource + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + Dynamic3DPatchSource( + PlugStream *stream, + Entity *entity + ); + ~Dynamic3DPatchSource(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Mix levels + // + public: + AudioControlValue + CalculateSourceVolumeScale(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State implementations + // + public: + void + StartImplementation(); + void + StopImplementation(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected implementations + // + protected: + void + StartMessageImplementation(); + + void + ExecuteModel(Logical force_update); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + MIDIValue + lastFrontLeftMIDIVolume, + lastFrontRightMIDIVolume, + lastRearLeftMIDIVolume, + lastRearRightMIDIVolume; + + MIDIPitchBend + lastFrontLeftMIDIPitchBend, + lastFrontRightMIDIPitchBend, + lastRearLeftMIDIPitchBend, + lastRearRightMIDIPitchBend; + + MIDINRPNValue + lastMIDIFilterCutoff; + }; + + //########################################################################## + //####################### Static3DPatchSource ######################## + //########################################################################## + + class Static3DPatchSource: + public L4AudioSource + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + Static3DPatchSource( + PlugStream *stream, + Entity *entity + ); + ~Static3DPatchSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // SetPosition + // + public: + void + SetPosition(const Vector3D &vector3D); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State implementations + // + public: + void + StartImplementation(); + void + StopImplementation(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Protected implementations + // + protected: + void + StartMessageImplementation(); + + void + ExecuteModel(Logical force_update); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Methods + // + private: + L4AudioSpatialization::Quadrant + GetQuadrant(); + Radian + GetAzimuthOfSource(); + + Scalar + GetFrontLeftScale(); + Scalar + GetFrontRightScale(); + Scalar + GetRearLeftScale(); + Scalar + GetRearRightScale(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + Vector3D + position; + + Logical + useInternalSpatialization; + L4AudioSpatialization + internalSpatialization; + + MIDIValue + lastFrontLeftMIDIVolume, + lastFrontRightMIDIVolume, + lastRearLeftMIDIVolume, + lastRearRightMIDIVolume; + + MIDIPitchBend + lastMIDIPitchBend; + + MIDINRPNValue + lastMIDIFilterCutoff; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ Static3DPatchSource inlines ~~~~~~~~~~~~~~~~~~~~~ + + inline L4AudioSpatialization::Quadrant + Static3DPatchSource::GetQuadrant() + { + return internalSpatialization.quadrant; + } + + inline Radian + Static3DPatchSource::GetAzimuthOfSource() + { + return internalSpatialization.azimuthOfSource; + } + + inline Scalar + Static3DPatchSource::GetFrontLeftScale() + { + return internalSpatialization.frontLeftScale; + } + + inline Scalar + Static3DPatchSource::GetFrontRightScale() + { + return internalSpatialization.frontRightScale; + } + + inline Scalar + Static3DPatchSource::GetRearLeftScale() + { + return internalSpatialization.rearLeftScale; + } + + inline Scalar + Static3DPatchSource::GetRearRightScale() + { + return internalSpatialization.rearRightScale; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannelSet inlines ~~~~~~~~~~~~~~~~~~~~~~ + + inline void + AudioChannelSet::SetFrontLeft(AudioChannel *audio_channel) + { + Check(this); + channels[0] = audio_channel; + } + + inline void + AudioChannelSet::SetFrontRight(AudioChannel *audio_channel) + { + Check(this); + channels[1] = audio_channel; + } + + inline void + AudioChannelSet::SetRearLeft(AudioChannel *audio_channel) + { + Check(this); + channels[2] = audio_channel; + } + + inline void + AudioChannelSet::SetRearRight(AudioChannel *audio_channel) + { + Check(this); + channels[3] = audio_channel; + } + + inline AudioChannel* + AudioChannelSet::GetFrontLeft() + { + Check(this); + return channels[0]; + } + + inline AudioChannel* + AudioChannelSet::GetFrontRight() + { + Check(this); + return channels[1]; + } + + inline AudioChannel* + AudioChannelSet::GetRearLeft() + { + Check(this); + return channels[2]; + } + + inline AudioChannel* + AudioChannelSet::GetRearRight() + { + Check(this); + return channels[3]; + } + + inline void + AudioChannelSet::SetNth( + AudioChannelSetIndex index, + AudioChannel *audio_channel + ) + { + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + channels[index] = audio_channel; + } + + inline AudioChannel* + AudioChannelSet::GetNth(AudioChannelSetIndex index) + { + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + return channels[index]; + } + + inline void + AudioChannelSet::EnableFrontLeft(Logical flag) + { + Check(this); + enables[0] = flag; + } + + inline void + AudioChannelSet::EnableFrontRight(Logical flag) + { + Check(this); + enables[1] = flag; + } + + inline void + AudioChannelSet::EnableRearLeft(Logical flag) + { + Check(this); + enables[2] = flag; + } + + inline void + AudioChannelSet::EnableRearRight(Logical flag) + { + Check(this); + enables[3] = flag; + } + + inline Logical + AudioChannelSet::IsFrontLeftEnabled() + { + Check(this); + return enables[0]; + } + + inline Logical + AudioChannelSet::IsFrontRightEnabled() + { + Check(this); + return enables[1]; + } + + inline Logical + AudioChannelSet::IsRearLeftEnabled() + { + Check(this); + return enables[2]; + } + + inline Logical + AudioChannelSet::IsRearRightEnabled() + { + Check(this); + return enables[3]; + } + + inline void + AudioChannelSet::EnableNth( + AudioChannelSetIndex index, + Logical flag + ) + { + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + enables[index] = flag; + } + + inline Logical + AudioChannelSet::IsNthEnabled(AudioChannelSetIndex index) + { + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + return enables[index]; + } + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4AUDLVL.CPP b/CODE/RP/MUNGA_L4/L4AUDLVL.CPP new file mode 100644 index 0000000..20b83a5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDLVL.CPP @@ -0,0 +1,220 @@ +//===========================================================================// +// File: l4audlvl.cpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDLVL_HPP) +# include +#endif + +#if !defined(OBJSTRM_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if DEBUG_LEVEL>0 + TableOf + PatchLevelOfDetail::patchTableSocket(NULL, True); +#endif + +// +//############################################################################# +//############################################################################# +// +PatchLevelOfDetail::PatchLevelOfDetail(PlugStream *stream): + AudioLevelOfDetail(stream) +{ + MemoryStream_Read(stream, &bankID); + MemoryStream_Read(stream, &patchID); + MemoryStream_Read(stream, &maxMIDIFilterCutoff); + + Warn(GetVoiceCount() > 4); // HACK - AWE appears to only play 1st 4 voices + + #ifdef LAB_ONLY + setupCount = 0; + #endif + + // + // Keep table of created patchs to verify that duplicates + // are not created, could move this to tool time + // + #if DEBUG_LEVEL>0 + unsigned int index_value = (bankID * 1000) + patchID; + if (patchTableSocket.Find(index_value) != NULL) + { + Dump((int)bankID); + Dump((int)patchID); + } + Verify(patchTableSocket.Find(index_value) == NULL); + patchTableSocket.AddValue(this, index_value); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + PatchLevelOfDetail::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioLevelOfDetail::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, SBKBankID, bank_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, SBKPatchID, patch_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, MIDINRPNValue, max_filter_cutoff); +} + +// +//############################################################################# +//############################################################################# +// +PatchLevelOfDetail::~PatchLevelOfDetail() +{ + #ifdef LAB_ONLY + cout << "PatchLevelOfDetail::~PatchLevelOfDetail\t"; + cout << (int)bankID << ":" << (int)patchID << "\t"; + cout << "setupCount=\t" << setupCount << "\n"; + #endif +} + +// +//############################################################################# +//############################################################################# +// +Logical + PatchLevelOfDetail::TestInstance() const +{ + AudioLevelOfDetail::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + PatchLevelOfDetail::SetupPatch(AudioChannel *channel) +{ + Check(this); + Check(channel); + + #ifdef LAB_ONLY + setupCount++; + #endif + + // + // Set the channel to the bank and program, reset patch controls + // + channel->SelectBank(bankID); + channel->SendProgramChange(patchID); + channel->SendController(MIDI_CONTROL_RESET, MIDI_MAX_CONTROL_VALUE); + + #if 0 + Tell((int)bankID << ":" << (int)patchID << "\n"); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +PatchResource::PatchResource(PlugStream *stream): + AudioResource(stream) +{ +} + +// +//############################################################################# +//############################################################################# +// +void + PatchResource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioResource::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +PatchResource::~PatchResource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + PatchResource::TestInstance() const +{ + AudioResource::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + PatchResource::SetupPatch(AudioChannel *channel) +{ + Check(this); + Check(channel); + + PatchLevelOfDetail *patch_level_of_detail = + Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail()); + + Check(patch_level_of_detail); + patch_level_of_detail->SetupPatch(channel); +} + +// +//############################################################################# +//############################################################################# +// +MIDINRPNValue + PatchResource::GetMaxMIDIFilterCutoff() +{ + Check(this); + + PatchLevelOfDetail *patch_level_of_detail = + Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail()); + + Check(patch_level_of_detail); + return patch_level_of_detail->GetMaxMIDIFilterCutoff(); +} + + diff --git a/CODE/RP/MUNGA_L4/L4AUDLVL.HPP b/CODE/RP/MUNGA_L4/L4AUDLVL.HPP new file mode 100644 index 0000000..5b2c26c --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDLVL.HPP @@ -0,0 +1,142 @@ +//===========================================================================// +// File: l4audlvl.hpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4AUDLVL_HPP) +# define L4AUDLVL_HPP + +# if !defined(AUDLVL_HPP) +# include +# endif + +# if !defined(L4AUDHDW_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + typedef MIDIValue SBKPatchID; + typedef MIDIValue SBKBankID; + + class PatchLevelOfDetail: + public AudioLevelOfDetail + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + PatchLevelOfDetail(PlugStream *stream); + ~PatchLevelOfDetail(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + void + SetupPatch(AudioChannel *channel); + + MIDINRPNValue + GetMaxMIDIFilterCutoff() + {return maxMIDIFilterCutoff;} + + private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + SBKBankID + bankID; + SBKPatchID + patchID; + MIDINRPNValue + maxMIDIFilterCutoff; + + #ifdef LAB_ONLY + int + setupCount; + #endif + + // + // Keep table of created patchs to verify that duplicates + // are not created + // + #if DEBUG_LEVEL>0 + static TableOf + patchTableSocket; + #endif + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class PatchResource: + public AudioResource + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + PatchResource(PlugStream *stream); + ~PatchResource(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + void + SetupPatch(AudioChannel *channel); + + MIDINRPNValue + GetMaxMIDIFilterCutoff(); + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4AUDRES.CPP b/CODE/RP/MUNGA_L4/L4AUDRES.CPP new file mode 100644 index 0000000..09c2716 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDRES.CPP @@ -0,0 +1,1019 @@ +//===========================================================================// +// File: l4audres.cpp // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/10/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDRES_HPP) +# include +#endif + +#if !defined(L4AUDHDW_HPP) +# include +#endif + +#if !defined(L4AUDIO_HPP) +# include +#endif + +#if !defined(L4AUDLVL_HPP) +# include +#endif + +#if !defined(L4AUDWTR_HPP) +# include +#endif + +#if !defined(AUDCMP_HPP) +# include +#endif + +#if !defined(AUDSEQ_HPP) +# include +#endif + +#if !defined(AUDREND_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +//############################################################################# +//####################### AudioObjectStream ############################# +//############################################################################# + +// +//############################################################################# +// AudioObjectStream +//############################################################################# +// +AudioObjectStream::AudioObjectStream( + ResourceDescription *resource_description, + Entity *the_entity +): + PlugStream(resource_description) +{ + entity = the_entity; +} + +// +//############################################################################# +// AudioObjectStream +//############################################################################# +// +AudioObjectStream::AudioObjectStream() +{ + entity = NULL; +} + +// +//############################################################################# +// ~AudioObjectStream +//############################################################################# +// +AudioObjectStream::~AudioObjectStream() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioObjectStream::TestInstance() const +{ + PlugStream::TestInstance(); + if (entity != NULL) + { + Check(entity); + } + return True; +} + +// +//############################################################################# +// MakeObjectImplementation +//############################################################################# +// +RegisteredClass* + AudioObjectStream::MakeObjectImplementation(Enumeration class_ID) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + + // + //----------------------------------------------------------------------- + // HACK - Constructors should be referenced through registration, for + // now just use a switch statement + //----------------------------------------------------------------------- + // + RegisteredClass *object; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::PatchLevelOfDetailClassID: + object = new PatchLevelOfDetail(this); + break; + + case RegisteredClass::PatchResourceClassID: + object = new PatchResource(this); + break; + + case RegisteredClass::AudioResourceIndexClassID: + object = new AudioResourceIndex(this); + break; + + // + // Location and sources ... + // + case RegisteredClass::L4AudioLocationClassID: + object = new L4AudioLocation(this, entity); + break; + + case RegisteredClass::DirectPatchSourceClassID: + object = new DirectPatchSource(this, entity); + break; + + case RegisteredClass::Dynamic3DPatchSourceClassID: + object = new Dynamic3DPatchSource(this, entity); + break; + + case RegisteredClass::Static3DPatchSourceClassID: + object = new Static3DPatchSource(this, entity); + break; + + // + // Audio components ... + // + case RegisteredClass::AudioControlMixerClassID: + object = new AudioControlMixer(this, entity); + break; + + case RegisteredClass::AudioControlMultiplierClassID: + object = new AudioControlMultiplier(this, entity); + break; + + case RegisteredClass::AudioResourceSelectorClassID: + object = new AudioResourceSelector(this, entity); + break; + + case RegisteredClass::AudioControlSmootherClassID: + object = new AudioControlSmoother(this, entity); + break; + + case RegisteredClass::AudioSampleAndHoldClassID: + object = new AudioSampleAndHold(this, entity); + break; + + case RegisteredClass::AudioControlSendClassID: + object = new AudioControlSend(this, entity); + break; + + case RegisteredClass::AudioControlSequenceClassID: + object = new AudioControlSequence(this, entity); + break; + + case RegisteredClass::AudioControlSplitterClassID: + object = new AudioControlSplitter(this, entity); + break; + + case RegisteredClass::AudioLFOClassID: + object = new AudioLFO(this, entity); + break; + + // + // Audio watchers ... + // + case RegisteredClass::AudioMotionTriggerClassID: + object = new AudioMotionTrigger(this, entity); + break; + + case RegisteredClass::AudioMotionScaleClassID: + object = new AudioMotionScale(this, entity); + break; + + case RegisteredClass::AudioHingeScaleClassID: + object = new AudioHingeScale(this, entity); + break; + + case RegisteredClass::AudioScalarTriggerClassID: + object = new AudioScalarTrigger(this, entity); + break; + + case RegisteredClass::AudioScalarScaleClassID: + object = new AudioScalarScale(this, entity); + break; + + case RegisteredClass::AudioLogicalTriggerClassID: + object = new AudioLogicalTrigger(this, entity); + break; + + case RegisteredClass::AudioEnumerationTriggerClassID: + object = new AudioEnumerationTrigger(this, entity); + break; + + case RegisteredClass::AudioIntegerTriggerClassID: + object = new AudioIntegerTrigger(this, entity); + break; + + case RegisteredClass::AudioControlsButtonTriggerClassID: + object = new AudioControlsButtonTrigger(this, entity); + break; + + case RegisteredClass::AudioStateTriggerClassID: + object = new AudioStateTrigger(this, entity); + break; + + case RegisteredClass::AudioIdleWatcherClassID: + object = new AudioIdleWatcher(this, entity); + break; + + case RegisteredClass::AudioEnumerationDeltaTriggerClassID: + object = new AudioEnumerationDeltaTrigger(this, entity); + break; + + case RegisteredClass::AudioScalarDeltaTriggerClassID: + object = new AudioScalarDeltaTrigger(this, entity); + break; + + case RegisteredClass::L4AudioCollisionTriggerClassID: + object = new L4AudioCollisionTrigger(this, entity); + break; + + case RegisteredClass::AudioMessageWatcherClassID: + object = new AudioMessageWatcher(this, entity); + break; + + case RegisteredClass::AudioControlsButtonMessageWatcherClassID: + object = new AudioControlsButtonMessageWatcher(this, entity); + break; + + // + // Inherited behavior + // + default: + object = PlugStream::MakeObjectImplementation(class_ID); + break; + } + return object; +} + +// +//############################################################################# +// CreatedObjectImplementation +//############################################################################# +// +void + AudioObjectStream::CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ) +{ + Check(this); + Check(object); + Verify(object_ID != NullObjectID); + + // + // Decide which index to add object to + // + switch (object->GetClassID()) + { + case RegisteredClass::PatchLevelOfDetailClassID: + case RegisteredClass::PatchResourceClassID: + case RegisteredClass::AudioResourceIndexClassID: + AddGlobalPlug(Cast_Object(Plug*, object), object_ID); + break; + + default: + AddLocalPlug(Cast_Object(Plug*, object), object_ID); + break; + } +} + +// +//############################################################################# +// BuildFromPageImplementation +//############################################################################# +// +void + AudioObjectStream::BuildFromPageImplementation( + NameList *name_list, + Enumeration class_ID_enumeration, + ObjectID object_ID + ) +{ + Check(this); + Verify(class_ID_enumeration != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + + // + //----------------------------------------------------------------------- + // HACK - Page interpreters should be referenced through registration, + // for now just use a switch statement + //----------------------------------------------------------------------- + // + RegisteredClass::ClassID + class_ID = (RegisteredClass::ClassID)class_ID_enumeration; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::PatchLevelOfDetailClassID: + PatchLevelOfDetail::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::PatchResourceClassID: + PatchResource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioResourceIndexClassID: + AudioResourceIndex::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Location and sources ... + // + case RegisteredClass::L4AudioLocationClassID: + L4AudioLocation::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::DirectPatchSourceClassID: + DirectPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::Dynamic3DPatchSourceClassID: + Dynamic3DPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::Static3DPatchSourceClassID: + Static3DPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Audio components ... + // + case RegisteredClass::AudioControlMixerClassID: + AudioControlMixer::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlMultiplierClassID: + AudioControlMultiplier::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioResourceSelectorClassID: + AudioResourceSelector::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSmootherClassID: + AudioControlSmoother::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioSampleAndHoldClassID: + AudioSampleAndHold::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSendClassID: + AudioControlSend::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSequenceClassID: + AudioControlSequence::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSplitterClassID: + AudioControlSplitter::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioLFOClassID: + AudioLFO::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Audio watchers ... + // + case RegisteredClass::AudioMotionTriggerClassID: + AudioMotionTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioMotionScaleClassID: + AudioMotionScale::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioHingeScaleClassID: + AudioHingeScale::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioScalarTriggerClassID: + AudioScalarTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioScalarScaleClassID: + AudioScalarScale::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioLogicalTriggerClassID: + AudioLogicalTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioEnumerationTriggerClassID: + AudioEnumerationTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioIntegerTriggerClassID: + AudioIntegerTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlsButtonTriggerClassID: + AudioControlsButtonTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioStateTriggerClassID: + AudioStateTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioIdleWatcherClassID: + AudioIdleWatcher::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioEnumerationDeltaTriggerClassID: + AudioEnumerationDeltaTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioScalarDeltaTriggerClassID: + AudioScalarDeltaTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::L4AudioCollisionTriggerClassID: + L4AudioCollisionTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioMessageWatcherClassID: + AudioMessageWatcher::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlsButtonMessageWatcherClassID: + AudioControlsButtonMessageWatcher::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Inherited behavior + // + default: + PlugStream::BuildFromPageImplementation(name_list, class_ID, object_ID); + break; + } +} + +// +//############################################################################# +// BuiltFromPageImplementation +//############################################################################# +// +void + AudioObjectStream::BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name + ) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + Check(&object_name); + + // + // Decide which index to add object to + // + if (object_name.Length() == 0) + return; + + switch (class_ID) + { + case RegisteredClass::PatchLevelOfDetailClassID: + case RegisteredClass::PatchResourceClassID: + case RegisteredClass::AudioResourceIndexClassID: + AddGlobalObjectID(object_ID, object_name); + break; + + default: + AddLocalObjectID(object_ID, object_name); + break; + } +} + +//############################################################################# +//###################### L4AudioResourceManager ######################### +//############################################################################# + +// +//############################################################################# +// L4AudioResourceManager +//############################################################################# +// +L4AudioResourceManager::L4AudioResourceManager() +{ +} + +// +//############################################################################# +// ~L4AudioResourceManager +//############################################################################# +// +L4AudioResourceManager::~L4AudioResourceManager() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + L4AudioResourceManager::TestInstance() const +{ + Node::TestInstance(); + return True; +} + +// +//############################################################################# +// PreloadResources +//############################################################################# +// +void + L4AudioResourceManager::PreloadResources( + NotationFile *notation_file, + AudioHardware *audio_hardware + ) +{ + Check(this); + Check(notation_file); + Check(audio_hardware); + + // + //---------------------------------------------------------------------- + // Load the sound banks + //---------------------------------------------------------------------- + // + NameList *name_list; + NameList::Entry *entry; + + Verify(notation_file->EntryCount("AudioResources") >= 2); + + name_list = notation_file->MakeEntryList("AudioResources"); + Register_Object(name_list); + entry = name_list->GetFirstEntry(); + Check(entry); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("front_audio_resource")) + { + Check_Pointer(entry->GetChar()); + Check(audio_hardware->GetFrontCard()); + audio_hardware->GetFrontCard()->LoadSBK(entry->GetChar()); + } + else + { + Verify(entry->IsName("rear_audio_resource")); + Check_Pointer(entry->GetChar()); + Check(audio_hardware->GetRearCard()); + audio_hardware->GetRearCard()->LoadSBK(entry->GetChar()); + } + entry = entry->GetNextEntry(); + } + Unregister_Object(name_list); + delete name_list; + + // + //---------------------------------------------------------------------- + // Create static audio objects + //---------------------------------------------------------------------- + // + + // + // Get static audio stream resource + // + ResourceDescription *resource_description; + + Check(application); + Check(application->GetResourceFile()); + resource_description = + application->GetResourceFile()->FindResourceDescription( + "StaticAudioStream", + ResourceDescription::StaticAudioStreamResourceType + ); + Check(resource_description); + resource_description->Lock(); + + // + // Parse the audio object stream + // + AudioObjectStream audio_object_stream(resource_description, NULL); + + Check(&audio_object_stream); + audio_object_stream.CreateObjects(); + resource_description->Unlock(); +} + +// +//############################################################################# +// UnloadResources +//############################################################################# +// +void + L4AudioResourceManager::UnloadResources( + AudioHardware *audio_hardware + ) +{ + Check(this); + Check(audio_hardware); + + // + //---------------------------------------------------------------------- + // Release banks + //---------------------------------------------------------------------- + // + Check(audio_hardware->GetFrontCard()); + audio_hardware->GetFrontCard()->ReleaseAllBanks(); + Check(audio_hardware->GetRearCard()); + audio_hardware->GetRearCard()->ReleaseAllBanks(); +} + +// +//############################################################################# +// CreateStaticAudioStreamResource +//############################################################################# +// +ResourceDescription::ResourceID + L4AudioResourceManager::CreateStaticAudioStreamResource( + ResourceFile *resource_file + ) +{ + Check(resource_file); + + // + //---------------------------------------------------------------------- + // Open the notation file for the static stream resource + //---------------------------------------------------------------------- + // + Tell("Opening Audio Script audio\\static.scp\n"); + NotationFile notation_file("audio\\static.scp"); + Check(¬ation_file); + + // + //---------------------------------------------------------------------- + // Build the static audio object stream + //---------------------------------------------------------------------- + // + AudioObjectStream audio_object_stream; + + Check(&audio_object_stream); + audio_object_stream.BuildFromNotationFile(¬ation_file, resource_file); + Tell("Closed Audio Script\n"); + + // + //---------------------------------------------------------------------- + // Add the resource + //---------------------------------------------------------------------- + // + ResourceDescription *res_description; + + res_description = + resource_file->AddResourceMemoryStream( + "StaticAudioStream", + ResourceDescription::StaticAudioStreamResourceType, + 1, + ResourceDescription::Preload, + &audio_object_stream + ); + Check(res_description); + return res_description->resourceID; +} + +// +//############################################################################# +// CreateEntityAudioObjects +//############################################################################# +// +void + L4AudioResourceManager::CreateEntityAudioObjects( + Entity *entity, + AudioRepresentation audio_representation + ) +{ + Check(this); + Check(entity); + Verify( + audio_representation == InternalAudioRepresentation || + audio_representation == ExternalAudioRepresentation + ); + + // + //------------------------------------------------------------------------ + // Read the audio resource for this entity + //------------------------------------------------------------------------ + // + ResourceDescription *audio_resource_description; + + Check(application); + Check(application->GetResourceFile()); + audio_resource_description = + application->GetResourceFile()->SearchList( + entity->GetResourceID(), + ResourceDescription::AudioStreamListResourceType + ); + if (audio_resource_description == NULL) + return; + + // + //------------------------------------------------------------------------ + // Read the appropriate resource for an internal or external + // representation + //------------------------------------------------------------------------ + // + ResourceDescription *stream_resource_description; + + Check(application); + Check(application->GetResourceFile()); + Check(audio_resource_description); + stream_resource_description = + application->GetResourceFile()->SearchList( + audio_resource_description->resourceID, + (audio_representation == InternalAudioRepresentation) ? + ResourceDescription::InternalAudioStreamResourceType : + ResourceDescription::ExternalAudioStreamResourceType + ); + if (stream_resource_description == NULL) + return; + Check(stream_resource_description); + stream_resource_description->Lock(); + audio_resource_description->Lock(); + + // + //------------------------------------------------------------------------ + // Make the audio object stream + //------------------------------------------------------------------------ + // + AudioObjectStream + audio_object_stream( + stream_resource_description, + entity + ); + + Check(&audio_object_stream); + audio_object_stream.CreateObjects(); + stream_resource_description->Unlock(); + audio_resource_description->Unlock(); +} + +// +//############################################################################# +// DestroyEntityAudioObjects +//############################################################################# +// +void + L4AudioResourceManager::DestroyEntityAudioObjects(Entity *entity) +{ + Check(this); + Check(entity); + + // + //-------------------------------------------------------------------------- + // Stop and delete all audio objects + //-------------------------------------------------------------------------- + // + Entity::AudioSocketIterator + iterator(entity); + Component + *component; + AudioComponent + *audio_component; + + Check(&iterator); + while ((component = iterator.ReadAndNext()) != NULL) + { + audio_component = Cast_Object(AudioComponent*, component); + Check(audio_component); + audio_component->ReceiveControl(StopAudioControlID, 0.0f); + audio_component->ReceiveControl(FlushMessagesAudioControlID, 0.0f); + } + iterator.DeletePlugs(); +} + +// +//############################################################################# +// CreateModelAudioResource +//############################################################################# +// +ResourceDescription::ResourceID + L4AudioResourceManager::CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories* + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + const char *script_name = NULL; + ResourceDescription::ResourceID resource_id_list[3]; + size_t list_length = 0; + + resource_id_list[0] = ResourceDescription::NullResourceID; + resource_id_list[1] = ResourceDescription::NullResourceID; + resource_id_list[2] = ResourceDescription::NullResourceID; + + // + //-------------------------------------------------------------------------- + // Check for the external audio script + //-------------------------------------------------------------------------- + // + if (model_file->GetEntry("audio", "external", &script_name)) + { + // + // See if the resource already exists + // + ResourceDescription *res_description = + resource_file->FindResourceDescription( + script_name, + ResourceDescription::ExternalAudioStreamResourceType + ); + + // + //----------------------------------------------------------------------- + // If not, create it + //----------------------------------------------------------------------- + // + if (res_description == NULL) + { + // + // Make the file name + // + CString file_name(script_name); + CString prefix("audio\\"); + + file_name = prefix + file_name; + + // + // Build the memory stream + // + Tell("Opening Audio Script " << file_name << "\n"); + NotationFile script_file(file_name); + AudioObjectStream audio_object_stream; + + Check(&script_file); + Check(&audio_object_stream); + audio_object_stream.BuildFromNotationFile(&script_file, resource_file); + Tell("Closed Audio Script\n"); + + // + // Add the resource + // + res_description = + resource_file->AddResourceMemoryStream( + script_name, + ResourceDescription::ExternalAudioStreamResourceType, + 1, + ResourceDescription::Preload, + &audio_object_stream + ); + } + Check(res_description); + resource_id_list[list_length++] = res_description->resourceID; + } + + // + //-------------------------------------------------------------------------- + // Check for the internal audio script + //-------------------------------------------------------------------------- + // + if (model_file->GetEntry("audio", "internal", &script_name)) + { + // + // See if the resource already exists + // + ResourceDescription *res_description = + resource_file->FindResourceDescription( + script_name, + ResourceDescription::InternalAudioStreamResourceType + ); + + // + // If not, create it + // + if (res_description == NULL) + { + // + // Make the file name + // + CString file_name(script_name); + CString prefix("audio\\"); + + file_name = prefix + file_name; + + // + // Build the memory stream + // + Tell("Opening Audio Script " << file_name << "\n"); + NotationFile script_file(file_name); + AudioObjectStream audio_object_stream; + + Check(&script_file); + Check(&audio_object_stream); + audio_object_stream.BuildFromNotationFile(&script_file, resource_file); + Tell("Closed Audio Script\n"); + + // + // Add the resource + // + res_description = + resource_file->AddResourceMemoryStream( + script_name, + ResourceDescription::InternalAudioStreamResourceType, + 1, + ResourceDescription::Preload, + &audio_object_stream + ); + } + Check(res_description); + resource_id_list[list_length++] = res_description->resourceID; + } + + // + //-------------------------------------------------------------------------- + // Check for the audio entity model + //-------------------------------------------------------------------------- + // + const char *audio_entity_model = NULL; + + if (model_file->GetEntry("audio", "model", &audio_entity_model)) + { + // + // The resource should already exist + // + ResourceDescription *res_description = + resource_file->FindResourceDescription( + audio_entity_model, + ResourceDescription::ModelListResourceType + ); + if (res_description == NULL) + { + cout << "audio_entity_model == " << audio_entity_model; + Fail("L4AudioResourceManager::CreateModelAudioStreamResource - model not found"); + } + Check(res_description); + resource_id_list[list_length++] = res_description->resourceID; + } + + // + //-------------------------------------------------------------------------- + // If either script has been created, then create the resource list + //-------------------------------------------------------------------------- + // + if (list_length > 0) + { + ResourceDescription *res_description = + resource_file->AddResourceList( + model_name, + ResourceDescription::AudioStreamListResourceType, + 1, + ResourceDescription::Preload, + resource_id_list, + list_length + ); + Check(res_description); + return res_description->resourceID; + } + return ResourceDescription::NullResourceID; +} + diff --git a/CODE/RP/MUNGA_L4/L4AUDRES.HPP b/CODE/RP/MUNGA_L4/L4AUDRES.HPP new file mode 100644 index 0000000..3b72e4f --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDRES.HPP @@ -0,0 +1,185 @@ +//===========================================================================// +// File: l4audres.hpp // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/10/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4AUDRES_HPP) +# define L4AUDRES_HPP + +# if !defined(OBJSTRM_HH) +# include +# endif + +# if !defined(ENTITY_HPP) +# include +# endif + +# if !defined(AUDIO_HPP) +# include +# endif + + class AudioHardware; + + //########################################################################## + //###################### AudioObjectStream ########################### + //########################################################################## + + class AudioObjectStream: + public PlugStream + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + AudioObjectStream(); + AudioObjectStream( + ResourceDescription *resource_description, + Entity *entity + ); + ~AudioObjectStream(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Implementations + // + private: + RegisteredClass* + MakeObjectImplementation(Enumeration class_ID); + + void + CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ); + + void + BuildFromPageImplementation( + NameList *entry_list, + Enumeration class_ID, + ObjectID object_ID + ); + + void + BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name_string + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + Entity *entity; + }; + + //########################################################################## + //#################### L4AudioResourceManager ######################## + //########################################################################## + + class L4AudioResourceManager: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + L4AudioResourceManager(); + ~L4AudioResourceManager(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Static audio object methods + // + public: + // + //-------------------------------------------------------------------- + // PreloadResources + //-------------------------------------------------------------------- + // + void + PreloadResources( + NotationFile *notation_file, + AudioHardware *audio_hardware + ); + + // + //-------------------------------------------------------------------- + // UnloadResources + //-------------------------------------------------------------------- + // + void + UnloadResources( + AudioHardware *audio_hardware + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Static audio object methods - tool support + // + public: + // + //-------------------------------------------------------------------- + // CreateStaticAudioStreamResource + //-------------------------------------------------------------------- + // + static ResourceDescription::ResourceID + CreateStaticAudioStreamResource( + ResourceFile *resource_file + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Dynamic audio object methods + // + public: + // + //-------------------------------------------------------------------- + // CreateEntityAudioObjects + //-------------------------------------------------------------------- + // + void + CreateEntityAudioObjects( + Entity *entity, + AudioRepresentation audio_representation + ); + + // + //-------------------------------------------------------------------- + // DestroyEntityAudioObjects + //-------------------------------------------------------------------- + // + void + DestroyEntityAudioObjects(Entity *entity); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Dynamic audio object methods - tool support + // + public: + // + //-------------------------------------------------------------------- + // CreateModelAudioStreamResource + //-------------------------------------------------------------------- + // + static ResourceDescription::ResourceID + CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4AUDRND.CPP b/CODE/RP/MUNGA_L4/L4AUDRND.CPP new file mode 100644 index 0000000..4b3f67d --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDRND.CPP @@ -0,0 +1,1383 @@ +//===========================================================================// +// File: l4audrnd.cc // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDRND_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +// +//############################################################################# +// L4AudioRenderer +//############################################################################# +// +L4AudioRenderer::L4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode +): + AudioRenderer(render_rate), + runningAudioSourceSocket(NULL, False), + dormantAudioSourceSocket(NULL), + mixingAudioSourceSocket(NULL, False) +{ + missionReviewMode = mission_review_mode; + nextCalculateMixFrame = NullAudioFrameCount; +} + +// +//############################################################################# +// ~L4AudioRenderer +//############################################################################# +// +L4AudioRenderer::~L4AudioRenderer() +{ + // + //---------------------------------------------------------------------- + // Verify that all of entities have become uninteresting + //---------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.GetSize() == 0); + } + { + DormantSourceIterator iterator(&dormantAudioSourceSocket); + Verify(iterator.GetSize() == 0); + } + #endif + + // + //---------------------------------------------------------------------- + // Unload resources + //---------------------------------------------------------------------- + // + Check(&audioResourceManager); + audioResourceManager.UnloadResources(&audioHardware); + + // + //---------------------------------------------------------------------- + // Close audio hardware + //---------------------------------------------------------------------- + // + Check(&audioHardware); + audioHardware.Close(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + L4AudioRenderer::TestInstance() const +{ + AudioRenderer::TestInstance(); + + Check(&audioHardware); + Check(&runningAudioSourceSocket); + Check(&dormantAudioSourceSocket); + Check(&mixingAudioSourceSocket); + + return True; +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + L4AudioRenderer::Initialize() +{ + Check(this); + + // + //---------------------------------------------------------------------- + // Call inherited method + //---------------------------------------------------------------------- + // + AudioRenderer::Initialize(); + + // + //---------------------------------------------------------------------- + // Get the audio head + //---------------------------------------------------------------------- + // + AudioHead *audio_head = GetAudioHead(); + Check(audio_head); + + // + //---------------------------------------------------------------------- + // Open the audio renderer notation file + //---------------------------------------------------------------------- + // + int ret; + CString audio_file_name; + + if (missionReviewMode) + { + audio_file_name = "audio\\audiomr.ini"; + } + else + { + audio_file_name = "audio\\audio.ini"; + } + + NotationFile notation_file(audio_file_name); + Check(¬ation_file); + + // + //---------------------------------------------------------------------- + // Define clipping sphere (m) + //---------------------------------------------------------------------- + // + Scalar clipping_radius; + + ret = notation_file.GetEntry( + "AudioRenderer", + "clipping_radius", + &clipping_radius + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - clipping_radius not defined"); + } + Check(audio_head); + audio_head->DefineClippingSphere(clipping_radius); + + // + //---------------------------------------------------------------------- + // Distance to speakers or width of head entity (m) + //---------------------------------------------------------------------- + // + Scalar distance_between_ears; + ret = notation_file.GetEntry( + "AudioRenderer", + "distance_between_ears", + &distance_between_ears + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - distance_between_ears not defined"); + } + Check(audio_head); + audio_head->SetDistanceBetweenEars(distance_between_ears); + + // + //---------------------------------------------------------------------- + // Define amplitude rolloff characteristics + //---------------------------------------------------------------------- + // + Scalar amplitude_rolloff; + Scalar amplitude_rolloff_knee; + Scalar amplitude_rolloff_distance_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "amplitude_rolloff", + &litude_rolloff + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - amplitude_rolloff not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "amplitude_rolloff_distance_scale", + &litude_rolloff_distance_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - amplitude_rolloff_distance_scale not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "amplitude_rolloff_knee", + &litude_rolloff_knee + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - amplitude_rolloff_knee not defined"); + } + + Check(audio_head); + audio_head->ControlAmplitudeRollOff( + amplitude_rolloff, + amplitude_rolloff_knee, + amplitude_rolloff_distance_scale + ); + + // + //---------------------------------------------------------------------- + // Define high frequency rolloff characteristics + //---------------------------------------------------------------------- + // + Scalar high_frequency_rolloff; + Scalar high_frequency_rolloff_knee; + Scalar high_frequency_rolloff_distance_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "high_frequency_rolloff", + &high_frequency_rolloff + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - high_frequency_rolloff not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "high_frequency_rolloff_knee", + &high_frequency_rolloff_knee + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - high_frequency_rolloff_knee not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "high_frequency_rolloff_distance_scale", + &high_frequency_rolloff_distance_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - high_frequency_rolloff_distance_scale not defined"); + } + + Check(audio_head); + audio_head->ControlHighFrequencyRollOff( + high_frequency_rolloff, + high_frequency_rolloff_knee, + high_frequency_rolloff_distance_scale + ); + + // + //---------------------------------------------------------------------- + // Define Doppler characterisitics + //---------------------------------------------------------------------- + // + Scalar doppler_range; + Scalar speed_of_sound; + + ret = notation_file.GetEntry( + "AudioRenderer", + "doppler_range", + &doppler_range + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - doppler_range not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "speed_of_sound", + &speed_of_sound + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - speed_of_sound not defined"); + } + + Check(audio_head); + audio_head->ControlDopplerEffect( + doppler_range, + speed_of_sound + ); + + // + //---------------------------------------------------------------------- + // Define source compression characterisitics + //---------------------------------------------------------------------- + // + Scalar compression_exponent; + Scalar compression_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "compression_exponent", + &compression_exponent + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - compression_exponent not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "compression_scale", + &compression_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - compression_scale not defined"); + } + + Check(audio_head); + audio_head->ControlSourceCompression( + compression_exponent, + compression_scale + ); + + // + //---------------------------------------------------------------------- + // Set ITD difference + //---------------------------------------------------------------------- + // + Scalar itd_difference; + + ret = notation_file.GetEntry( + "AudioRenderer", + "itd_difference", + &itd_difference + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - itd_difference not defined"); + } + + Check(audio_head); + audio_head->SetITDDifference(itd_difference); + + // + //---------------------------------------------------------------------- + // Set global reverb scale + //---------------------------------------------------------------------- + // + Scalar global_reverb_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "global_reverb_scale", + &global_reverb_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - global_reverb_scale not defined"); + } + + Check(audio_head); + audio_head->SetGlobalReverbScale(global_reverb_scale); + + // + //---------------------------------------------------------------------- + // Initialize the audio hardware + //---------------------------------------------------------------------- + // + Check(&audioHardware); + audioHardware.Initialize(); + + // + //---------------------------------------------------------------------- + // Preload resources + //---------------------------------------------------------------------- + // + Check(&audioResourceManager); + audioResourceManager.PreloadResources(¬ation_file, &audioHardware); +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + L4AudioRenderer::NotifyOfNewInterestingEntity(Entity *interesting_entity) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_CREATE_OBJECTS(); + + Check(this); + Check(interesting_entity); + + Entity *linked_entity = GetLinkedEntity(); + Check(linked_entity); + + AudioRepresentation audio_representation = + (AudioRepresentation)interesting_entity->GetAudioRepresentation( + linked_entity + ); + + Check(&audioResourceManager); + audioResourceManager.CreateEntityAudioObjects( + interesting_entity, + audio_representation + ); + + CLEAR_AUDIO_RENDERER_CREATE_OBJECTS(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntity +//############################################################################# +// +void + L4AudioRenderer::NotifyOfBecomingUninterestingEntity( + Entity *uninteresting_entity + ) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_DESTROY_OBJECTS(); + + Check(this); + Check(uninteresting_entity); + + Check(&audioResourceManager); + audioResourceManager.DestroyEntityAudioObjects(uninteresting_entity); + + CLEAR_AUDIO_RENDERER_DESTROY_OBJECTS(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +// LoadMissionImplementation +//############################################################################# +// +void + L4AudioRenderer::LoadMissionImplementation(Mission*) +{ + Check(this); +} + +// +//############################################################################# +// ShutdownImplementation +//############################################################################# +// +void + L4AudioRenderer::ShutdownImplementation() +{ + Check(this); +} + +// +//############################################################################# +// SuspendImplementation +//############################################################################# +// +void + L4AudioRenderer::SuspendImplementation() +{ + Check(this); +} + +// +//############################################################################# +// ResumeImplementation +//############################################################################# +// +void + L4AudioRenderer::ResumeImplementation() +{ + Check(this); +} + +// +//############################################################################# +// StartRequest +//############################################################################# +// +void + L4AudioRenderer::StartRequest(L4AudioSource *audio_source) +{ + Check(this); + Check(audio_source); + + // + //-------------------------------------------------------------------------- + // Verify that the source is stopped + //-------------------------------------------------------------------------- + // + Verify(audio_source->GetAudioSourceState() == StoppedAudioSourceState); + + // + //-------------------------------------------------------------------------- + // Request audio resources + //-------------------------------------------------------------------------- + // + Logical + resources_available; + AudioChannelSet + channel_set_result; + + resources_available = + RequestAudioResources( + audio_source, + &channel_set_result + ); + if (!resources_available) + { + if (audio_source->GetAudioRenderType() == SustainedAudioRenderType) + { + // + // Set state to dormant and add the source to the dormant list + // + audio_source->AssignAudioSourceState(DormantAudioSourceState); + dormantAudioSourceSocket.Add(audio_source); + } + return; + } + + // + //-------------------------------------------------------------------------- + // Start the audio source + //-------------------------------------------------------------------------- + // + + // + // Update source spatial model + // Set channel set of source + // Source start implementation + // Set state of source to running + // + audio_source->UpdateSpatialModel(GetAudioHead()); + audio_source->SetAudioChannelSet(channel_set_result); + audio_source->StartImplementation(); + audio_source->AssignAudioSourceState(RunningAudioSourceState); + + // + // Add source to the running list and the mixing list + // + runningAudioSourceSocket.AddValue( + audio_source, + audio_source->CalculateAudioWeighting() + ); + if ( + audio_source->GetAudioSourceMixPresence() != + ManualAudioSourceMixPresence + ) + { + mixingAudioSourceSocket.AddValue( + audio_source, + audio_source->GetAudioSourceMixPresence() + ); + } + #ifdef LAB_ONLY + sourceStartCount++; + #endif +} + +// +//############################################################################# +// StopRequest +//############################################################################# +// +void + L4AudioRenderer::StopRequest(L4AudioSource *audio_source) +{ + Check(this); + Check(audio_source); + + // + //-------------------------------------------------------------------------- + // Verify that the source is not stopped + //-------------------------------------------------------------------------- + // + Verify(audio_source->GetAudioSourceState() != StoppedAudioSourceState); + + // + //-------------------------------------------------------------------------- + // If state of the source is dormant or suspended + // Then set source to stop state and remove from dormant list + //-------------------------------------------------------------------------- + // + if ( + audio_source->GetAudioSourceState() == DormantAudioSourceState || + audio_source->GetAudioSourceState() == SuspendedAudioSourceState + ) + { + // + // Set state of source to stopped + // Verify that source is in dormant list + // Remove source from dormant list + // Verify that source is not in dormant list + // + audio_source->AssignAudioSourceState(StoppedAudioSourceState); + #if DEBUG_LEVEL>0 + { + DormantSourceIterator iterator(&dormantAudioSourceSocket); + Verify(iterator.IsPlugMember(audio_source) == True); + } + #endif + PlugIterator remover(audio_source); + remover.RemoveSocket(&dormantAudioSourceSocket); + #if DEBUG_LEVEL>0 + { + DormantSourceIterator iterator(&dormantAudioSourceSocket); + Verify(iterator.IsPlugMember(audio_source) == False); + } + #endif + return; + } + + // + //-------------------------------------------------------------------------- + // Stop the source + //-------------------------------------------------------------------------- + // + AudioSourceStopMaintenance(audio_source); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +void + L4AudioRenderer::ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_EXECUTE(); + + Check(this); + + AudioRenderer::ExecuteImplementation(complexity_update, iterator); + CalculateMix(); + RunningSourceCheckup(); + // RunningAudioSourceSort(); + DormantSourceCheckup(); + + CLEAR_AUDIO_RENDERER_EXECUTE(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +// CalculateMix +//############################################################################# +// +void + L4AudioRenderer::CalculateMix() +{ + SET_AUDIO_CALCULATE_MIX(); + + // + //-------------------------------------------------------------------------- + // Is this the next calculate mix frame + //-------------------------------------------------------------------------- + // + #if 0 + if (nextCalculateMixFrame > GetAudioFrameCount()) + { + CLEAR_AUDIO_CALCULATE_MIX(); + return; + } + nextCalculateMixFrame = GetAudioFrameCount() + DefaultAudioFrameDelay; + #endif + + // + //-------------------------------------------------------------------------- + // Calculate the compression volume scaling + // + // For each source, calculate the amount to scale its volume by + // according to those sources which have a higher mix presence + //-------------------------------------------------------------------------- + // + { + AudioControlValue + compression_scale = 1.0f; + AudioControlValue + compression_effect = 0.0f; + AudioSourceMixPresence + current_mix_presence = MedAudioSourceMixPresence; + + MixingSourceIterator + iterator(&mixingAudioSourceSocket); + L4AudioSource + *audio_source; + + Check(GetAudioHead()); + Scalar comp_scale = GetAudioHead()->GetSourceCompressionScale(); + Scalar comp_exp = GetAudioHead()->GetSourceCompressionExponent(); + + // + // Get mix presence of the first source + // + if ((audio_source = iterator.GetCurrent()) != NULL) + { + Check(audio_source); + current_mix_presence = audio_source->GetAudioSourceMixPresence(); + } + + // + //----------------------------------------------------------------------- + // For each audio source, calculate the compression scale + //----------------------------------------------------------------------- + // + while ((audio_source = iterator.ReadAndNext()) != NULL) + { + Check(audio_source); + + // + //-------------------------------------------------------------------- + // If the mix presence of this source is greater then the last + // source then we have stepped to a lower mix presence. + //-------------------------------------------------------------------- + // + if ( + current_mix_presence != + audio_source->GetAudioSourceMixPresence() + ) + { + Verify( + current_mix_presence < + audio_source->GetAudioSourceMixPresence() + ); + current_mix_presence = audio_source->GetAudioSourceMixPresence(); + + // + // Calculate the compression scale for this mix presence + // + // scale = 1 - ((comp_scale*x)^comp_exp) + // + compression_scale = + 1.0f - pow(comp_scale * compression_effect, comp_exp); + Verify(compression_scale >= 0.0f && compression_scale <= 1.0f); + } + + // + //-------------------------------------------------------------------- + // Set the compression scale for this source + //-------------------------------------------------------------------- + // + audio_source->SetVolumeCompressionScale(compression_scale); + + // + //-------------------------------------------------------------------- + // Calculate the compression effect for this source + //-------------------------------------------------------------------- + // + AudioControlValue source_compression_effect; + + source_compression_effect = + audio_source->CalculateSourceCompressionEffect(); + Verify( + source_compression_effect >= 0.0f && + source_compression_effect <= 1.0f + ); + + // + //-------------------------------------------------------------------- + // Update the compression effect for this mix presence + //-------------------------------------------------------------------- + // + compression_effect = + Max(compression_effect, source_compression_effect); + Verify(compression_effect >= 0.0f && compression_effect <= 1.0f); + + #if 0 + Tell( + "compression_effect " << compression_effect << + " : compression_scale " << compression_scale << "\n" + ); + #endif + } + } + CLEAR_AUDIO_CALCULATE_MIX(); +} + +// +//############################################################################# +// RunningSourceCheckup +//############################################################################# +// +void + L4AudioRenderer::RunningSourceCheckup() +{ + SET_AUDIO_RUNNING_SOURCES(); + + // + //-------------------------------------------------------------------------- + // Iterate through all running sources + //-------------------------------------------------------------------------- + // + ChainOf + resort_socket(NULL); + RunningSourceIterator + running_iterator(&runningAudioSourceSocket); + L4AudioSource + *audio_source; + + while ((audio_source = running_iterator.GetCurrent()) != NULL) + { + Check(audio_source); + + // + //----------------------------------------------------------------------- + // If the source does not require maintenance then skip it + //----------------------------------------------------------------------- + // + if (!audio_source->RequiresMaintenance(GetAudioHead())) + { + running_iterator.Next(); + continue; + } + + // + //----------------------------------------------------------------------- + // If the source is clipped then either stop or suspend + //----------------------------------------------------------------------- + // + if (audio_source->IsAudioSourceClipped(GetAudioHead())) + { + if (audio_source->GetAudioRenderType() == TransientAudioRenderType) + { + AudioSourceStopMaintenance(audio_source); + } + else + { + Verify( + audio_source->GetAudioRenderType() == + SustainedAudioRenderType + ); + AudioSourceSuspendMaintenance(audio_source); + } + continue; + } + + // + //----------------------------------------------------------------------- + // If the source is finished playing then stop it + //----------------------------------------------------------------------- + // + if (audio_source->IsFinishedPlaying()) + { + AudioSourceStopMaintenance(audio_source); + continue; + } + + // + //----------------------------------------------------------------------- + // Recycle sustained sources + //----------------------------------------------------------------------- + // + if (audio_source->GetAudioRenderType() == SustainedAudioRenderType) + { + AudioTime duration_cutoff(15.0f); + + #if 0 + duration_cutoff = 15.0f; // HACK - should come from somewhere else + #endif + if (audio_source->GetCurrentRunningTime() > duration_cutoff) + { + audio_source->SuspendImplementation(); + audio_source->AssignAudioSourceState(SuspendedAudioSourceState); + audio_source->ResumeImplementation(); + audio_source->AssignAudioSourceState(RunningAudioSourceState); + running_iterator.Next(); + continue; + } + } + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + SET_AUDIO_EXECUTE_SOURCES(); + audio_source->Execute(); + CLEAR_AUDIO_EXECUTE_SOURCES(); + + // + //----------------------------------------------------------------------- + // Add to resort list if weight has changed + //----------------------------------------------------------------------- + // + if ( + audio_source->CalculateAudioWeighting() != + running_iterator.GetValue() + ) + { + running_iterator.Remove(); + resort_socket.Add(audio_source); + } + else + { + running_iterator.Next(); + } + } + + // + //-------------------------------------------------------------------------- + // Sort resort socket back into running socket + //-------------------------------------------------------------------------- + // + ChainIteratorOf + resort_iterator(&resort_socket); + + while ((audio_source = resort_iterator.ReadAndNext()) != NULL) + { + Check(audio_source); + Verify(running_iterator.IsPlugMember(audio_source) == False); + runningAudioSourceSocket.AddValue( + audio_source, + audio_source->CalculateAudioWeighting() + ); + } + + CLEAR_AUDIO_RUNNING_SOURCES(); +} + +// +//############################################################################# +// DormantSourceCheckup +//############################################################################# +// +void + L4AudioRenderer::DormantSourceCheckup() +{ + SET_AUDIO_DORMANT_SOURCES(); + + // + //-------------------------------------------------------------------------- + // Assemble the request socket + //-------------------------------------------------------------------------- + // + VChainOf + resume_request_socket(NULL, False); + DormantSourceIterator + dormant_iterator(&dormantAudioSourceSocket); + L4AudioSource + *audio_source; + + while ((audio_source = dormant_iterator.ReadAndNext()) != NULL) + { + Check(audio_source); + + // + // If the suspend gate is not up then it can not resume + // + if (!audio_source->CanResume(GetAudioHead())) + continue; + + // + // If the audio source is clipped then it can not resume + // + if (audio_source->IsAudioSourceClipped(GetAudioHead())) + continue; + + // + // Add to request socket + // + resume_request_socket.AddValue( + audio_source, + audio_source->CalculateAudioWeighting() + ); + } + + // + //-------------------------------------------------------------------------- + // Iterate through request socket + //-------------------------------------------------------------------------- + // + VChainIteratorOf + resume_request_iterator(&resume_request_socket); + + while ((audio_source = resume_request_iterator.GetCurrent()) != NULL) + { + Check(audio_source); + + // + // Request audio resources + // + AudioChannelSet + channel_set_result; + + if (!RequestAudioResources(audio_source, &channel_set_result)) + break; + + // + // Remove from dormant list and request list + // + PlugIterator remover(audio_source); + remover.RemoveSocket(&dormantAudioSourceSocket); + AudioWeighting audio_weighting = resume_request_iterator.GetValue(); + resume_request_iterator.Remove(); + + // + // Update Spatial model + // + audio_source->UpdateSpatialModel(GetAudioHead()); + + // + // Set channel set of source + // Source resume implementation + // Set state of source to running + // + audio_source->SetAudioChannelSet(channel_set_result); + audio_source->ResumeImplementation(); + audio_source->AssignAudioSourceState(RunningAudioSourceState); + + // + // Put on running socket and mixing socket + // + runningAudioSourceSocket.AddValue(audio_source, audio_weighting); + if ( + audio_source->GetAudioSourceMixPresence() != + ManualAudioSourceMixPresence + ) + { + mixingAudioSourceSocket.AddValue( + audio_source, + audio_source->GetAudioSourceMixPresence() + ); + } + } + CLEAR_AUDIO_DORMANT_SOURCES(); +} + +// +//############################################################################# +// AudioSourceStopMaintenance +//############################################################################# +// +void + L4AudioRenderer::AudioSourceStopMaintenance(L4AudioSource *source) +{ + Check(source); + Verify(source->GetAudioSourceState() == RunningAudioSourceState); + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == True); + } + #endif + + source->StopImplementation(); + source->AssignAudioSourceState(StoppedAudioSourceState); + source->ReleaseChannels(); + + PlugIterator remover(source); + remover.RemoveSocket(&runningAudioSourceSocket); + remover.RemoveSocket(&mixingAudioSourceSocket); + + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == False); + } + #endif +} + +// +//############################################################################# +// AudioSourceSuspendMaintenance +//############################################################################# +// +void + L4AudioRenderer::AudioSourceSuspendMaintenance(L4AudioSource *source) +{ + Check(source); + Verify(source->GetAudioRenderType() == SustainedAudioRenderType); + Verify(source->GetAudioSourceState() == RunningAudioSourceState); + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == True); + } + #endif + + source->SuspendImplementation(); + source->AssignAudioSourceState(SuspendedAudioSourceState); + source->ReleaseChannels(); + + PlugIterator remover(source); + remover.RemoveSocket(&runningAudioSourceSocket); + remover.RemoveSocket(&mixingAudioSourceSocket); + + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == False); + } + #endif + + dormantAudioSourceSocket.Add(source); +} + +// +//############################################################################# +// RequestAudioResources +//############################################################################# +// +Logical + L4AudioRenderer::RequestAudioResources( + L4AudioSource *audio_source, + AudioChannelSet *channel_set_result + ) +{ + Check(this); + Check(audio_source); + Check(channel_set_result); + + // + //-------------------------------------------------------------------------- + // This source must be within the culling volume + //-------------------------------------------------------------------------- + // + if (audio_source->IsAudioSourceClipped(GetAudioHead())) + return False; + + // + //-------------------------------------------------------------------------- + // Request audio channels for this source + //-------------------------------------------------------------------------- + // + Logical + resources_available; + + *channel_set_result = *audio_source->GetAudioChannelSet(); + Check(channel_set_result); + + resources_available = + RequestAudioChannels( + audio_source->GetAudioVoiceCount(), + channel_set_result + ); + + // + //-------------------------------------------------------------------------- + // If audio channels are not available then check running sources for + // lower weight sources + //-------------------------------------------------------------------------- + // + if (!resources_available) + { + RunningSourceIterator + iterator(&runningAudioSourceSocket); + L4AudioSource + *running_audio_source; + AudioWeighting + audio_source_weighting; + + iterator.Last(); + running_audio_source = iterator.GetCurrent(); + audio_source_weighting = audio_source->CalculateAudioWeighting(); + + // + //----------------------------------------------------------------------- + // while + // request for channels is not satisfied and + // there exist running sources that have lower weighting + //----------------------------------------------------------------------- + // + while ( + !resources_available && + running_audio_source != NULL && + audio_source_weighting < iterator.GetValue() // Actual value is inverted + ) + { + Check(running_audio_source); + Verify( + running_audio_source->GetAudioSourcePriority() <= + audio_source->GetAudioSourcePriority() + ); + + // + //-------------------------------------------------------------------- + // Collect Statistics + //-------------------------------------------------------------------- + // + #ifdef LAB_ONLY + if ( + running_audio_source->GetAudioSourcePriority() < + audio_source->GetAudioSourcePriority() + ) + { + resourceStealPriorityCount++; + } + else + { + Verify( + running_audio_source->GetAudioSourcePriority() == + audio_source->GetAudioSourcePriority() + ); + Warn( + running_audio_source->CalculateSourceVolumeScale() >= + audio_source->CalculateSourceVolumeScale() + ); + resourceStealVolumeCount++; + } + AudioTime duration_cutoff(0.1f); + if ( + running_audio_source->GetCurrentRunningTime() <= + duration_cutoff + ) + { + stealShortDurationCount++; + } + resourceStealCount++; + #endif + + // + //-------------------------------------------------------------------- + // If running source is transient + // Then stop the source + // Else suspend the source + //-------------------------------------------------------------------- + // + if ( + running_audio_source->GetAudioRenderType() == + TransientAudioRenderType + ) + { + AudioSourceStopMaintenance(running_audio_source); + } + else + { + Verify( + running_audio_source->GetAudioRenderType() == + SustainedAudioRenderType + ); + AudioSourceSuspendMaintenance(running_audio_source); + } + + // + //-------------------------------------------------------------------- + // Request resources again + //-------------------------------------------------------------------- + // + resources_available = + RequestAudioChannels( + audio_source->GetAudioVoiceCount(), + channel_set_result + ); + + iterator.Last(); + running_audio_source = iterator.GetCurrent(); + } + } + return resources_available; +} + +// +//############################################################################# +// RequestAudioChannels +//############################################################################# +// +Logical + L4AudioRenderer::RequestAudioChannels( + AudioVoiceCount voices_requested, + AudioChannelSet *channel_set_request + ) +{ + Check(this); + Check(channel_set_request); + + // + //---------------------------------------------------------------------- + // Attempt to allocate channels from audio hardware + //---------------------------------------------------------------------- + // + AudioChannel *channel; + Logical success = False; + AudioCard *front_card = GetFrontCard(); + AudioCard *rear_card = GetRearCard(); + + Check(front_card); + Check(rear_card); + + while (True) + { + if (channel_set_request->IsFrontLeftEnabled()) + { + if ((channel = + front_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetFrontLeft(channel); + } + + if (channel_set_request->IsFrontRightEnabled()) + { + if ((channel = + front_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetFrontRight(channel); + } + + if (channel_set_request->IsRearLeftEnabled()) + { + if ((channel = + rear_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetRearLeft(channel); + } + + if (channel_set_request->IsRearRightEnabled()) + { + if ((channel = + rear_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetRearRight(channel); + } + + success = True; + break; + } + + // + //---------------------------------------------------------------------- + // If did not succeed then release allocated channels + //---------------------------------------------------------------------- + // + if (!success) + { + channel_set_request->ReleaseAll(); + return False; + } + + // + //---------------------------------------------------------------------- + // else, return allocated channels + //---------------------------------------------------------------------- + // + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer profile bits ~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(TRACE_AUDIO_RENDERER_RUNNING_SOURCES) + BitTrace Audio_Renderer_Running_Sources("Audio Renderer Running Sources"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_RUNNING_SORT) + BitTrace Audio_Renderer_Running_Sort("Audio Renderer Running Sort"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_CALCULATE_MIX) + BitTrace Audio_Renderer_Calculate_Mix("Audio Renderer Calculate Mix"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_EXECUTE_SOURCES) + BitTrace Audio_Renderer_Execute_Sources("Audio Renderer Execute Sources"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_DORMANT_SOURCES) + BitTrace Audio_Renderer_Dormant_Sources("Audio Renderer Dormant Sources"); +#endif diff --git a/CODE/RP/MUNGA_L4/L4AUDRND.HPP b/CODE/RP/MUNGA_L4/L4AUDRND.HPP new file mode 100644 index 0000000..da4d2b5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDRND.HPP @@ -0,0 +1,231 @@ +//===========================================================================// +// File: l4audrnd.hh // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4AUDRND_HPP) +# define L4AUDRND_HPP + +# if !defined(AUDREND_HPP) +# include +# endif + +# if !defined(L4AUDHDW_HPP) +# include +# endif + +# if !defined(L4AUDIO_HPP) +# include +# endif + +# if !defined(L4AUDRES_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class L4AudioRenderer: + public AudioRenderer + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction, Testing + // + public: + L4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode + ); + ~L4AudioRenderer(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Renderer support + // + public: + void + Initialize(); + + void + NotifyOfNewInterestingEntity(Entity *interesting_entity); + void + NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity); + + protected: + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + + private: + void + LoadMissionImplementation(Mission *mission); + void + ShutdownImplementation(); + void + SuspendImplementation(); + void + ResumeImplementation(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Audio hardware accessors + // + public: + AudioCard* + GetFrontCard(); + AudioCard* + GetRearCard(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Audio Source support + // + public: + void + StartRequest(L4AudioSource *audio_source); + void + StopRequest(L4AudioSource *audio_source); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + void + CalculateMix(); + void + RunningSourceCheckup(); + //void + // RunningAudioSourceSort(); + void + DormantSourceCheckup(); + void + AudioSourceStopMaintenance(L4AudioSource *source); + void + AudioSourceSuspendMaintenance(L4AudioSource *source); + + Logical + RequestAudioResources( + L4AudioSource *audio_source, + AudioChannelSet *channel_set_result + ); + Logical + RequestAudioChannels( + AudioVoiceCount voices_requested, + AudioChannelSet *channel_set_request + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + Logical + missionReviewMode; + + AudioHardware + audioHardware; + L4AudioResourceManager + audioResourceManager; + + AudioFrameCount + nextCalculateMixFrame; + + typedef VChainOf + RunningSourceSocket; + typedef VChainIteratorOf + RunningSourceIterator; + + RunningSourceSocket + runningAudioSourceSocket; + + typedef ChainOf + DormantSourceSocket; + typedef ChainIteratorOf + DormantSourceIterator; + + DormantSourceSocket + dormantAudioSourceSocket; + + typedef VChainOf + MixingSourceSocket; + typedef VChainIteratorOf + MixingSourceIterator; + + MixingSourceSocket + mixingAudioSourceSocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + + inline AudioCard* + L4AudioRenderer::GetFrontCard() + { + Check(this); + return audioHardware.GetFrontCard(); + } + + inline AudioCard* + L4AudioRenderer::GetRearCard() + { + Check(this); + return audioHardware.GetRearCard(); + } + + //~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer profile macros ~~~~~~~~~~~~~~~~~~~~ + + #if defined(TRACE_AUDIO_RENDERER_RUNNING_SOURCES) + extern BitTrace Audio_Renderer_Running_Sources; + #define SET_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Set() + #define CLEAR_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Clear() + #else + #define SET_AUDIO_RUNNING_SOURCES() + #define CLEAR_AUDIO_RUNNING_SOURCES() + #endif + + #if defined(TRACE_AUDIO_RENDERER_RUNNING_SORT) + extern BitTrace Audio_Renderer_Running_Sort; + #define SET_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Set() + #define CLEAR_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Clear() + #else + #define SET_AUDIO_RUNNING_SORT() + #define CLEAR_AUDIO_RUNNING_SORT() + #endif + + #if defined(TRACE_AUDIO_RENDERER_CALCULATE_MIX) + extern BitTrace Audio_Renderer_Calculate_Mix; + #define SET_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Set() + #define CLEAR_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Clear() + #else + #define SET_AUDIO_CALCULATE_MIX() + #define CLEAR_AUDIO_CALCULATE_MIX() + #endif + + #if defined(TRACE_AUDIO_RENDERER_EXECUTE_SOURCES) + extern BitTrace Audio_Renderer_Execute_Sources; + #define SET_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Set() + #define CLEAR_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Clear() + #else + #define SET_AUDIO_EXECUTE_SOURCES() + #define CLEAR_AUDIO_EXECUTE_SOURCES() + #endif + + #if defined(TRACE_AUDIO_RENDERER_DORMANT_SOURCES) + extern BitTrace Audio_Renderer_Dormant_Sources; + #define SET_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Set() + #define CLEAR_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Clear() + #else + #define SET_AUDIO_DORMANT_SOURCES() + #define CLEAR_AUDIO_DORMANT_SOURCES() + #endif + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4AUDTUL.CPP b/CODE/RP/MUNGA_L4/L4AUDTUL.CPP new file mode 100644 index 0000000..14fc13d --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDTUL.CPP @@ -0,0 +1,83 @@ +//===========================================================================// +// File: l4audres.cpp // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/10/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDRES_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +#if !defined(L4AUDIO_HPP) +# include +#endif + +ResourceDescription::ResourceID + L4Tool::CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + return + L4AudioResourceManager::CreateModelAudioStreamResource( + resource_file, + model_name, + model_file, + directories + ); +} + +ResourceDescription::ResourceID + L4Tool::CreateStaticAudioStreamResource( + ResourceFile *resource_file + ) +{ + return + L4AudioResourceManager::CreateStaticAudioStreamResource( + resource_file + ); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioCreateSymbols::WriteEntryStream(ofstream &symbol_file) +{ + AudioCreateSymbols::WriteEntryStream(symbol_file); + + #define WRITE_ENTRY(name)\ + {\ + Verify(symbol_file);\ + symbol_file << #name;\ + symbol_file << "=";\ + symbol_file << name;\ + symbol_file << "\n";\ + } + + WRITE_ENTRY(FrontDirectPatchPosition); + WRITE_ENTRY(RearDirectPatchPosition); + WRITE_ENTRY(FrontLeftDirectPatchPosition); + WRITE_ENTRY(FrontRightDirectPatchPosition); + WRITE_ENTRY(RearLeftDirectPatchPosition); + WRITE_ENTRY(RearRightDirectPatchPosition); +} + diff --git a/CODE/RP/MUNGA_L4/L4AUDWTR.CPP b/CODE/RP/MUNGA_L4/L4AUDWTR.CPP new file mode 100644 index 0000000..db21e42 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDWTR.CPP @@ -0,0 +1,210 @@ +//===========================================================================// +// File: l4audwtr.cpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 04/17/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4AUDWTR_HPP) +# include +#endif + +#if !defined(OBJSTRM_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +//############################################################################# +//######################## L4AudioCollisionTrigger ###################### +//############################################################################# + +#if 0 +L4AudioCollisionTrigger::L4AudioCollisionTrigger( + StateIndicator *state_attribute_ptr, + Normal *normal_attribute_ptr, + Static3DPatchSource *audio_source, + Enumeration trigger_state, + AudioControlID control_ID, + AudioControlValue control_value, + Logical dump_value +): + AudioStateWatcher( + state_attribute_ptr, + audio_source, + L4AudioCollisionTriggerClassID, + dump_value + ) +{ + Check(normal_attribute_ptr); + normalAttributePtr = normal_attribute_ptr; + triggerState = trigger_state; + controlID = control_ID; + controlValue = control_value; + + PrimeWatcher(); +} +#endif + +// +//############################################################################# +//############################################################################# +// +L4AudioCollisionTrigger::~L4AudioCollisionTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +L4AudioCollisionTrigger::L4AudioCollisionTrigger( + PlugStream *stream, + Entity *entity +): + AudioStateWatcher(stream, entity) +{ + // + // HACK - Get "normal" attribute pointer with names + // + CString attribute_name; + void *attribute_ptr; + + MemoryStream_Read(stream, &attribute_name); + Check(entity); + attribute_ptr = entity->GetAttributePointer(attribute_name); + normalAttributePtr = Cast_Object(Normal*, attribute_ptr); + + // + // Get other fields + // + MemoryStream_Read(stream, &triggerState); + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioCollisionTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioStateWatcher::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // HACK - Store "normal" attribute pointer with names + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, normal_attribute); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, trigger_state); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value); +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioCollisionTrigger::TestInstance() const +{ + AudioStateWatcher::TestInstance(); + Check(normalAttributePtr); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioCollisionTrigger::StateChanged( + Enumeration, + Enumeration new_state + ) +{ + if (new_state == triggerState) + { + // + // Get static 3D source + // + AudioComponent *audio_component; + Static3DPatchSource *audio_source; + + Check(&audioComponentSocket); + audio_component = audioComponentSocket.GetCurrent(); + Check(audio_component); + audio_source = Cast_Object(Static3DPatchSource*, audio_component); + Check(audio_source); + + // + // Get collision direction + // + Vector3D collision_direction(0.0f, 0.0f, 0.0f); + + Check(normalAttributePtr); + collision_direction -= *normalAttributePtr; + Check(&collision_direction); + audio_source->SetPosition(collision_direction); + + // + // Send control value + // + #if 1 + audio_component->ReceiveControl(controlID, controlValue); + #else + audio_component->PostReceiveControl(controlID, controlValue); + #endif + } +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + L4AudioCollisionTrigger::DumpValue(const StateIndicator *state_attribute_ptr) +#else +void + L4AudioCollisionTrigger::DumpValue(const StateIndicator*) +#endif +{ + // + // Get collision direction + // + Vector3D collision_direction(0.0f, 0.0f, 0.0f); + + Check(normalAttributePtr); + collision_direction -= *normalAttributePtr; + Check(&collision_direction); + + Tell( + "*state_attribute_ptr = " << *state_attribute_ptr << " : " << + "collision_direction = " << collision_direction << "\n" + ); +} + diff --git a/CODE/RP/MUNGA_L4/L4AUDWTR.HPP b/CODE/RP/MUNGA_L4/L4AUDWTR.HPP new file mode 100644 index 0000000..d2c6072 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4AUDWTR.HPP @@ -0,0 +1,113 @@ +//===========================================================================// +// File: l4audwtr.hpp // +// Project: MUNGA Brick: Audio Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 04/17/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(l4AUDWTR_HPP) +# define l4AUDWTR_HPP + +# if !defined(AUDWTHR_HPP) +# include +# endif + +# if !defined(L4AUDIO_HPP) +# include +# endif + +# if !defined(NORMAL_HPP) +# include +# endif + + //########################################################################## + //##################### L4AudioCollisionTrigger ###################### + //########################################################################## + + class L4AudioCollisionTrigger: + public AudioStateWatcher + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor + //-------------------------------------------------------------------- + // + #if 0 + L4AudioCollisionTrigger( + StateIndicator *state_attribute_ptr, + Normal *normal_attribute_ptr, + Static3DPatchSource *audio_source, + Enumeration trigger_state, + AudioControlID control_ID, + AudioControlValue control_value, + Logical dump_value + ); + #endif + L4AudioCollisionTrigger( + PlugStream *stream, + Entity *entity + ); + ~L4AudioCollisionTrigger(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + RegisteredClass::ClassID class_ID, + ObjectID object_ID + ); + + protected: + // + //-------------------------------------------------------------------- + // StateChanged + //-------------------------------------------------------------------- + // + void + StateChanged( + Enumeration old_state, + Enumeration new_state + ); + + private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const StateIndicator *state_attribute_ptr); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Normal* + normalAttributePtr; + Enumeration + triggerState; + AudioControlID + controlID; + AudioControlValue + controlValue; + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4CTLTUL.CPP b/CODE/RP/MUNGA_L4/L4CTLTUL.CPP new file mode 100644 index 0000000..98b3d64 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4CTLTUL.CPP @@ -0,0 +1,31 @@ +//===========================================================================// +// File: l4video.cpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +// 07/11/95 KEO Modify video resource format. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include + +#if !defined(L4CTRL_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +PlatformTool::FindNameFunction + L4Tool::GetControlMappingFunction() +{ + return &LBE4ControlsManager::SetControlMappingID; +} + diff --git a/CODE/RP/MUNGA_L4/L4CTRL.CPP b/CODE/RP/MUNGA_L4/L4CTRL.CPP new file mode 100644 index 0000000..99b7431 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4CTRL.CPP @@ -0,0 +1,2429 @@ +//==========================================================================// +// File: controls.cc // +// Project: MUNGA Brick: Controls Manager // +// Contents: Interface specification for Controls // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 11/21/94 CPB Initial coding. // +//--------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4CTRL_HPP) +# include +#endif + +#if !defined(L4KEYBD_HPP) +# include +#endif + +#if !defined(L4APP_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) Tell(n << flush); +#else +# define Test_Tell(n) +#endif + +static const char *initFileName = "JOYSTICK.INI"; +#define RIO_SPOOL_SIZE 12000 + +//########################################################################### +//########################### Button type table ############################# +//########################################################################### +#define DARKBTN (char) 0 +#define AUTOBTN (char) 1 +#define MAPBTN (char) 2 + +static char + buttonType[LBE4ControlsManager::ButtonCount] = +{ + AUTOBTN, // ButtonAuxLowerLeft8=0x00 + AUTOBTN, // ButtonAuxLowerLeft7 + AUTOBTN, // ButtonAuxLowerLeft6, + AUTOBTN, // ButtonAuxLowerLeft5, + AUTOBTN, // ButtonAuxLowerLeft4, + AUTOBTN, // ButtonAuxLowerLeft3, + AUTOBTN, // ButtonAuxLowerLeft2, + AUTOBTN, // ButtonAuxLowerLeft1, + + AUTOBTN, // ButtonAuxLowerRight8=0x08 + AUTOBTN, // ButtonAuxLowerRight7, + AUTOBTN, // ButtonAuxLowerRight6, + AUTOBTN, // ButtonAuxLowerRight5, + AUTOBTN, // ButtonAuxLowerRight4, + AUTOBTN, // ButtonAuxLowerRight3, + AUTOBTN, // ButtonAuxLowerRight2, + AUTOBTN, // ButtonAuxLowerRight1, + + AUTOBTN, // ButtonSecondary1=0x10 + AUTOBTN, // ButtonSecondary2, + AUTOBTN, // ButtonSecondary3, + AUTOBTN, // ButtonSecondary4, + AUTOBTN, // ButtonSecondary5, + AUTOBTN, // ButtonSecondary6, + DARKBTN, // + DARKBTN, // + AUTOBTN, // ButtonSecondary7=0x18 + AUTOBTN, // ButtonSecondary8, + AUTOBTN, // ButtonSecondary9, + AUTOBTN, // ButtonSecondary10, + AUTOBTN, // ButtonSecondary11, + AUTOBTN, // ButtonSecondary12, + DARKBTN, // + DARKBTN, // + + AUTOBTN, // ButtonAuxUpperCenter8=0x20 + AUTOBTN, // ButtonAuxUpperCenter7, + AUTOBTN, // ButtonAuxUpperCenter6, + AUTOBTN, // ButtonAuxUpperCenter5, + AUTOBTN, // ButtonAuxUpperCenter4, + AUTOBTN, // ButtonAuxUpperCenter3, + AUTOBTN, // ButtonAuxUpperCenter2, + AUTOBTN, // ButtonAuxUpperCenter1, + + AUTOBTN, // ButtonAuxUpperLeft8=0x28 + AUTOBTN, // ButtonAuxUpperLeft7, + AUTOBTN, // ButtonAuxUpperLeft6, + AUTOBTN, // ButtonAuxUpperLeft5, + AUTOBTN, // ButtonAuxUpperLeft4, + AUTOBTN, // ButtonAuxUpperLeft3, + AUTOBTN, // ButtonAuxUpperLeft2, + AUTOBTN, // ButtonAuxUpperLeft1, + + AUTOBTN, // ButtonAuxUpperRight8=0x30 + AUTOBTN, // ButtonAuxUpperRight7, + AUTOBTN, // ButtonAuxUpperRight6, + AUTOBTN, // ButtonAuxUpperRight5, + AUTOBTN, // ButtonAuxUpperRight4, + AUTOBTN, // ButtonAuxUpperRight3, + AUTOBTN, // ButtonAuxUpperRight2, + AUTOBTN, // ButtonAuxUpperRight1, + + AUTOBTN, // ButtonPanic=0x38, + DARKBTN, // + DARKBTN, // + DARKBTN, // + DARKBTN, // ButtonDoor=0x3C, + DARKBTN, // + DARKBTN, // + + DARKBTN, // ButtonThrottle1=0x3F, + MAPBTN, // ButtonJoystickTrigger=0x40 + MAPBTN, // ButtonJoystickHatDown=0x41 + MAPBTN, // ButtonJoystickHatUp=0x42 + MAPBTN, // ButtonJoystickHatRight=0x43 + MAPBTN, // ButtonJoystickHatLeft=0x44 + MAPBTN, // ButtonJoystickPinky=0x45 + MAPBTN, // ButtonJoystickThumbLow=0x46 + MAPBTN // ButtonJoystickThumbHigh=0x47 +}; + +//########################################################################### +//############################ Joystick classes ############################# +//########################################################################### +Joystick::Joystick() +{ + NotationFile + init(initFileName); + + channel[0] = new FilterChannel( + &init, + FilterChannel::joystickXName, + 10,20,30 // bogus values in case file didn't previously exist + ); + Check(channel[0]); + + channel[1] = new FilterChannel( + &init, + FilterChannel::joystickYName, + 10,20,30 // bogus values in case file didn't previously exist + ); + Check(channel[1]); + + ButtonReleased = Joystick::NoButton; + ButtonPressed = Joystick::NoButton; + Check_Fpu(); +} + +Joystick::~Joystick() +{ + Check(this); + + NotationFile + init(initFileName); + + //------------------------------------------- + // Save DOS timestamp + //------------------------------------------- + time_t + dos_time; + time(&dos_time); + init.SetEntry("operator", "time", ctime(&dos_time)); + + for(int i=0; i<2; ++i) + { + Check(channel[i]); + delete channel[i]; + channel[i] = NULL; + } + Check_Fpu(); +} + +void + Joystick::BeginAlignment() +{ + Check(this); + for(int i=0; i<2; ++i) + { + Check(channel[i]); + channel[i]->BeginAlignment(); + } + Check_Fpu(); +} + +void + Joystick::EndAlignment() +{ + Check(this); + //------------------------------------------------------------ + // If channel was never adjusted, synthesize reasonable values + //------------------------------------------------------------ + NotationFile + init(initFileName); + EndAndSaveAlignment(&init); + + Check_Fpu(); +} + +void + Joystick::EndAndSaveAlignment(NotationFile *init_file) +{ + Check(this); + Check(init_file); + for(int i=0; i<2; ++i) + { + Check(channel[i]); + channel[i]->EndAlignment(init_file); + } + Check_Fpu(); +} + +void + Joystick::Update() +{ + Fail("Joystick::Update should not be called!\n"); +} + +void + Joystick::SetDeadBand(Scalar dead_band) +{ + Check(this); + for(int i=0; i<2; ++i) + { + Check(channel[i]); + channel[i]->SetDeadBand(dead_band); + } + Check_Fpu(); +} + +OrdinaryJoystick::OrdinaryJoystick() +{ + PC_Joystick_Mask = PCJ_Standard_Mask; + ExtendedValue.x = (Scalar) 0; + ExtendedValue.y = (Scalar) 0; + Check_Fpu(); +} + +OrdinaryJoystick::~OrdinaryJoystick() +{ + Check_Fpu(); +} + +void OrdinaryJoystick::Update() +{ + int newButtons, changedButtons; + + Check(this); + // + //--------------------------------------------------- + // Update analog values + //--------------------------------------------------- + // + PC_Joystick_Update(); + Check(channel[0]); + Value.x = channel[0]->Update(PC_Joystick1_Raw_X); + Check(channel[1]); + Value.y = channel[1]->Update(PC_Joystick1_Raw_Y); + // + //--------------------------------------------------- + // Handle button changes + //--------------------------------------------------- + // + newButtons = (int) PC_Joystick_Buttons; + changedButtons = newButtons ^ oldButtons; + + ButtonPressed = Joystick::NoButton; + ButtonReleased = Joystick::NoButton; + + if (changedButtons) + { + if (changedButtons & PCJ_Standard_Button1) + { + if (newButtons & PCJ_Standard_Button1) + { + ButtonPressed |= Joystick::Trigger; + } + else + { + ButtonReleased |= Joystick::Trigger; + } + } + if (changedButtons & PCJ_Standard_Button2) + { + if (newButtons & PCJ_Standard_Button2) + { + ButtonPressed |= Joystick::Thumb3; + } + else + { + ButtonReleased |= Joystick::Thumb3; + } + } + } + oldButtons = newButtons; + Check_Fpu(); +} + +Logical + Joystick::TestInstance() const +{ + return True; +} + +FlightStickPro::FlightStickPro() +{ + NotationFile + init(initFileName); + + throttle = new FilterChannel( + &init, + FilterChannel::throttleName, + 10,30 // bogus values in case file doesn't exist + ); + + Check(throttle); + + PC_Joystick_Mask = PCJ_FSP_Mask; + ExtendedValue.x = (Scalar) 0; + Check_Fpu(); +} + +FlightStickPro::~FlightStickPro() +{ + Check(this); + + NotationFile + init(initFileName); + //------------------------------------------- + // Save DOS timestamp + //------------------------------------------- + time_t + dos_time; + time(&dos_time); + init.SetEntry("operator", "time", ctime(&dos_time)); + + Check(throttle); + delete throttle; + throttle = NULL; + + Check_Fpu(); +} + +void FlightStickPro::Update() +{ + int newButtons; + + Check(this); + // + //--------------------------------------------------- + // Update analog values + //--------------------------------------------------- + // + PC_Joystick_Update(); + Check(channel[0]); + Value.x = channel[0]->Update(PC_Joystick1_Raw_X); + Check(channel[1]); + Value.y = channel[1]->Update(PC_Joystick1_Raw_Y); + + // Note inverted direction (below) for throttle + + Check(throttle); + ExtendedValue.y = 1.0 - throttle->Update(PC_Joystick2_Raw_Y); + // + //--------------------------------------------------- + // Handle button changes + //--------------------------------------------------- + // + newButtons = int (PC_Joystick_Buttons); + + ButtonPressed = Joystick::NoButton; + ButtonReleased = Joystick::NoButton; + + if (newButtons != oldButtons) + { + switch(oldButtons) + { + case PCJ_FSP_Up: ButtonReleased = Joystick::HatUp; break; + case PCJ_FSP_Down: ButtonReleased = Joystick::HatDown; break; + case PCJ_FSP_Left: ButtonReleased = Joystick::HatLeft; break; + case PCJ_FSP_Right: ButtonReleased = Joystick::HatRight; break; + case PCJ_FSP_Trigger: ButtonReleased = Joystick::Trigger; break; + case PCJ_FSP_LButton: ButtonReleased = Joystick::Thumb3; break; + case PCJ_FSP_RButton: ButtonReleased = Joystick::Thumb1; break; + case PCJ_FSP_CButton: ButtonReleased = Joystick::Thumb2; break; + } + switch(newButtons) + { + case PCJ_FSP_Up: ButtonPressed = Joystick::HatUp; break; + case PCJ_FSP_Down: ButtonPressed = Joystick::HatDown; break; + case PCJ_FSP_Left: ButtonPressed = Joystick::HatLeft; break; + case PCJ_FSP_Right: ButtonPressed = Joystick::HatRight; break; + case PCJ_FSP_Trigger: ButtonPressed = Joystick::Trigger; break; + case PCJ_FSP_LButton: ButtonPressed = Joystick::Thumb3; break; + case PCJ_FSP_RButton: ButtonPressed = Joystick::Thumb1; break; + case PCJ_FSP_CButton: ButtonPressed = Joystick::Thumb2; break; + } + oldButtons = newButtons; + } + Check_Fpu(); +} + +void + FlightStickPro::BeginAlignment() +{ + Check(this); + Check(throttle); + throttle->BeginAlignment(); + + Joystick::BeginAlignment(); + Check_Fpu(); +} + +void + FlightStickPro::EndAlignment() +{ + Check(this); + + NotationFile + init(initFileName); + + Check(throttle); + throttle->EndAlignment(&init); + + Joystick::EndAndSaveAlignment(&init); + + Check_Fpu(); +} + +ThrustMaster::ThrustMaster() +{ + PC_Joystick_Mask = PCJ_TM_Mask; + ExtendedValue.x = (Scalar) 0; + ExtendedValue.y = (Scalar) 0; + hatMax = 0; + prevHatState = 0; + Check_Fpu(); +} + +ThrustMaster::~ThrustMaster() +{ + Check_Fpu(); +} + +void ThrustMaster::Update() +{ + int newButtons, changedButtons; + int hat; + + Check(this); + // + //--------------------------------------------------- + // Update analog values + //--------------------------------------------------- + // + PC_Joystick_Update(); + Check(channel[0]); + Value.x = channel[0]->Update(PC_Joystick1_Raw_X); + Check(channel[1]); + Value.y = channel[1]->Update(PC_Joystick1_Raw_Y); + // + //--------------------------------------------------- + // Handle button changes + //--------------------------------------------------- + // + ButtonPressed = Joystick::NoButton; + ButtonReleased = Joystick::NoButton; + + newButtons = (int) PC_Joystick_Buttons; + changedButtons = newButtons ^ oldButtons; + + if (changedButtons) + { + if (changedButtons & PCJ_TM_Trigger) + { + if (newButtons & PCJ_TM_Trigger) + { + ButtonPressed |= Joystick::Trigger; + } + else + { + ButtonReleased |= Joystick::Trigger; + } + } + if (changedButtons & PCJ_TM_ThumbHigh) + { + if (newButtons & PCJ_TM_ThumbHigh) + { + ButtonPressed |= Joystick::Thumb3; + } + else + { + ButtonReleased |= Joystick::Thumb3; + } + } + if (changedButtons & PCJ_TM_ThumbMid) + { + if (newButtons & PCJ_TM_ThumbMid) + { + ButtonPressed |= Joystick::Thumb2; + } + else + { + ButtonReleased |= Joystick::Thumb2; + } + } + if (changedButtons & PCJ_TM_ThumbLow) + { + if (newButtons & PCJ_TM_ThumbLow) + { + ButtonPressed |= Joystick::Thumb1; + } + else + { + ButtonReleased |= Joystick::Thumb1; + } + } + oldButtons = newButtons; + } + // + //--------------------------------------------------- + // Handle "hat" changes + //--------------------------------------------------- + // + hat = PC_Joystick2_Raw_Y; + if (hatMax < hat) { hatMax = hat; } + if (hat > ((hatMax*7)>>3)) // Unpressed, near max. + { + newButtons = 0; + } + else if (hat > ((hatMax*5)>>3)) // HatLeft is about 3/4 max + { + newButtons = Joystick::HatLeft; + } + else if (hat > ((hatMax*3)>>3)) // HatDown is about 1/2 max + { + newButtons = Joystick::HatDown; + } + else if (hat > (hatMax>>3)) // HatRight is about 1/4 max + { + newButtons = Joystick::HatRight; + } + else // Must be hatUp (near zero) + { + newButtons = Joystick::HatUp; + } + if (newButtons != prevHatState) + { + ButtonReleased |= prevHatState; + ButtonPressed |= newButtons; + prevHatState = newButtons; + } + Check_Fpu(); +} + + +//######################################################################### +//########################## LBE4ControlsManager ########################## +//######################################################################### + +//--------------------------------------------------------------------------- +// Class derivation +//--------------------------------------------------------------------------- +Derivation + LBE4ControlsManager::ClassDerivations( + ControlsManager::ClassDerivations,"L4ControlsManager"); + +//--------------------------------------------------------------------------- +// Message support +//--------------------------------------------------------------------------- +//const Receiver::HandlerEntry +// LBE4ControlsManager::MessageHandlerEntries[]= +//{ +// MESSAGE_ENTRY(LBE4ControlsManager,BeginCalibration), +// MESSAGE_ENTRY(LBE4ControlsManager,EndCalibration) +//}; +// +//Receiver::MessageHandlerSet +// LBE4ControlsManager::MessageHandlers( +// ELEMENTS(LBE4ControlsManager::MessageHandlerEntries), +// LBE4ControlsManager::MessageHandlerEntries, +// ControlsManager::MessageHandlers +// ); +//--------------------------------------------------------------------------- +// Shared data +//--------------------------------------------------------------------------- +LBE4ControlsManager::SharedData + LBE4ControlsManager::DefaultData( + LBE4ControlsManager::ClassDerivations, + LBE4ControlsManager::MessageHandlers + ); +// +//############################################################################ +// LBE4ControlsManager +// +// Creator method +//---------------------------------------------------------------------------- +// Enter: virtualDataPtr +//############################################################################ +// +LBE4ControlsManager::LBE4ControlsManager(): + ControlsManager(L4ControlsManagerClassID, DefaultData) +{ + Check_Pointer(this); + // + //------------------------------------------------------------------------- + // configure + //------------------------------------------------------------------------- + // + flags.mouseExists = 0; + flags.keyboardExists = 0; + flags.joystickExists = 0; + flags.RIOExists = 0; + + virtualJoystickX = 0; + virtualJoystickY = 0; + + lastJoystickUpdate = 0L; + joystickType = LBE4ControlsManager::none; + + mousePointer = NULL; + joystickPointer = NULL; + rioPointer = NULL; + lastRioRequest = 0L; + primaryControlType = LBE4ControlsManager::None; + + char + *controlString(getenv("L4CONTROLS")); + + if (controlString != NULL) + { + // + //------------------------------------------------- + // parse environment variable, build configuration + //------------------------------------------------- + // + char + temp[128]; + char + *dest; + char + c; + int + noMore(0); + + do + { + // + // Get the next token + // Can't use strtok(), because RIO::RIO uses it, + // and it's not re-entrant. + // + + dest = temp; + if (noMore) + { + *dest = '\0'; + } + else + { + do + { + switch(c=*controlString++) + { + case '\0': + case '\n': + noMore = 1; + // deliberately falls through into next case + + case ',': + case ';': + c = '\0'; + // deliberately falls through into default case + + default: + *dest++=c; + break; + } + } + while (c != '\0'); + } + + if ( + (strcmpi(temp, "RIO") == 0)|| + (strcmpi(temp, "RIO:COM1") == 0) + ) + { + rioPointer = new RIO(RIO_COM1); + Check(rioPointer); + Register_Object(rioPointer); + flags.RIOExists = 1; + primaryControlType = LBE4ControlsManager::PrimaryRIO; + } + else if (strcmpi(temp, "RIO:COM2") == 0) + { + rioPointer = new RIO(RIO_COM2); + Check(rioPointer); + Register_Object(rioPointer); + flags.RIOExists = 1; + primaryControlType = LBE4ControlsManager::PrimaryRIO; + } + else if (strcmpi(temp, "KEYBOARD") == 0) + { + flags.keyboardExists = 1; + } + else if (strcmpi(temp, "MOUSE") == 0) + { + if (!flags.mouseExists) + { + flags.mouseExists = 1; + mousePointer = new Mouse; + Check(mousePointer); + Register_Object(mousePointer); + if (mousePointer->Errors) + { + Unregister_Object(mousePointer); + delete mousePointer; + mousePointer = NULL; + flags.mouseExists = 0; + } + } + } + else if (strcmpi(temp, "JOYSTICK") == 0) + { + flags.joystickExists = 1; + joystickType = LBE4ControlsManager::ordinary; + joystickPointer = new OrdinaryJoystick(); + Register_Object(joystickPointer); + primaryControlType = LBE4ControlsManager::PrimaryGenericJoystick; + } + else if (strcmpi(temp, "FLIGHTSTICKPRO") == 0) + { + flags.joystickExists = 1; + joystickType = LBE4ControlsManager::flightstickPro; + joystickPointer = new FlightStickPro(); + Register_Object(joystickPointer); + primaryControlType = LBE4ControlsManager::PrimaryFlightStickPro; + } + else if (strcmpi(temp, "THRUSTMASTER") == 0) + { + flags.joystickExists = 1; + joystickType = LBE4ControlsManager::thrustMaster; + joystickPointer = new ThrustMaster(); + Register_Object(joystickPointer); + primaryControlType = LBE4ControlsManager::PrimaryThrustMaster; + } + } + while (temp[0] != '\0'); + } + + //-------------------------------------------------- + // Clear all lamps (and reset analog I/O) + //-------------------------------------------------- + if (rioPointer != NULL) + { + Check(rioPointer); + rioPointer->GeneralReset(); + } + //-------------------------------------------------- + // Get mode mask for updating + //-------------------------------------------------- + Check(application); + Check(application->GetModeManager()); + ModeMask + mode_mask = application->GetModeManager()->GetModeMask(); + //-------------------------------------------------- + // Initialize scalar group + //-------------------------------------------------- + { + int + i; + ControlsScalar + initial_scalar = 0.0; + + for(i=0; iRewind(); + RIOStreamEvent + *start = (RIOStreamEvent*)rioStream->GetPointer(); + + Unregister_Object(rioStream); + delete rioStream; + + Unregister_Pointer(start); + delete[] start; + + rioStream = NULL; + streamEnabled = False; + } + + //-------------------------------------------------- + // Delete mouse + //-------------------------------------------------- + if (mousePointer != NULL) + { + Check(mousePointer); + Unregister_Object(mousePointer); + delete mousePointer; + mousePointer = NULL; + } + //-------------------------------------------------- + // Delete joystick + //-------------------------------------------------- + if (joystickPointer != NULL) + { + Check(joystickPointer); + Unregister_Object(joystickPointer); + delete joystickPointer; + joystickPointer = NULL; + } + //-------------------------------------------------- + // Delete string manager temporary groups + //-------------------------------------------------- + ExitControlsMode(); + //-------------------------------------------------- + // Delete RIO AFTER buttons! + // ...the 'autoManager' button class sends + // lamp commands when deleted. + //-------------------------------------------------- + if (rioPointer != NULL) + { + Check(rioPointer); + Unregister_Object(rioPointer); + delete rioPointer; + rioPointer = NULL; + } + + Check_Fpu(); +} + +// +//############################################################################# +// LocalShutdown +//############################################################################# +// +void + LBE4ControlsManager::LocalShutdown() +{ + Check_Pointer(this); + + if (rioPointer != NULL) + { + Check(rioPointer); + Unregister_Object(rioPointer); + delete rioPointer; + + rioPointer = NULL; + } + + ControlsManager::LocalShutdown(); + Check_Fpu(); +} + +// +//############################################################################ +// Remove +// +// Remove all controlsInstance records bearing the given ID +//############################################################################ +// +void + LBE4ControlsManager::Remove(ModeMask mode_mask) +{ + int i; + + Check(this); + for(i=0; i= 0); + Verify(lamp_number < LBE4ControlsManager::LampCount); + + rioPointer->SetLamp(lamp_number, (RIO::LampState) state); + } + Check_Fpu(); +} + +// +//############################################################################ +// Execute +// +// Execution method +//############################################################################ +// +void + LBE4ControlsManager::Execute() +{ + ControlsJoystick virtual_joystick; + ControlsKey keyValue; + ControlsMouse mouseValue; + Logical new_RIO_values(False); + + Check(this); + //-------------------------------------------------- + // Get mode mask for updating + //-------------------------------------------------- + Check(application); + Check(application->GetModeManager()); + ModeMask + mode_mask = application->GetModeManager()->GetModeMask(); + //------------------------------------------------------------------------- + // Process operator control mode + //------------------------------------------------------------------------- + // ManageControlsMode(); + + //------------------------------------------------------------------------- + // Process RIO + //------------------------------------------------------------------------- + if (flags.RIOExists) + { + Check(rioPointer); + + RIO::RIOEvent rio_event; + // + //------------------------------------ + // Request analog update + // (held down to 5 Hz unless reply + // is received: reply allows another + // request to be sent next invocation) + //------------------------------------ + // + if (!playbackMode) + { + Scalar + delta_t(Now() - lastRioRequest); + Scalar + limit; + static Logical + first_time = True; + + if (application->GetApplicationState() == Application::RunningMission) + { + limit = 15.0; // 0.2 + } + else + { + limit = 15.0; + } + + if (first_time) + { + first_time = False; + } + else + { + if (delta_t >= limit) // 5 Hz minimum rate, in case of no reply + { + //------------------------- + // Debugging aid + //------------------------- + long + time_in_ticks; + + time_in_ticks = lastRioRequest; + if (time_in_ticks != 0L) + { + DEBUG_STREAM << + "LBE4ControlsManager::Execute, lost RIO analog request\n"; + + extern Logical + iThinkIRQIsOn; + + extern int + pcspakCharactersSent; + + + DEBUG_STREAM << + "iThinkIRQIsOn =" << iThinkIRQIsOn << + ", actual state =" << PCSPAKIRQState() << + ", characters sent =" << pcspakCharactersSent << "\n"; + } + + rioPointer->RequestAnalogUpdate(); + lastRioRequest = Now(); + } + //------------------------- + // Debugging aid + //------------------------- + else if (delta_t < 0.0) + { + DEBUG_STREAM << + "LBE4ControlsManager::Execute, delta_t went negative (" << + delta_t << ")\n"; + + rioPointer->RequestAnalogUpdate(); + lastRioRequest = Now(); + } + } + } + + // + //------------------------------------ + // Process events + //------------------------------------ + // + while (GetNextRIOEvent(&rio_event)) + { + ProcessRIOEvent(rio_event, &new_RIO_values); + } + } + + // + //------------------------------------------------------------------------- + // Read physical joystick inputs, filter the values + //------------------------------------------------------------------------- + // + if (flags.joystickExists) + { + Scalar delta_t(((long)Now())-lastJoystickUpdate); + + if (delta_t > .05) + { + Check(joystickPointer); + joystickPointer->Update(); + joystickPointer->Value.x = -joystickPointer->Value.x; // HACK!!! + + lastJoystickUpdate = Now(); + } + } + + // + //------------------------------------------------------------------------- + // Read physical mouse inputs, generate virtual joystick values + //------------------------------------------------------------------------- + // + if (flags.mouseExists) + { + Check(mousePointer); + mousePointer->ReadCounters(&mouseValue.x, &mouseValue.y); + + virtualJoystickX += mouseValue.x; + virtualJoystickY += mouseValue.y; + + +# define MAXEXTENT 2048 // This is a guess. We'll have to try it and see. + + if (virtualJoystickX > MAXEXTENT) { virtualJoystickX = MAXEXTENT; } + if (virtualJoystickX < -MAXEXTENT) { virtualJoystickX = -MAXEXTENT; } + virtual_joystick.x = (Scalar) virtualJoystickX / (Scalar) MAXEXTENT; + + if (virtualJoystickY > MAXEXTENT) { virtualJoystickY = MAXEXTENT; } + if (virtualJoystickY < -MAXEXTENT) { virtualJoystickY = -MAXEXTENT; } + virtual_joystick.y = (Scalar) virtualJoystickY / (Scalar) MAXEXTENT; + } + + // + //------------------------------------------------------------------------- + // Update the scalar mapping groups using the analog values + //------------------------------------------------------------------------- + // + if (flags.RIOExists && new_RIO_values) + { + Check(rioPointer); + + Check(&scalarGroup[LBE4ControlsManager::ScalarThrottle]); + scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( + &rioPointer->Throttle, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarLeftPedal]); + scalarGroup[LBE4ControlsManager::ScalarLeftPedal].Update( + &rioPointer->LeftPedal, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarRightPedal]); + scalarGroup[LBE4ControlsManager::ScalarRightPedal].Update( + &rioPointer->RightPedal, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickX]); + scalarGroup[LBE4ControlsManager::ScalarJoystickX].Update( + &rioPointer->JoystickX, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickY]); + scalarGroup[LBE4ControlsManager::ScalarJoystickY].Update( + &rioPointer->JoystickY, mode_mask + ); + } + else if (flags.joystickExists) + { + Check(&scalarGroup[LBE4ControlsManager::ScalarThrottle]); + scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( + &joystickPointer->ExtendedValue.y, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickX]); + scalarGroup[LBE4ControlsManager::ScalarJoystickX].Update( + &joystickPointer->Value.x, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickY]); + scalarGroup[LBE4ControlsManager::ScalarJoystickY].Update( + &joystickPointer->Value.y, mode_mask + ); + } + + if (flags.mouseExists) + { + Check(&scalarGroup[LBE4ControlsManager::ScalarMouseX]); + scalarGroup[LBE4ControlsManager::ScalarMouseX].Update( + &virtual_joystick.x, mode_mask + ); + Check(&scalarGroup[LBE4ControlsManager::ScalarMouseY]); + scalarGroup[LBE4ControlsManager::ScalarMouseY].Update( + &virtual_joystick.y, mode_mask + ); + } + + // + //------------------------------------------------------------------------- + // Update the joystick mapping groups using the analog values + //------------------------------------------------------------------------- + // + if (flags.RIOExists && new_RIO_values) + { + Check(rioPointer); + + ControlsJoystick + stick; + + stick.x = rioPointer->JoystickX; + stick.y = rioPointer->JoystickY; + + Check(&joystickGroup[LBE4ControlsManager::JoystickPhysical]); + joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( + &stick, mode_mask + ); + } + else if (flags.joystickExists) + { + Check(&joystickGroup[LBE4ControlsManager::JoystickPhysical]); + joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( + &joystickPointer->Value, mode_mask + ); + } + + if (flags.mouseExists) + { + Check(&joystickGroup[LBE4ControlsManager::JoystickVirtual]); + joystickGroup[LBE4ControlsManager::JoystickVirtual].Update( + &virtual_joystick, mode_mask + ); + } + + // + //------------------------------------------------------------------------- + // Update the PC keyboard mapping group + //------------------------------------------------------------------------- + // + if (flags.keyboardExists) + { + keyValue = (ControlsKey) PC_Keyboard_Read(); + if (keyValue) + { + Check(&keyboardGroup[KeyboardPC]); + keyboardGroup[KeyboardPC].ForceUpdate(&keyValue, mode_mask); + + Check(&stringManager); + stringManager.Update(KeyboardPC, keyValue); + } + } + + // + //------------------------------------------------------------------------- + // Update the button mapping groups + //------------------------------------------------------------------------- + // + + // + //-------------------------- + // Joystick buttons + //-------------------------- + // + if (flags.joystickExists) + { + int i; + ControlsButton b; + + Check(joystickPointer); + + i = joystickPointer->ButtonReleased; + if(i != Joystick::NoButton) + { + if (i & Joystick::Trigger) + { + b = - ButtonJoystickTrigger - 1; + buttonGroup[ButtonJoystickTrigger].Update(&b, mode_mask); + } + if (i & Joystick::Thumb1) + { + b = - ButtonJoystickPinky - 1; + buttonGroup[ButtonJoystickPinky].Update(&b, mode_mask); + } + if (i & Joystick::Thumb2) + { + b = - ButtonJoystickThumbLow - 1; + buttonGroup[ButtonJoystickThumbLow].Update(&b, mode_mask); + } + if (i & Joystick::Thumb3) + { + b = - ButtonJoystickThumbHigh - 1; + buttonGroup[ButtonJoystickThumbHigh].Update(&b, mode_mask); + } + if (i & Joystick::HatUp) + { + b = - ButtonJoystickHatUp - 1; + buttonGroup[ButtonJoystickHatUp].Update(&b, mode_mask); + } + if (i & Joystick::HatDown) + { + b = - ButtonJoystickHatDown - 1; + buttonGroup[ButtonJoystickHatDown].Update(&b, mode_mask); + } + if (i & Joystick::HatLeft) + { + b = - ButtonJoystickHatLeft - 1; + buttonGroup[ButtonJoystickHatLeft].Update(&b, mode_mask); + } + if (i & Joystick::HatRight) + { + b = - ButtonJoystickHatRight - 1; + buttonGroup[ButtonJoystickHatRight].Update(&b, mode_mask); + } + } + + i = joystickPointer->ButtonPressed; + if(i != Joystick::NoButton) + { + if (i & Joystick::Trigger) + { + b = ButtonJoystickTrigger + 1; + buttonGroup[ButtonJoystickTrigger].Update(&b, mode_mask); + } + if (i & Joystick::Thumb1) + { + b = ButtonJoystickPinky + 1; + buttonGroup[ButtonJoystickPinky].Update(&b, mode_mask); + } + if (i & Joystick::Thumb2) + { + b = ButtonJoystickThumbLow + 1; + buttonGroup[ButtonJoystickThumbLow].Update(&b, mode_mask); + } + if (i & Joystick::Thumb3) + { + b = ButtonJoystickThumbHigh + 1; + buttonGroup[ButtonJoystickThumbHigh].Update(&b, mode_mask); + } + if (i & Joystick::HatUp) + { + b = ButtonJoystickHatUp + 1; + buttonGroup[ButtonJoystickHatUp].Update(&b, mode_mask); + } + if (i & Joystick::HatDown) + { + b = ButtonJoystickHatDown + 1; + buttonGroup[ButtonJoystickHatDown].Update(&b, mode_mask); + } + if (i & Joystick::HatLeft) + { + b = ButtonJoystickHatLeft + 1; + buttonGroup[ButtonJoystickHatLeft].Update(&b, mode_mask); + } + if (i & Joystick::HatRight) + { + b = ButtonJoystickHatRight + 1; + buttonGroup[ButtonJoystickHatRight].Update(&b, mode_mask); + } + } + } + + // + //-------------------------- + // Mouse buttons + //-------------------------- + // + if (flags.mouseExists) + { + int i, j, k; + ControlsButton b; + + k = mousePointer->ButtonCount; + + for( + i=0,j=LBE4ControlsManager::ButtonMouseLeft; + iButtonPressed(i)) + { + b = (ControlsButton) (j+1); + buttonGroup[j].Update(&b, mode_mask); + } + + if (mousePointer->ButtonReleased(i)) + { + b = (ControlsButton) (-j-1); + buttonGroup[j].Update(&b, mode_mask); + } + } + // + //------------------------------------------------------------------------- + // Update the mouse mapping group + //------------------------------------------------------------------------- + // + mouseGroup[0].Update(&mouseValue, mode_mask); + } + + // Tell("LBE4ControlsManager::Execute ends\n" << flush); + Check_Fpu(); +} + +// +//############################################################################ +// BeginAlignJoystick +// +// Start alignment process for joystick and analog inputs +//############################################################################ +// +void + LBE4ControlsManager::BeginAlignJoystick() +{ + Check(this); + + if (flags.joystickExists) + { + Check(joystickPointer); + joystickPointer->BeginAlignment(); + } + Check_Fpu(); +} + +// +//############################################################################ +// EndAlignJoystick +// +// End alignment process for joystick and analog inputs +//############################################################################ +// +void + LBE4ControlsManager::EndAlignJoystick() +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->ForceCenterJoystick(); + } + + if (flags.joystickExists) + { + Check(joystickPointer); + joystickPointer->EndAlignment(); + } + Check_Fpu(); +} + +void + LBE4ControlsManager::CenterRIOJoystick() +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->ForceCenterJoystick(); + } + + Check_Fpu(); +} + +void + LBE4ControlsManager::SetJoystickDeadBand(Scalar dead_band) +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->SetJoystickDeadBand(dead_band); + } + + if (flags.joystickExists) + { + Check(joystickPointer); + joystickPointer->SetDeadBand(dead_band); + } + + Check_Fpu(); +} + +void + LBE4ControlsManager::SetThrottleDeadBand(Scalar dead_band) +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->SetThrottleDeadBand(dead_band); + } + Check_Fpu(); +} + +void + LBE4ControlsManager::SetPedalsDeadBand(Scalar dead_band) +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->SetPedalsDeadBand(dead_band); + } + Check_Fpu(); +} + +const char* + LBE4ControlsManager::GetLampName(int lamp_number) +{ + const char + *lamp_name[] = + { + "AuxLowerRight8", + "AuxLowerRight7", + "AuxLowerRight6", + "AuxLowerRight5", + "AuxLowerRight4", + "AuxLowerRight3", + "AuxLowerRight2", + "AuxLowerRight1", + "AuxLowerLeft8", + "AuxLowerLeft7", + "AuxLowerLeft6", + "AuxLowerLeft5", + "AuxLowerLeft4", + "AuxLowerLeft3", + "AuxLowerLeft2", + "AuxLowerLeft1", + "Secondary1", //=0x10 + "Secondary2", + "Secondary3", + "Secondary4", + "Secondary5", + "Secondary6", + "TeslaRelay3", + "undefined_0x17", + "Secondary7", //=0x18 + "Secondary8", + "Secondary9", + "Secondary10", + "Secondary11", + "Secondary12", + "TeslaRelay1", + "TeslaRelay2", + "AuxUpperCenter8", //=0x20 + "AuxUpperCenter7", + "AuxUpperCenter6", + "AuxUpperCenter5", + "AuxUpperCenter4", + "AuxUpperCenter3", + "AuxUpperCenter2", + "AuxUpperCenter1", + "AuxUpperLeft8", //=0x28 + "AuxUpperLeft7", + "AuxUpperLeft6", + "AuxUpperLeft5", + "AuxUpperLeft4", + "AuxUpperLeft3", + "AuxUpperLeft2", + "AuxUpperLeft1", + "AuxUpperRight8", //=0x30 + "AuxUpperRight7", + "AuxUpperRight6", + "AuxUpperRight5", + "AuxUpperRight4", + "AuxUpperRight3", + "AuxUpperRight2", + "AuxUpperRight1", + "PanicButton", //=0x38 + "IcomAmpEnableRelay",//=0x39 + "IcomIncRelay", //=0x3A + "IcomPTTRelay", //=0x03B + "IcomDecRelay", //=0x3C + "undefined_0x3D", //=0x3D unimplemented convenience lamp + "FloorEntry" //=0x3E + }; + + if (lamp_number >= LampCount) + { + return "overrange"; + } + else if (lamp_number < 0) + { + return "underrange"; + } + else + { + return lamp_name[lamp_number]; + } +} + + +#define ID_ENTRY(name,group)\ + { #name , LBE4ControlsManager::##group, LBE4ControlsManager::##name } + +struct { + const char* controlName; + Enumeration + controlsGroup, + controlsElement; +} + Control_IDs[]= +{ + //----------------------------------------------- + // Throttle + //----------------------------------------------- + ID_ENTRY(ScalarThrottle,ScalarGroup), + ID_ENTRY(ButtonThrottle1,ButtonGroup), + + //----------------------------------------------- + // Pedals + //----------------------------------------------- + ID_ENTRY(ScalarLeftPedal,ScalarGroup), + ID_ENTRY(ScalarRightPedal,ScalarGroup), + + //----------------------------------------------- + // Joystick + //----------------------------------------------- + ID_ENTRY(JoystickPhysical,JoystickGroup), + ID_ENTRY(ButtonJoystickHatUp,ButtonGroup), + ID_ENTRY(ButtonJoystickHatDown,ButtonGroup), + ID_ENTRY(ButtonJoystickHatLeft,ButtonGroup), + ID_ENTRY(ButtonJoystickHatRight,ButtonGroup), + ID_ENTRY(ButtonJoystickTrigger,ButtonGroup), + ID_ENTRY(ButtonJoystickThumbHigh,ButtonGroup), + ID_ENTRY(ButtonJoystickThumbLow,ButtonGroup), + ID_ENTRY(ButtonJoystickPinky,ButtonGroup), + + //----------------------------------------------- + // Secondary buttons + //----------------------------------------------- + ID_ENTRY(ButtonSecondary1,ButtonGroup), + ID_ENTRY(ButtonSecondary2,ButtonGroup), + ID_ENTRY(ButtonSecondary3,ButtonGroup), + ID_ENTRY(ButtonSecondary4,ButtonGroup), + ID_ENTRY(ButtonSecondary5,ButtonGroup), + ID_ENTRY(ButtonSecondary6,ButtonGroup), + ID_ENTRY(ButtonSecondary7,ButtonGroup), + ID_ENTRY(ButtonSecondary8,ButtonGroup), + ID_ENTRY(ButtonSecondary9,ButtonGroup), + ID_ENTRY(ButtonSecondary10,ButtonGroup), + ID_ENTRY(ButtonSecondary11,ButtonGroup), + ID_ENTRY(ButtonSecondary12,ButtonGroup), + + //----------------------------------------------- + // Upper left auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxUpperLeft8,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft7,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft6,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft5,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft4,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft3,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft2,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft1,ButtonGroup), + + //----------------------------------------------- + // Center auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxUpperCenter8,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter7,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter6,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter5,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter4,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter3,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter2,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter1,ButtonGroup), + + //----------------------------------------------- + // Upper right auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxUpperRight8,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight7,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight6,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight5,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight4,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight3,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight2,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight1,ButtonGroup), + + //----------------------------------------------- + // Lower left auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxLowerLeft8,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft7,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft6,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft5,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft4,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft3,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft2,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft1,ButtonGroup), + + //----------------------------------------------- + // Lower right auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxLowerRight8,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight7,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight6,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight5,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight4,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight3,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight2,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight1,ButtonGroup), + + //----------------------------------------------- + // Miscellaneous buttons + //----------------------------------------------- + ID_ENTRY(ButtonPanic,ButtonGroup), + ID_ENTRY(ButtonDoor,ButtonGroup) +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + LBE4ControlsManager::SetControlMappingID( + const char *control_name, + ControlsMapping *mapping + ) +{ + Check_Pointer(control_name); + Check_Pointer(mapping); + + int i; + for (i=0; icontrolsGroup = Control_IDs[i].controlsGroup; + mapping->controlsElement = Control_IDs[i].controlsElement; + break; + } + } + Check_Fpu(); + return i < ELEMENTS(Control_IDs); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Lamp * + LBE4ControlsManager::MakeLinkedLamp( + int element, + ModeMask mode_mask + ) +{ + Check(this); + Check(application); + + if (application->GetGaugeRenderer() == NULL) + { + return NULL; + } + else + { + Check(application->GetGaugeRenderer()); + + //------------------------------------------ + // Create the lamp + //------------------------------------------ + L4LampManager + *lamp_manager = (L4LampManager *) application-> + GetGaugeRenderer()->GetLampManager(); + Check(lamp_manager); + + Lamp + *lamp = new L4Lamp( + element, + mode_mask, + lamp_manager + ); + Register_Object(lamp); + //------------------------------------------ + // Add button mapping to lamp + //------------------------------------------ + buttonGroup[element].Add( + mode_mask, + &((L4Lamp *)lamp)->automaticValue, + lamp + ); + + Check_Fpu(); + return lamp; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::CreateStreamedMappings( + Entity *player, + const int *control_mappings + ) +{ + Check(this); + Check_Pointer(control_mappings); + + int + controls_count = *control_mappings; + ++control_mappings; + + ControlsMapping + *mapping = (ControlsMapping*)control_mappings; + Simulation + *subsystem; + void + *attribute; + + for (int i=0; iGetSimulation(mapping->subsystemID); + Verify(subsystem); + + // + //--------------------------- + // Handle the direct mappings + //--------------------------- + // + int + element = mapping->controlsElement; + ModeMask + mode_mask = mapping->modeMask; + + if (mapping->mappingType == ControlsMapping::DirectMapping) + { + attribute = subsystem->GetAttributePointer(mapping->attributeID); + switch (mapping->controlsGroup) + { + case ScalarGroup: + scalarGroup[element].Add( + mode_mask, + (ControlsScalar*)attribute, + subsystem + ); + break; + case JoystickGroup: + joystickGroup[element].Add( + mode_mask, + (ControlsJoystick*)attribute, + subsystem + ); + break; + case ButtonGroup: + //---------------------------------------------- + // Add button + //---------------------------------------------- + buttonGroup[element].Add( + mode_mask, + (ControlsButton*)attribute, + subsystem + ); + //---------------------------------------------- + // Create associated lamp + //---------------------------------------------- + if(buttonType[element] == AUTOBTN) + { +# if DEBUG_LEVEL > 0 + Lamp * + lamp = +# endif + MakeLinkedLamp(element, mode_mask); + +# if DEBUG_LEVEL > 0 + if (lamp != NULL) + { + Check(lamp); + } +# endif + } + break; + default: + Fail("Unknown mapping group!\n"); + break; + } + } + + // + //-------------------------------------------------- + // Otherwise, it is an event mapping, so set that up + //-------------------------------------------------- + // + else if (mapping->mappingType == ControlsMapping::EventMapping) + { + Receiver::MessageID + msg_id = mapping->messageID; + + switch (mapping->controlsGroup) + { + case ScalarGroup: + scalarGroup[element].Add(mode_mask,subsystem,msg_id,subsystem); + break; + case JoystickGroup: + joystickGroup[element].Add(mode_mask,subsystem,msg_id,subsystem); + break; + case ButtonGroup: + //---------------------------------------------- + // Add button + //---------------------------------------------- + buttonGroup[element].Add( + mode_mask, + subsystem, + msg_id, + subsystem + ); + //---------------------------------------------- + // Create associated lamp + //---------------------------------------------- + if(buttonType[element] == AUTOBTN) + { +# if DEBUG_LEVEL > 0 + Lamp * + lamp = +# endif + MakeLinkedLamp(element, mode_mask); + +# if DEBUG_LEVEL > 0 + if (lamp != NULL) + { + Check(lamp); + } +# endif + } + break; + default: + Fail("Unknown mapping group!\n"); + break; + } + } + else + { + Fail("Unknown mapping type!\n"); + } + mapping = (ControlsMapping*)((char*)mapping + sizeof(ControlsMapping)); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::EnterControlsMode( + L4ControlsMode new_mode, + Scalar time_until_exit, + Receiver::MessageID message_on_exit + ) +{ + Check(this); + l4ControlsMode = new_mode; + + exitModeTime = ((Scalar) Now()) + time_until_exit; + exitMessageID = message_on_exit; + + SetLamp(LampPanic, RIO::flashFast+RIO::state1Off+RIO::state2Bright); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::ExitControlsMode() +{ + Check(this); + + l4ControlsMode = normalMode; + + int + i; + + for(i=0; i= exitModeTime) + { + Receiver::Message + message(exitMessageID, sizeof(Receiver__Message)); + + Dispatch(&message); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LBE4ControlsManager::TestInstance() const +{ + Verify(IsDerivedFrom(ClassDerivations)); + return ControlsManager::TestInstance(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LBE4ControlsManager::AnalogHasChanged() +{ + Check(this); + + Logical + result = False; + + if (rioPointer != NULL) + { + Check(rioPointer); + + result = (rioPointer->Throttle != previousThrottle); + result |= (rioPointer->LeftPedal != previousPedalLeft); + result |= (rioPointer->RightPedal != previousPedalRight); + result |= (rioPointer->JoystickX != previousJoystickX); + result |= (rioPointer->JoystickY != previousJoystickY); + + if (result) + { + previousThrottle = rioPointer->Throttle; + previousPedalLeft = rioPointer->LeftPedal; + previousPedalRight = rioPointer->RightPedal; + previousJoystickX = rioPointer->JoystickX; + previousJoystickY = rioPointer->JoystickY; + } + } + + Check_Fpu(); + return result; +} + +Logical + LBE4ControlsManager::GetNextRIOEvent(RIO::RIOEvent *rio_event) +{ + // + //------------------------------------------------- + // If we aren't in playback mode, read the real RIO + //------------------------------------------------- + // + if (!playbackMode) + { + Logical + result = rioPointer->GetNextEvent(rio_event); + //---------------------------------------------------------------------- + // If the RIO stream exists, and a rio event was added, + // store this event in the rioStream + //---------------------------------------------------------------------- + if (result && streamEnabled) + { + Check(rioStream); + if (rioStream->GetBytesRemaining() >= sizeof(RIOStreamEvent)) + { + Check(rioStream); + RIOStreamEvent + *event = (RIOStreamEvent*)rioStream->GetPointer(); + Check_Pointer(event); + + event->timeStamp.ticks = Now().ticks - streamStart.ticks; + + if (rio_event->Type == RIO::AnalogEvent) + { + if (AnalogHasChanged()) + { +DEBUG_STREAM << "AnalogEvent at" << event->timeStamp.ticks << "\n"; +DEBUG_STREAM << "Pointer=" << hex << event << dec << "\n"; + //---------------------------- + // Set the event type + //---------------------------- + event->eventType = analog; + //---------------------------- + // Get the analog state + //---------------------------- + event->data.analog.throttle = rioPointer->Throttle; + event->data.analog.pedalLeft = rioPointer->LeftPedal; + event->data.analog.pedalRight = rioPointer->RightPedal; + event->data.analog.joystickX = rioPointer->JoystickX; + event->data.analog.joystickY = rioPointer->JoystickY; + //---------------------------- + // Save the event + //---------------------------- + rioStream->AdvancePointer(sizeof(RIOStreamEvent)); + } + } + else + { +DEBUG_STREAM << "DigitalEvent at" << event->timeStamp.ticks << "\n"; +DEBUG_STREAM << "Pointer=" << hex << event << dec << "\n"; + //---------------------------- + // Set the event type + //---------------------------- + event->eventType = digital; + //---------------------------- + // Save the event + //---------------------------- + event->data.rioEvent = *rio_event; + rioStream->AdvancePointer(sizeof(RIOStreamEvent)); + } + } + } + return result; + } + + // + //---------------------------------------------------------------------- + // Otherwise, we are in playback mode, so get the next record out of the + // memory block + //---------------------------------------------------------------------- + // + else if (streamEnabled) + { + Check(rioStream); + if (rioStream->GetBytesRemaining() >= sizeof(RIOStreamEvent)) + { + RIOStreamEvent + *event = (RIOStreamEvent*)rioStream->GetPointer(); + + Check_Pointer(event); + Time + now; + + now.ticks = Now().ticks - streamStart.ticks; + + if (event->timeStamp.ticks <= now.ticks) + { +DEBUG_STREAM << "Event timestamp=" << event->timeStamp.ticks << "\n"; + switch(event->eventType) + { + case analog: +DEBUG_STREAM << "AnalogEvent\n"; + //---------------------------- + // Send event type ONLY + //---------------------------- + rio_event->Type = RIO::AnalogEvent; + //---------------------------- + // Restore the analog state + //---------------------------- + rioPointer->Throttle = event->data.analog.throttle; + rioPointer->LeftPedal = event->data.analog.pedalLeft; + rioPointer->RightPedal = event->data.analog.pedalRight; + rioPointer->JoystickX = event->data.analog.joystickX; + rioPointer->JoystickY = event->data.analog.joystickY; + break; + + case digital: +DEBUG_STREAM << "DigitalEvent\n"; + //---------------------------- + // Send the entire event + //---------------------------- + *rio_event = event->data.rioEvent; + break; + } + rioStream->AdvancePointer(sizeof(RIOStreamEvent)); + return True; + } + } + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::ProcessRIOEvent( + RIO::RIOEvent &rio_event, + Logical *new_RIO_values + ) +{ + //-------------------------------------------------- + // Get mode mask for updating + //-------------------------------------------------- + Check(application); + Check(application->GetModeManager()); + ModeMask + mode_mask = application->GetModeManager()->GetModeMask(); + ControlsButton temp; + + switch(rio_event.Type) + { + case RIO::ButtonPressedEvent: + Verify(rio_event.Data.Unit >= 0); + Verify(rio_event.Data.Unit < ButtonCount); + temp = rio_event.Data.Unit + 1; + + Check(&buttonGroup[rio_event.Data.Unit]); + buttonGroup[rio_event.Data.Unit].Update(&temp, mode_mask); + //---------------------------------------- + // Save 'pressed' mode mask for 'release' + //---------------------------------------- + buttonActivateModeMask[rio_event.Data.Unit] = mode_mask; + break; + + case RIO::ButtonReleasedEvent: + Verify(rio_event.Data.Unit >= 0); + Verify(rio_event.Data.Unit < ButtonCount); + temp = -rio_event.Data.Unit - 1; + + Check(&buttonGroup[rio_event.Data.Unit]); + //---------------------------------------- + // Use 'pressed' mode mask for 'release' + //---------------------------------------- + buttonGroup[rio_event.Data.Unit].Update( + &temp, + buttonActivateModeMask[rio_event.Data.Unit] + ); + break; + + case RIO::KeyEvent: + { + Verify(rio_event.Data.Keyboard.Unit >= 0); + Verify(rio_event.Data.Keyboard.Unit < KeyboardCount); + //-------------------------------------- + // Convert key to ASCII + //-------------------------------------- + ControlsKey + new_key = rio_event.Data.Keyboard.Key; + if (new_key <= 9) + { + new_key += '0'; + } + else + { + new_key += 'A'-10; + } + Test_Tell( + "LBE4ControlsManager::Execute, new_key=" << (int) new_key << + "\n" + ); + + Check(&keyboardGroup[rio_event.Data.Keyboard.Unit]); + keyboardGroup[rio_event.Data.Keyboard.Unit]. + ForceUpdate(&new_key, mode_mask); + + Check(&stringManager); + stringManager.Update( + rio_event.Data.Keyboard.Unit, + new_key + ); + } + break; + + case RIO::AnalogEvent: + lastRioRequest = 0L; // force another RIO update request + *new_RIO_values = True; + break; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::SaveRecording(const char* file_name) +{ + Check(this); + Check_Pointer(file_name); + Check(rioStream); + + FileStream + output(file_name, True); + size_t + length = rioStream->GetBytesUsed(); + if (length) + { + rioStream->Rewind(); + + output << length; + output << *rioStream; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::LoadPlayback(const char* file_name) +{ + Check(this); + Check_Pointer(file_name); + + FileStream + input(file_name); + Verify(input.IsFileOpened()); + + // + //------------------------------- + // Figure out how big the file is + //------------------------------- + // + size_t + spool_size = 0; + input >> spool_size; + Verify(spool_size); + Verify(spool_size <= RIO_SPOOL_SIZE * sizeof(RIOStreamEvent)); + + RIOStreamEvent + *events = new RIOStreamEvent[RIO_SPOOL_SIZE]; + Register_Pointer(events); + + Verify(rioStream == NULL); + rioStream = new MemoryStream(events, spool_size); + Register_Object(rioStream); + + input.ReadBytes(events, spool_size); +} + +#if defined(TEST_CLASS) +# include "l4ctrl.tcp" +#endif + diff --git a/CODE/RP/MUNGA_L4/L4CTRL.HPP b/CODE/RP/MUNGA_L4/L4CTRL.HPP new file mode 100644 index 0000000..a00d761 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4CTRL.HPP @@ -0,0 +1,692 @@ +//===========================================================================// +// File: L4ctrl.hpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for LBE4 Controls module // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/21/94 CPB Initial coding. // +// 6/ 7/95 CPB Adjusted switch/lamp enumerations to match reality // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4CTRL_HPP) +# define L4CTRL_HPP + + class LBE4ControlsManager; + enum LBE4ControlsManager::LampCount; + +# if !defined(CONTROLS_HPP) +# include +# endif + +# if !defined(L4RIO_HPP) +# include +# endif + +# if !defined(L4KEYBD_HPP) +# include +# endif + +# if !defined(L4MOUSE_HPP) +# include +# endif + +# if !defined(L4JOYSTK_HPP) +# include +# endif + +# if !defined(L4LAMP_HPP) +# include +# endif + +# if !defined(TIME_HPP) +# include +# endif + +# if !defined(ENTITY_HPP) +# include +# endif + + class LBE4ControlsManager; + class L4MappableButtonManager; + + //######################################################################## + //############################ Joystick classes ########################## + //######################################################################## + class Joystick; + class OrdinaryJoystick; + class FlightStickPro; + class ThrustMaster; + + class Joystick SIGNATURED + { + friend class LBE4ControlsManager; + friend class OrdinaryJoystick; + friend class FlightStickPro; + friend class ThrustMaster; + + protected: + Joystick(); + + public: + virtual ~Joystick(); + virtual void + BeginAlignment(); + virtual void + EndAlignment(); + virtual void + Update(); + void + SetDeadBand(Scalar amount_of_deadband); + Logical + TestInstance() const; + + protected: + virtual void + EndAndSaveAlignment(NotationFile *init_file); + public: + enum ButtonState { + NoButton = 0, + Trigger = 0x01, + Thumb1 = 0x02, + Thumb2 = 0x04, + Thumb3 = 0x08, + HatUp = 0x10, + HatDown = 0x20, + HatLeft = 0x40, + HatRight = 0x80 + }; + Vector2DOf Value; + Vector2DOf ExtendedValue; + int ButtonReleased; + int ButtonPressed; + + protected: + FilterChannel *channel[2]; + int oldButtons; + }; + + class OrdinaryJoystick: + public Joystick + { + public: + OrdinaryJoystick(); + ~OrdinaryJoystick(); + void Update(); + }; + + class FlightStickPro: + public Joystick + { + public: + FlightStickPro(); + ~FlightStickPro(); + void Update(); + void + BeginAlignment(); + void + EndAlignment(); + protected: + FilterChannel + *throttle; + }; + + class ThrustMaster: + public Joystick + { + public: + ThrustMaster(); + ~ThrustMaster(); + void Update(); + + int hatMax, prevHatState; + }; + + + + enum RioStreamEventType + { + analog, + digital + }; + + struct RIOStreamEvent + { + Time timeStamp; + + RioStreamEventType eventType; + + union + { + struct + { + Scalar + joystickX, + joystickY, + throttle, + pedalLeft, + pedalRight; + } + analog; + + RIO::RIOEvent rioEvent; + } + data; + }; + + //######################################################################### + //########################## LBE4ControlsManager ########################## + //######################################################################### + + class LBE4ControlsManager: + public ControlsManager + { + friend class L4MappableButtonManager; // allows access to 'groupEnable' + + //------------------------------------------------------------------- + // Shared data support + //------------------------------------------------------------------- + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + //------------------------------------------------------------------- + // Message support + //------------------------------------------------------------------- +// public: +// enum { +// BeginCalibrationMessageID=ControlsManager::NextMessageID, +// EndCalibrationMessageID, +// NextMessageID +// }; +// private: +// static const HandlerEntry MessageHandlerEntries[]; +// protected: +// static MessageHandlerSet MessageHandlers; + + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- + public: + LBE4ControlsManager(); + ~LBE4ControlsManager(); + + static Logical + TestClass(); + Logical + TestInstance() const; + + void + LocalShutdown(); + + void + Execute(); + + //------------------------------------------------------------------- + // Message handlers + //------------------------------------------------------------------- +// void +// BeginCalibrationMessageHandler(Receiver::Message *message); +// void +// EndCalibrationMessageHandler(Receiver::Message *message); +// + //------------------------------------------------------------------- + // Control mapping methods + //------------------------------------------------------------------- + + void + Remove(ModeMask mode_mask); + + static int + SetControlMappingID( + const char *control_name, + ControlsMapping *mapping + ); + void + CreateStreamedMappings( + Entity *player, + const int *control_mappings + ); + + //------------------------------------------------------------------- + // Lamps + //------------------------------------------------------------------- + + // Commonly used combinations + enum + { + LampSolidOff = RIO::solid + RIO::state1Off + RIO::state2Off, + LampSolidDim = RIO::solid + RIO::state1Dim + RIO::state2Dim, + LampSolidBright = RIO::solid + RIO::state1Bright + RIO::state2Bright + }; + + // This is the order of the mapped lamps + // See also "GetLampName" + enum { + LampAuxLowerRight8=0x00, // Lower left auxiliary panel buttons + LampAuxLowerRight7, + LampAuxLowerRight6, + LampAuxLowerRight5, + LampAuxLowerRight4, + LampAuxLowerRight3, + LampAuxLowerRight2, + LampAuxLowerRight1, + + LampAuxLowerLeft8=0x08, // Lower right auxiliary panel buttons + LampAuxLowerLeft7, + LampAuxLowerLeft6, + LampAuxLowerLeft5, + LampAuxLowerLeft4, + LampAuxLowerLeft3, + LampAuxLowerLeft2, + LampAuxLowerLeft1, + + LampSecondary1=0x10, // Secondary panel buttons + LampSecondary2, + LampSecondary3, + LampSecondary4, + LampSecondary5, + LampSecondary6, + LampTesla1, // top? of three solid-state relays + LampTesla2, // middle? of three solid-state relays + + LampSecondary7=0x18, + LampSecondary8, + LampSecondary9, + LampSecondary10, + LampSecondary11, + LampSecondary12, + LampTesla3, // bottom of three solid-state relays + + LampAuxUpperCenter8=0x20, // Upper center auxiliary panel buttons + LampAuxUpperCenter7, + LampAuxUpperCenter6, + LampAuxUpperCenter5, + LampAuxUpperCenter4, + LampAuxUpperCenter3, + LampAuxUpperCenter2, + LampAuxUpperCenter1, + + LampAuxUpperLeft8=0x28, // Upper left auxiliary panel buttons + LampAuxUpperLeft7, + LampAuxUpperLeft6, + LampAuxUpperLeft5, + LampAuxUpperLeft4, + LampAuxUpperLeft3, + LampAuxUpperLeft2, + LampAuxUpperLeft1, + + LampAuxUpperRight8=0x30, // Upper right auxiliary panel buttons + LampAuxUpperRight7, + LampAuxUpperRight6, + LampAuxUpperRight5, + LampAuxUpperRight4, + LampAuxUpperRight3, + LampAuxUpperRight2, + LampAuxUpperRight1, + + LampIcomDecRelay = 0x38, + LampIcomAmpEnable = 0x39, + LampIcomIncRelay = 0x3A, + LampIcomPTTRelay = 0x03B, + + LampPanic=0x3D, + LampFloor=0x3E, // floor lamp (entry/exit) + LampUnused=0x3F, // unimplemented convenience lamp + + LampCount // the total number of defined lamps + }; + + Lamp * + MakeLinkedLamp( + int element, + ModeMask mode_mask = ModeManager::ModeAlwaysActive + ); + + void + SetLamp( + int lamp_number, + int state + ); + + static const char* + GetLampName(int lamp_number); + //------------------------------------------------------------------- + // Control groups + // Each control belongs to one of several groups (as in the + // enum below). + //------------------------------------------------------------------- + + enum { + ScalarGroup, + JoystickGroup, + KeyboardGroup, + ButtonGroup, + MouseGroup + }; + + //------------------------------------------------------------- + // Scalars + //------------------------------------------------------------- + + // This is the order of the mapped scalars + enum { + ScalarThrottle, + ScalarLeftPedal, ScalarRightPedal, + ScalarJoystickX, ScalarJoystickY, // 'real' joystick values + ScalarMouseX, ScalarMouseY, // 'virtual' joystick values + ScalarCount + }; + + ControlsUpdateManager + scalarGroup[ScalarCount]; + +public: + void + SetThrottleDeadBand(Scalar dead_band); + void + SetPedalsDeadBand(Scalar dead_band); + //------------------------------------------------------------- + // Joysticks + //------------------------------------------------------------- + void + BeginAlignJoystick(); + void + EndAlignJoystick(); + void + CenterRIOJoystick(); + void + SetJoystickDeadBand(Scalar dead_band); + + + // This is the order of the mapped joysticks + enum { + JoystickPhysical, // the 'real' joystick + JoystickVirtual, // a 'virtual' joystick driven by the PC mouse + JoystickCount + }; + + ControlsUpdateManager + joystickGroup[JoystickCount]; + + enum JoystickType + { + none, ordinary, flightstickPro, thrustMaster + }; + + JoystickType + joystickType; + + protected: + Joystick + *joystickPointer; + int + virtualJoystickX, virtualJoystickY; + long + lastJoystickUpdate; + + public: + //------------------------------------------------------------- + // Keyboards + //------------------------------------------------------------- + + // This is the order of the mapped keyboards + enum { + KeyboardPilot, // internal keypad used by the pilot + KeyboardExternal, // external keypad used by an operator + KeyboardPC, // PC keyboard + KeyboardCount + }; + + ControlsUpdateManager + keyboardGroup[KeyboardCount]; + + //------------------------------------------------------------- + // Buttons + //------------------------------------------------------------- + + // This is the order of the buttons + enum { + ButtonAuxLowerRight8=0x00, // Lower left auxiliary panel buttons + ButtonAuxLowerRight7, + ButtonAuxLowerRight6, + ButtonAuxLowerRight5, + ButtonAuxLowerRight4, + ButtonAuxLowerRight3, + ButtonAuxLowerRight2, + ButtonAuxLowerRight1, + + ButtonAuxLowerLeft8=0x08, // Lower right auxiliary panel buttons + ButtonAuxLowerLeft7, + ButtonAuxLowerLeft6, + ButtonAuxLowerLeft5, + ButtonAuxLowerLeft4, + ButtonAuxLowerLeft3, + ButtonAuxLowerLeft2, + ButtonAuxLowerLeft1, + + ButtonSecondary1=0x10, // Secondary panel buttons + ButtonSecondary2, + ButtonSecondary3, + ButtonSecondary4, + ButtonSecondary5, + ButtonSecondary6, + + ButtonSecondary7=0x18, + ButtonSecondary8, + ButtonSecondary9, + ButtonSecondary10, + ButtonSecondary11, + ButtonSecondary12, + + ButtonAuxUpperCenter8=0x20,// Upper center auxiliary panel buttons + ButtonAuxUpperCenter7, + ButtonAuxUpperCenter6, + ButtonAuxUpperCenter5, + ButtonAuxUpperCenter4, + ButtonAuxUpperCenter3, + ButtonAuxUpperCenter2, + ButtonAuxUpperCenter1, + + ButtonAuxUpperLeft8=0x28, // Upper left auxiliary panel buttons + ButtonAuxUpperLeft7, + ButtonAuxUpperLeft6, + ButtonAuxUpperLeft5, + ButtonAuxUpperLeft4, + ButtonAuxUpperLeft3, + ButtonAuxUpperLeft2, + ButtonAuxUpperLeft1, + + ButtonAuxUpperRight8=0x30, // Upper right auxiliary panel buttons + ButtonAuxUpperRight7, + ButtonAuxUpperRight6, + ButtonAuxUpperRight5, + ButtonAuxUpperRight4, + ButtonAuxUpperRight3, + ButtonAuxUpperRight2, + ButtonAuxUpperRight1, + + ButtonIcomHeadPluggedIn = 0x39, + ButtonIcomSensor = 0x3A, + ButtonIcomMikePluggedIn = 0x3B, + ButtonDoor=0x3C, + ButtonPanic=0x3D, + + ButtonThrottle1=0x3F, + + ButtonJoystickTrigger=0x40, // Joystick trigger button + FirstMappableButton=ButtonJoystickTrigger, + ButtonJoystickHatDown=0x41, // Joystick trigger hat down + ButtonJoystickHatUp=0x42, // Joystick trigger hat up + ButtonJoystickHatRight=0x43, // Joystick trigger hat left + ButtonJoystickHatLeft=0x44, // Joystick trigger hat left + + ButtonJoystickPinky=0x45, // Joystick lowest button + ButtonJoystickThumbLow=0x46, // Joystick middle thumb button + ButtonJoystickThumbHigh=0x47, // Joystick upper thumb button (by hat) + LastMappableButton=ButtonJoystickThumbHigh, + + // The PC keyboard buttons will eventually + // be added here. + + ButtonMouseLeft, // left mouse button + ButtonMouseRight, // right mouse button + ButtonMouseCenter, // center mouse button (if available) + + + ButtonCount // defines number of buttons + }; + ControlsUpdateManager + buttonGroup[ButtonCount]; + protected: + ModeMask + buttonActivateModeMask[ButtonCount]; + + //------------------------------------------------------------- + // Mouse + //------------------------------------------------------------- + public: + ControlsUpdateManager + mouseGroup[1]; // Yes, only one mouse. Get real. + + protected: + Mouse + *mousePointer; + + public: + //------------------------------------------------------------- + // Strings (matched keyboard input) + //------------------------------------------------------------- + ControlsStringManager + stringManager; + + public: + //------------------------------------------------------------------- + // RIO data + //------------------------------------------------------------------- + RIO + *rioPointer; + + protected: + Time + lastRioRequest; + + public: + //------------------------------------------------------------------- + // Current IO type + //------------------------------------------------------------------- + enum IOType + { + None = 0, + PrimaryGenericJoystick, + PrimaryThrustMaster, + PrimaryFlightStickPro, + PrimaryRIO + }; + + IOType + primaryControlType; + + //------------------------------------------------------------------- + // Existence flags + //------------------------------------------------------------------- + struct { + unsigned int mouseExists:1; + unsigned int keyboardExists:1; + unsigned int joystickExists:1; + unsigned int RIOExists:1; + }flags; + + //------------------------------------------------------------------- + // Operator controls + //------------------------------------------------------------------- + protected: + enum L4ControlsMode + { + normalMode = 0, + calibrationMode + }; + + void + EnterControlsMode( + L4ControlsMode new_mode, + Scalar time_until_exit, + Receiver::MessageID message_on_exit + ); + + void + ExitControlsMode(); + + void + ManageControlsMode(); + + L4ControlsMode + l4ControlsMode; + Time + exitModeTime; + Receiver::MessageID + exitMessageID; + + enum + { + maxStringIDs = 16 + }; + + ControlsStringID + temporaryStringID[maxStringIDs]; + + // + //-------------------- + // RIO Stream Spoofing + //-------------------- + // + public: + Logical + GetNextRIOEvent(RIO::RIOEvent *rio_event); + void + ProcessRIOEvent( + RIO::RIOEvent &rio_event, + Logical *new_RIO_values + ); + + void + StartRecording() + {Check(this); streamStart = Now(); streamEnabled=True;} + void + SaveRecording(const char* file_name); + void + LoadPlayback(const char* file_name); + void + StartPlayback() + {Check(this); streamStart = Now(); streamEnabled=True;} + + Logical + IsRecording() + {return rioStream && !playbackMode;} + Logical + IsPlayingBack() + {return rioStream && playbackMode;} + Logical + AnalogHasChanged(); + + protected: + MemoryStream + *rioStream; + Time + streamStart; + Logical + playbackMode; + Logical + streamEnabled; + Scalar + previousJoystickX, + previousJoystickY, + previousThrottle, + previousPedalLeft, + previousPedalRight; + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4CTRL.TCP b/CODE/RP/MUNGA_L4/L4CTRL.TCP new file mode 100644 index 0000000..404dfbf --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4CTRL.TCP @@ -0,0 +1,448 @@ +//==========================================================================// +// File: lbe4ctrl.tst // +// Project: MUNGA Brick: LBE4 controls module // +// Contents: Test code for vector classes // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 12/26/94 CPB Initial coding. // +//--------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include +#include + +//########################################################################### +//############################# TestReceiver ################################ +//########################################################################### + +#if 0 +Derivation + TestControlsReceiver::ClassDerivations( + Receiver::ClassDerivations,"TestControlsReceiver" + ); + +TestControlsReceiver::SharedData + TestControlsReceiver::DefaultData( + TestControlsReceiver::ClassDerivations, + TestControlsReceiver::MessageHandlers + ); + +TestControlsReceiver::TestControlsReceiver( + TestControlsReceiver::ClassID class_ID, + TestControlsReceiver::SharedData &shared_data +): + Receiver(class_ID, shared_data) +{ + Check_Pointer(this); + keyValue = 0; + buttonValue = 0; + scalarValue = 0.0f; + joystickValue.x = 0.0f; + joystickValue.y = 0.0f; + mouseValue.x = 0; + mouseValue.y = 0; +} + +TestControlsReceiver::~TestControlsReceiver() +{ + Check(this); +} + +void +TestControlsReceiver::KeyboardMessageHandler( + ReceiverDataMessageOf *message +) +{ + Check(this); + Check_Pointer(message); + keyValue = message->dataContents; +} + +void +TestControlsReceiver::ScalarMessageHandler( + ReceiverDataMessageOf *message +) +{ + Check(this); + Check_Pointer(message); + scalarValue = message->dataContents; +} + +void +TestControlsReceiver::JoystickMessageHandler( + ReceiverDataMessageOf *message +) +{ + Check(this); + Check_Pointer(message); + joystickValue = message->dataContents; +} + +void +TestControlsReceiver::ButtonMessageHandler( + ReceiverDataMessageOf *message +) +{ + Check(this); + Check_Pointer(message); + buttonValue = message->dataContents; +} + +void +TestControlsReceiver::MouseMessageHandler( + ReceiverDataMessageOf *message +) +{ + Check(this); + Check_Pointer(message); + mouseValue += message->dataContents; +} + +const Receiver::HandlerEntry + TestControlsReceiver::MessageHandlerEntries[]= +{ + {TestControlsReceiver::KeyboardMessageID, + (Receiver::Handler)&TestControlsReceiver::KeyboardMessageHandler}, + {TestControlsReceiver::ScalarMessageID, + (Receiver::Handler)&TestControlsReceiver::ScalarMessageHandler}, + {TestControlsReceiver::JoystickMessageID, + (Receiver::Handler)&TestControlsReceiver::JoystickMessageHandler}, + {TestControlsReceiver::ButtonMessageID, + (Receiver::Handler)&TestControlsReceiver::ButtonMessageHandler}, + {TestControlsReceiver::MouseMessageID, + (Receiver::Handler)&TestControlsReceiver::MouseMessageHandler} +}; + +Receiver::MessageHandlerSet + TestControlsReceiver::MessageHandlers( + ELEMENTS(TestControlsReceiver::MessageHandlerEntries), + TestControlsReceiver::MessageHandlerEntries, + Receiver::MessageHandlers + ); +#endif + +// +//########################################################################### +//########################################################################### +// +Logical + LBE4ControlsManager::TestClass() +{ + Tell("Starting LBE4ControlsManager test...\n"); + +#if 0 + unsigned int fakeOwnerID(1); + + Check(application); + LBE4ControlsManager *controlsManager( + (LBE4ControlsManager *) application->GetControlsManager() + ); + Check(controlsManager); + + ControlsJoystick vector1; + Check(&vector1); + + TestControlsReceiver *my_receiver; + + my_receiver = new TestControlsReceiver(); + Check(my_receiver); + Register_Object(my_receiver); + + ControlsKey directKey = 0; + + // + //------------------------------------------------------------------- + // Keyboard test + //------------------------------------------------------------------- + // + controlsManager-> + keyboardGroup[LBE4ControlsManager::KeyboardPC]. + Add( + fakeOwnerID, + &directKey + ); + + controlsManager-> + keyboardGroup[LBE4ControlsManager::KeyboardPC]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::KeyboardMessageID + ); + cout << "Key test: Press any PC keyboard key" << + " or ENTER to move to next test.\n"; + while (my_receiver->keyValue != 0x0D) + { + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + + if (my_receiver->keyValue != 0) + { + cout << my_receiver->keyValue << "\n"; + Test(directKey == my_receiver->keyValue); + + if (my_receiver->keyValue != 0x0D) + { + my_receiver->keyValue = 0; + } + } + } + // + //------------------------------------------------------------------- + // Joystick test + //------------------------------------------------------------------- + // + controlsManager-> + joystickGroup[LBE4ControlsManager::JoystickPhysical]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::JoystickMessageID + ); + + cout << "Joystick test: Press ENTER to end.\n"; + cout << "Verify left is positive, backward is positive.\n"; + my_receiver->keyValue = 0; + while (my_receiver->keyValue != 0x0D) + { + char buffer[40]; + + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + + sprintf(buffer, "(%-6.5f, %-6.5f)\r", + my_receiver->joystickValue.x, + my_receiver->joystickValue.y + ); + cout << buffer; + } + cout << "\n"; + cout << "Joystick centering test: 'swizzle' the stick to its limits,\n"; + cout << "then center the joystick and press ENTER.\n"; + + controlsManager->BeginAlignJoystick(); + + my_receiver->keyValue = 0; + while (my_receiver->keyValue != 0x0D) + { + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + } + + controlsManager->EndAlignJoystick(); + + cout << "\n"; + cout << "Joystick centering test: verify centered, then press ENTER.\n"; + + my_receiver->keyValue = 0; + while (my_receiver->keyValue != 0x0D) + { + char buffer[40]; + + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + + sprintf(buffer, "(%-6.5f, %-6.5f)\r", + my_receiver->joystickValue.x, + my_receiver->joystickValue.y + ); + cout << buffer; + } + cout << "\n"; + + // + //------------------------------------------------------------------- + // Scalar test + //------------------------------------------------------------------- + // + controlsManager-> + scalarGroup[LBE4ControlsManager::ScalarJoystickX]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ScalarMessageID + ); + + cout << "Scalar test: Press ENTER to end.\n"; + cout << "Value displayed is joystick X axis.\n"; + my_receiver->keyValue = 0; + while (my_receiver->keyValue != 0x0D) + { + char buffer[40]; + + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + + sprintf(buffer, "(%-6.5f)\r", my_receiver->scalarValue); + cout << buffer; + } + cout << "\n"; + // + //------------------------------------------------------------------- + // Mouse test + //------------------------------------------------------------------- + // + controlsManager-> + mouseGroup[0]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::MouseMessageID + ); + + cout << "Mouse test: Press ENTER to end.\n"; + my_receiver->keyValue = 0; + while (my_receiver->keyValue != 0x0D) + { + char buffer[40]; + + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + + sprintf(buffer, "(%-06d, %-06d)\r", + my_receiver->mouseValue.x, + my_receiver->mouseValue.y + ); + cout << buffer; + } + cout << "\n"; + // + //------------------------------------------------------------------- + // "Virtual" (mouse-driven) joystick test + //------------------------------------------------------------------- + // + ControlsJoystick fakeJoystick; + + controlsManager-> + joystickGroup[LBE4ControlsManager::JoystickVirtual]. + Add( + fakeOwnerID, + &fakeJoystick + ); + + cout << "Virtual (mouse) joystick test: Press ENTER to end.\n"; + cout << "Verify left is positive, backward is positive.\n"; + my_receiver->keyValue = 0; + while (my_receiver->keyValue != 0x0D) + { + char buffer[40]; + + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + + sprintf(buffer, "(%-6.5f, %-6.5f)\r", + fakeJoystick.x, + fakeJoystick.y + ); + cout << buffer; + } + cout << "\n"; + // + //------------------------------------------------------------------- + // Button test + //------------------------------------------------------------------- + // + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickTrigger]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickThumbHigh]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickThumbLow]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + controlsManager-> + buttonGroup[LBE4ControlsManager::ButtonJoystickPinky]. + Add( + fakeOwnerID, + my_receiver, + TestControlsReceiver::ButtonMessageID + ); + + cout << "Button test: Operate joystick buttons. Press ENTER to end.\n"; + my_receiver->keyValue = 0; + while (my_receiver->keyValue != 0x0D) + { + controlsManager->Execute(); // 'manually' call update + application->ProcessAllEvents(); // 'manually' process events + + if (my_receiver->buttonValue) + { + switch(my_receiver->buttonValue) + { + case ButtonJoystickHatUp: cout << "Press hat up\n"; break; + case -ButtonJoystickHatUp: cout << "Release hat up\n"; break; + case ButtonJoystickHatDown: cout << "Press hat down\n"; break; + case -ButtonJoystickHatDown: cout << "Release hat down\n"; break; + case ButtonJoystickHatLeft: cout << "Press hat left\n"; break; + case -ButtonJoystickHatLeft: cout << "Release hat left\n"; break; + case ButtonJoystickHatRight: cout << "Press hat right\n"; break; + case -ButtonJoystickHatRight: cout << "Release hat right\n"; break; + case ButtonJoystickTrigger: cout << "Press trigger\n"; break; + case -ButtonJoystickTrigger: cout << "Release trigger\n"; break; + case ButtonJoystickThumbHigh: cout << "Press thumb high\n"; break; + case -ButtonJoystickThumbHigh:cout << "Release thumb high\n"; break; + case ButtonJoystickThumbLow: cout << "Press thumb low\n"; break; + case -ButtonJoystickThumbLow: cout << "Release thumb low\n"; break; + case ButtonJoystickPinky: cout << "Press pinky\n"; break; + case -ButtonJoystickPinky: cout << "Release pinky\n"; break; + } + my_receiver->buttonValue = 0; + } + } + + controlsManager->Remove(fakeOwnerID); + + Unregister_Object(my_receiver); + delete my_receiver; +#endif + + return True; +} + diff --git a/CODE/RP/MUNGA_L4/L4CTRL.THP b/CODE/RP/MUNGA_L4/L4CTRL.THP new file mode 100644 index 0000000..f98566c --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4CTRL.THP @@ -0,0 +1,88 @@ +//===========================================================================// +// File: controls.thh // +// Project: MUNGA Brick: Controls Module // +// Contents: Interface specification for Controls module // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 12/12/94 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(LBE4_CONTROLS_THH) +# define LBE4_CONTROLS_THH + + //######################################################################### + //############################# TestReceiver ############################## + //######################################################################### + class TestControlsReceiver: + public Receiver + { + //######################################################################### + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //######################################################################### + // Construction and Destruction Support + // + public: + TestControlsReceiver( + ClassID class_ID=TrivialReceiverClassID, + SharedData &shared_data=DefaultData + ); + + ~TestControlsReceiver(); + + //########################################################################## + // Messaging Support + // + public: + enum { + KeyboardMessageID=Receiver::NextMessageID, + ScalarMessageID, + JoystickMessageID, + ButtonMessageID, + MouseMessageID, + NextMessageID + }; + + protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void KeyboardMessageHandler(ReceiverDataMessageOf *); + void ScalarMessageHandler(ReceiverDataMessageOf *); + void JoystickMessageHandler(ReceiverDataMessageOf *); + void ButtonMessageHandler(ReceiverDataMessageOf *); + void MouseMessageHandler(ReceiverDataMessageOf *); + + //########################################################################## + // Test Support + // + public: + ControlsKey + keyValue; + + Scalar + scalarValue; + + ControlsJoystick + joystickValue; + + ControlsButton + buttonValue; + + ControlsMouse + mouseValue; + }; + + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4DPLMEM.CPP b/CODE/RP/MUNGA_L4/L4DPLMEM.CPP new file mode 100644 index 0000000..2018661 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4DPLMEM.CPP @@ -0,0 +1,45 @@ +/* +This block of code is expected to override the memory allocater in the DPL library +*/ +#include +#pragma hdrstop + +#if !defined(L4VIDEO_HPP) +# include +#endif + +extern "C" +{ + void + *dpl_malloc ( int n_bytes ), + *dpl_calloc ( size_t n, size_t n_bytes ), + dpl_free ( void *ptr ), + dpl_free_all ( void ); +}; + +void *dpl_malloc ( int n_bytes ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + return DPLRenderer::DPLHeap->Allocate(n_bytes); +} + +void *dpl_calloc ( size_t n, size_t n_bytes ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + void *p = DPLRenderer::DPLHeap->Allocate(n * n_bytes); + memset ( p, 0x0, n_bytes*n ); + return p; +} + +void dpl_free ( void *ptr ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + DPLRenderer::DPLHeap->Release(ptr); +} + +void dpl_free_all ( void ) +{ + Check_Pointer(DPLRenderer::DPLHeap); + DPLRenderer::DPLHeap->ReleaseAll(); +} + diff --git a/CODE/RP/MUNGA_L4/L4FILE.CPP b/CODE/RP/MUNGA_L4/L4FILE.CPP new file mode 100644 index 0000000..a30c98f --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4FILE.CPP @@ -0,0 +1,210 @@ +#include +#pragma hdrstop + +#if !defined(FILESTRM_HPP) +# include +#endif + +#if !defined(L4NET_HPP) +# include +#endif + +#if !defined(NETNUB_HPP) +# include +#endif + +#include +#include +#include + +#define NETNUB_MARK 0x10000 + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + FileStream::OpenImplementation( + const char* filename, + Logical read_only + ) +{ + Check_Pointer(filename); + + if (Net_Common_Ptr && !read_only) + { + OpenFileRequestPtr request = + (OpenFileRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + OpenFileReturnPtr status = + (OpenFileReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + + Net_Common_Ptr->Function = NETNUB_OPEN_FILE; + Net_Common_Ptr->Buffer_Length = sizeof(*request); + Str_Copy(request->File_Name, filename, sizeof(request->File_Name)); + request->Access = O_CREAT|O_TRUNC|O_BINARY|2; + request->Model = S_IWRITE; + + NetNub::SendCommand(); + + int handle = status->File_Handle; + return handle|NETNUB_MARK; + } + else if (read_only) + { + return open(filename, O_BINARY|O_RDONLY); + } + else + { + return open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, S_IWRITE); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + FileStream::CloseImplementation(int handle) +{ + if (handle&NETNUB_MARK) + { + Verify(Net_Common_Ptr); + CloseFileRequestPtr request = + (CloseFileRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + + Net_Common_Ptr->Function = NETNUB_CLOSE_FILE; + Net_Common_Ptr->Buffer_Length = sizeof(*request); + request->File_Handle = (short)(handle&~NETNUB_MARK); + + NetNub::SendCommand(); + } + else + { + close(handle); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::SeekImplementation( + int file_handle, + size_t where, + Logical from_end + ) +{ + if (file_handle&NETNUB_MARK) + { + Verify(Net_Common_Ptr); + SeekFileRequestPtr request = + (SeekFileRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + SeekFileReturnPtr status = + (SeekFileReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + + Net_Common_Ptr->Function = NETNUB_SEEK_FILE; + Net_Common_Ptr->Buffer_Length = sizeof(*request); + request->File_Handle = (short)(file_handle&~NETNUB_MARK); + request->Seek_Mode = (short)((from_end) ? SEEK_END : SEEK_SET); + request->Seek_Offset = where; + + NetNub::SendCommand(); + + return status->Seek_Position; + } + else + { + return lseek(file_handle, (long)where, (from_end) ? SEEK_END : SEEK_SET); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::WriteImplementation( + int file_handle, + const void *buffer, + size_t length + ) +{ + Check_Pointer(buffer); + + if (file_handle&NETNUB_MARK) + { + Verify(Net_Common_Ptr); + WriteFileRequestPtr request = + (WriteFileRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + #if DEBUG_LEVEL>0 + WriteFileReturnPtr status = + (WriteFileReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + #endif + + size_t remaining = length; + char *where = (char*)buffer; + while (remaining) + { + size_t chunk = remaining; + Max_Clamp(chunk, MAX_TRANSFER_SIZE); + + Net_Common_Ptr->Function = NETNUB_WRITE_FILE; + Net_Common_Ptr->Buffer_Length = (unsigned short)(chunk + 4); + request->File_Handle = (short)(file_handle&~NETNUB_MARK); + request->Write_Length = (unsigned short)chunk; + Mem_Copy(request->Write_Data, where, chunk, SHARED_MEMORY_SIZE); + + NetNub::SendCommand(); + Verify(status->Bytes_Written == chunk); + + where += chunk; + remaining -= chunk; + } + return length; + } + else + { + return write(file_handle, buffer, length); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::ReadImplementation( + int file_handle, + void *buffer, + size_t length + ) +{ + Check_Pointer(buffer); + + if (file_handle&NETNUB_MARK) + { + Verify(Net_Common_Ptr); + ReadFileRequestPtr request = + (ReadFileRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + ReadFileReturnPtr status = + (ReadFileReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + + size_t remaining = length; + char *where = (char*)buffer; + while (remaining) + { + size_t chunk = remaining; + Max_Clamp(chunk, MAX_TRANSFER_SIZE); + + Net_Common_Ptr->Function = NETNUB_READ_FILE; + Net_Common_Ptr->Buffer_Length = sizeof(*request); + request->File_Handle = (short)(file_handle&~NETNUB_MARK); + request->Read_Length = (unsigned short)chunk; + + NetNub::SendCommand(); + Verify(chunk == Net_Common_Ptr->Buffer_Length); + + Mem_Copy(where, status->Read_Data, chunk, SHARED_MEMORY_SIZE); + + where += chunk; + remaining -= chunk; + } + return length; + } + else + { + return read(file_handle, buffer, length); + } +} + diff --git a/CODE/RP/MUNGA_L4/L4GAUIMA.CPP b/CODE/RP/MUNGA_L4/L4GAUIMA.CPP new file mode 100644 index 0000000..be00920 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4GAUIMA.CPP @@ -0,0 +1,1696 @@ +//===========================================================================// +// File: vectlist.cpp // +// Project: MUNGA Brick: Gauge Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/19/95 CPB Initial coding. // +// 06/01/95 CPB Resourcified. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(L4GAUIMA_HPP) +# include +#endif + +#if !defined(L4APP_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +#if !defined(NAMELIST_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) cout << n << flush +#else +# define Test_Tell(n) +#endif + + +//############################################################################ +// GroupAttribute +// - this is a private class used nowhere else. +// It is initialized from a .GAT notation file, after which it +// holds a list of attribute group names with associated color and +// attribute fields. It may then be searched to find the values for +// that attribute group. +//############################################################################ +class GroupAttribute SIGNATURED +{ +public: + enum + { + nameLength=64 + }; + + int color; + int attribute; + char name[nameLength]; + + GroupAttribute + *next; + + GroupAttribute(const char *new_name, int new_color, int new_attrib); + ~GroupAttribute() + {} + + Logical + TestInstance() const + { return True; } + + static Logical + Initialize(const char *gat_file_name); + static void + Terminate(); + static Logical + Search(const char *name, int *color, int *attribute); +protected: + static + GroupAttribute + *head; +}; + +GroupAttribute + *GroupAttribute::head; + +GroupAttribute::GroupAttribute( + const char *new_name, + int new_color, + int new_attrib +) +{ + Test_Tell( + "GroupAttribute::GroupAttribute(" << new_name << + ", " << new_color << + ", " << new_attrib << + ")\n" + ); + Check_Pointer(this); + Check_Pointer(new_name); + + name[0] = '\0'; // safety check + Str_Copy(name, new_name, nameLength-1); + name[nameLength-1] = '\0'; + + color = new_color; + attribute = new_attrib; + + next = head; + head = this; + Check_Fpu(); +} + +Logical + GroupAttribute::Initialize(const char *gat_filename) +{ + Test_Tell("GroupAttribute::Initialize(" << gat_filename << ")\n"); + Check_Pointer(gat_filename); + + Logical + result = False; + + //------------------------------------------------------------- + // Open the associated .GAT file + //------------------------------------------------------------- + NotationFile + *gat_file = new NotationFile(gat_filename); + Check(gat_file); + Register_Object(gat_file); + + //------------------------------------------------------------- + // Create group, attribute, color name lists + //------------------------------------------------------------- + NameList + *color_namelist = gat_file->MakeEntryList("colors"); + if (color_namelist == NULL) + { + DEBUG_STREAM << gat_filename << " has no 'colors' page!" << endl; + } + + NameList + *attribute_namelist = gat_file->MakeEntryList("attributes"); + if (attribute_namelist == NULL) + { + DEBUG_STREAM << gat_filename << " has no 'attributes' page!" << endl; + } + + NameList + *group_namelist = gat_file->MakeEntryList("groups"); + if (group_namelist == NULL) + { + DEBUG_STREAM << gat_filename << " has no 'groups' page!" << endl; + } + + if ( + (attribute_namelist != NULL) && + (color_namelist != NULL) && + (group_namelist != NULL) + ) + { + //------------------------------------------------------------- + // Register the name lists + //------------------------------------------------------------- + Register_Object(color_namelist); + Register_Object(attribute_namelist); + Register_Object(group_namelist); + //------------------------------------------------------------- + // Clear the chain header + //------------------------------------------------------------- + head = NULL; + //------------------------------------------------------------- + // For all group names, build a GroupAttribute object + //------------------------------------------------------------- + NameList::Entry + *group_entry, + *color_entry, + *attribute_entry; + int + i, + new_attribute, + new_color; + Logical + found; + + for ( + group_entry = group_namelist->GetFirstEntry(); + group_entry != NULL; + group_entry = group_entry->GetNextEntry() + ) + { + Check(group_entry); + + char + buffer[256]; + char + *dest, + *text = group_entry->GetChar(); + + new_attribute = 0; + new_color = 0; + + if (text == NULL) + { + DEBUG_STREAM << text << " is an empty .GAT group!" << endl; + } + else + { + //------------------------------------------------------------- + // Skip white space + //------------------------------------------------------------- + while (*text != '\0') + { + while (isspace(*text)) + { + ++text; + } + //------------------------------------------------------------- + // Parse out one name + //------------------------------------------------------------- + for ( + i=0,dest=buffer; + i<(sizeof(buffer)-1); + ++i,++dest,++text + ) + { + if (!isalnum(*text)) + { + break; + } + + *dest = *text; + } + *dest = '\0'; + + Test_Tell("attribute item= <" << buffer << ">\n"); + //------------------------------------------------------------- + // Search color list for name + //------------------------------------------------------------- + found = False; + + for ( + color_entry = color_namelist->GetFirstEntry(); + color_entry != NULL; + color_entry = color_entry->GetNextEntry() + ) + { + Check(color_entry); + if (strcmp(color_entry->GetName(), buffer) == 0) + { + Check_Pointer(color_entry->GetData()); + new_color = color_entry->GetAtoi(); + Test_Tell("color=" << new_color << "\n"); + found = True; + break; + } + } + if (! found) + { + //---------------------------------------------------------- + // Search attribute list for name + //---------------------------------------------------------- + found = False; + + for ( + attribute_entry =attribute_namelist->GetFirstEntry(); + attribute_entry != NULL; + attribute_entry = attribute_entry->GetNextEntry() + ) + { + Check(attribute_entry); + if (strcmp(attribute_entry->GetName(), buffer) == 0) + { + Check_Pointer(attribute_entry->GetData()); + new_attribute |= attribute_entry->GetAtoi(); + Test_Tell( + "attribute=" << hex << new_attribute << dec << ">\n" + ); + found = True; + break; + } + } + if (! found) + { + DEBUG_STREAM << + "Attribute '" << buffer << "' not found!" << endl; + } + } + } + } + Check(group_entry); + Check_Pointer(group_entry->GetName()); + +# if DEBUG_LEVEL == 0 + new GroupAttribute( + group_entry->GetName(), + new_color, + new_attribute + ); +# else + GroupAttribute + *group_attribute = + new GroupAttribute( + group_entry->GetName(), + new_color, + new_attribute + ); + Check(group_attribute); + Register_Object(group_attribute); + Test_Tell("object created\n"); +# endif + } + //------------------------------------------------------------- + // Release the name lists + //------------------------------------------------------------- + Test_Tell("loop finished, deleting namelists\n"); + Check(color_namelist); + Unregister_Object(color_namelist); + delete color_namelist; + + Check(attribute_namelist); + Unregister_Object(attribute_namelist); + delete attribute_namelist; + + Check(group_namelist); + Unregister_Object(group_namelist); + delete group_namelist; + + result = True; + } + //------------------------------------------------------------- + // Release the notation file + //------------------------------------------------------------- + Test_Tell("deleting .GAT notation file\n"); + Check(gat_file); + Unregister_Object(gat_file); + delete gat_file; + + Test_Tell("returning " << result <<"\n"); + Check_Fpu(); + return result; +} + +void + GroupAttribute::Terminate() +{ + Test_Tell("GroupAttribute::Terminate\n"); + GroupAttribute + *group_attribute, + *next; + + for( + group_attribute= head; + group_attribute != NULL; + group_attribute = next + ) + { + Check(group_attribute); + next = group_attribute->next; + + Unregister_Object(group_attribute); + delete group_attribute; + } + + head = NULL; + Test_Tell("Termination completed\n"); + Check_Fpu(); +} + + +Logical + GroupAttribute::Search(const char *name, int *color_dest, int *attrib_dest) +{ + Test_Tell("GroupAttribute::Search("<< name <<")\n"); + GroupAttribute + *group_attribute; + + for( + group_attribute= head; + group_attribute != NULL; + group_attribute = group_attribute->next + ) + { + Check(group_attribute); + if ( + strncmp( + name, + group_attribute->name, + GroupAttribute::nameLength + ) == 0 + ) + { + Test_Tell("Found!\n"); + *color_dest = group_attribute->color; + *attrib_dest = group_attribute->attribute; + Check_Fpu(); + return True; + } + } + Check_Fpu(); + return False; +} + +//############################################################################ +// L4GaugeImage +//############################################################################ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +L4GaugeImage * + L4GaugeImage::Make(const char */*file_name*/) +{ + return NULL; // Gauge images come exclusively from resources +} + +L4GaugeImage * + L4GaugeImage::Make(ResourceDescription::ResourceID new_resource_id) +{ + Check(application); + Check(application->GetResourceFile()); + + L4GaugeImage + *image = NULL; + //------------------------------------------- + // Attempt to find the specified resource + //------------------------------------------- + ResourceDescription + *stream_resource_description = + application->GetResourceFile()->SearchList( + new_resource_id, + ResourceDescription::GaugeImageStreamResourceType + ); + + if (stream_resource_description == NULL) + { + Tell( + "L4GaugeImage::Make: resource ID '" << new_resource_id << + "' does not exist\n" + ); + } + else + { + //------------------------------------------- + // Found it, open a DynamicMemoryStream + //------------------------------------------- + Check(stream_resource_description); + stream_resource_description->Lock(); + MemoryStream + memory_stream( + stream_resource_description->resourceAddress, + stream_resource_description->resourceSize + ); + if (stream_resource_description->resourceAddress == NULL) + { + Tell("L4GaugeImage::Make: couldn't open stream\n"); + } + else + { + //------------------------------------------- + // Create the object + //------------------------------------------- + image = new L4GaugeImage(&memory_stream); + } + stream_resource_description->Unlock(); + } + Check_Fpu(); + return image; +} + +L4GaugeImage::L4GaugeImage(MemoryStream *mem_stream) +{ + Test_Tell("L4GaugeImage::L4GaugeImage\n"); + Check_Pointer(this); + Check(mem_stream); + + int + i; + + //------------------------------------------------------------- + // Read the number of vertices + //------------------------------------------------------------- + MemoryStream_Read(mem_stream, &vertexCount); + Verify(vertexCount > 0); + //------------------------------------------------------------- + // Allocate the vertex array + //------------------------------------------------------------- + vertexArray = new Point3D[vertexCount]; + Check_Pointer(vertexArray); + Register_Pointer(vertexArray); + //------------------------------------------------------------- + // Read in the vertex values + //------------------------------------------------------------- + for(i=0; i 0); + //------------------------------------------------------------- + // Allocate the LOD scales + //------------------------------------------------------------- + LODScales = new Scalar[LODCount]; + Check_Pointer(LODScales); + Register_Pointer(LODScales); + //------------------------------------------------------------- + // Read the LOD scales + //------------------------------------------------------------- + for(i=0; iGetEntry("gauge", "image", &gauge_filename) != 0) + { + //------------------------------------------------------------- + // It does, attempt to open the given notation file + //------------------------------------------------------------- + Tell("Opening gauge image " << gauge_filename << "\n"); + + char *gim_filename = + MakePathedFilename(directories->gaugeDirectory, gauge_filename); + Register_Pointer(gim_filename); + + NotationFile + *gim_file = new NotationFile(gim_filename); + Check(gim_file); + Register_Object(gim_file); + + //-------------------------------------------------------- + // Search for the name of the .GAT file + //-------------------------------------------------------- + const char + *gat_entry; + + if (gim_file->GetEntry("object", "gatfile", &gat_entry) == 0) + { + DEBUG_STREAM << "Missing .gat specification!" << endl; + } + else + { + //------------------------------------------------------------- + // Create the GroupAttribute data + //------------------------------------------------------------- + char *gat_filename = + MakePathedFilename(directories->gaugeDirectory, gat_entry); + Register_Pointer(gat_filename); + + if (GroupAttribute::Initialize(gat_filename)) + { + //------------------------------------------------------------- + // Create a dynamic memory stream, write out the data + // (note: the call to L4GaugeImage::DynamicMemoryStreamWrite() + // internally calls the dynamic stream writes for all of the + // 'owned' sub-parts as well) + //------------------------------------------------------------- + DynamicMemoryStream + *gim_stream = new DynamicMemoryStream(); + + Check(gim_stream); + Register_Object(gim_stream); + + if ( + L4GaugeImage::MemoryStreamWrite( + gim_stream, + gim_file + ) == True + ) + { + //------------------------------------------------------------- + // Create the resource description, assign an ID + //------------------------------------------------------------- + ResourceDescription + *res_desc_stream = + resource_file->ResourceFile::AddResourceMemoryStream( + model_name, + ResourceDescription::GaugeImageStreamResourceType, + 1, + ResourceDescription::Preload, + gim_stream + ); + + Check(res_desc_stream); + res_id = res_desc_stream->resourceID; + } + + //------------------------------------------------------------- + // Release the GroupAttribute data + //------------------------------------------------------------- + GroupAttribute::Terminate(); + + Check(gim_stream); + Unregister_Object(gim_stream); + delete gim_stream; + } + Check_Pointer(gat_filename); + Unregister_Pointer(gat_filename); + delete gat_filename; + } + //------------------------------------------------------------- + // Release variables + //------------------------------------------------------------- + Check(gim_file); + Unregister_Object(gim_file); + delete gim_file; + + Check_Pointer(gim_filename); + Unregister_Pointer(gim_filename); + delete gim_filename; + + Tell("Closed gauge image\n" << flush); + } + //------------------------------------------------------------- + // Return the new ResourceID + //------------------------------------------------------------- + Test_Tell("res_id = " << res_id << "\n"); + Check_Fpu(); + return res_id; +} + + +Logical + L4GaugeImage::MemoryStreamWrite( + MemoryStream *mem_stream, + NotationFile *gim_file + ) +{ + Test_Tell(" L4GaugeImage::MemoryStreamWrite(" << mem_stream << + ", " << gim_file << + ")\n" + ); + Check(mem_stream); + Check(gim_file); + + int + i; + //------------------------------------------------------------- + // 'result' is set to False if an error occurs. + //------------------------------------------------------------- + Logical + result = True; + //------------------------------------------------------------- + // Write the vertices + //------------------------------------------------------------- + NameList + *vertex_list = gim_file->MakeEntryList("vertices"); + + if (vertex_list == NULL) + { + DEBUG_STREAM << "No 'vertices' page in the .GIM file!" << endl; + result = False; + } + else + { + Check(vertex_list); + Register_Object(vertex_list); + //------------------------------------------------------------- + // Get the number of vertices + //------------------------------------------------------------- + int + vertex_count = vertex_list->EntryCount(); + + Test_Tell("vertex_count = " << vertex_count << "\n"); + if (vertex_count <= 0) + { + DEBUG_STREAM << + "The 'vertices' page in the .GIM file has no entries!" <GetFirstEntry(); + + for (int i=0; iGetChar(), &point_3d); + Test_Tell(" " << point_3d << "\n"); + MemoryStream_Write(mem_stream, &point_3d); + + vertex_entry = vertex_entry->GetNextEntry(); + } + } + //------------------------------------------------------------- + // Delete the vertex list + //------------------------------------------------------------- + Check(vertex_list); + Unregister_Object(vertex_list); + delete vertex_list; + } + + //------------------------------------------------------------- + // Write the levels of detail + //------------------------------------------------------------- + if (result == True) + { + NameList + *lod_namelist = gim_file->MakeEntryList("lods"); + + if (lod_namelist == NULL) + { + DEBUG_STREAM << "No 'lods' page in the .GIM file!" << endl; + result = False; + } + else + { + Check(lod_namelist); + Register_Object(lod_namelist); + //------------------------------------------------------------- + // Get the number of LOD's + //------------------------------------------------------------- + int + lod_count = lod_namelist->EntryCount(); + Test_Tell("lod_count = " << lod_count << "\n"); + if (lod_count <= 0) + { + DEBUG_STREAM << + "The 'lod' page in the .GIM file has no entries!" << endl; + result = False; + } + else + { + //------------------------------------------------------------- + // Write the number of LOD's to the stream + //------------------------------------------------------------- + MemoryStream_Write(mem_stream, &lod_count); + //------------------------------------------------------------- + // Write the LOD scales + //------------------------------------------------------------- + NameList::Entry + *scale_entry; + Scalar + scale; + + const char + *text; + + scale_entry = lod_namelist->GetFirstEntry(); + for (i=0; iGetChar(); + if (text == NULL) + { + DEBUG_STREAM << "Missing scale value!" << endl; + result = False; + break; + } + scale = (Scalar) atof(text); + + Test_Tell(" " << scale << "\n"); + MemoryStream_Write(mem_stream, &scale); + + scale_entry = scale_entry->GetNextEntry(); + } + //------------------------------------------------------------- + // Write the LOD lists + //------------------------------------------------------------- + scale_entry = lod_namelist->GetFirstEntry(); + for (i=0; iGetName() + ); + + if (result == False) + { + break; + } + + scale_entry = scale_entry->GetNextEntry(); + } + } + } + //------------------------------------------------------------- + // Delete the LOD list + //------------------------------------------------------------- + Check(lod_namelist); + Unregister_Object(lod_namelist); + delete lod_namelist; + } + Check_Fpu(); + return result; +} + + +void + L4GaugeImage::Draw( + Scalar LOD_value, // smaller = more detail (1.0 = 'normal') + Scalar scale_value, // metersPerPixel + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + int boxed_color + ) +{ + Test_Tell( + "L4GaugeImage::Draw(" << scale_value << + ", " << graphics_view << + ", " << default_color << + ", " << localToView << + ", " << boxed_color << + ")\n" + ); + Check(this); + Check(graphics_view); + // localToView allowed to be NULL + Check_Pointer(LODScales); + Check_Pointer(LODList); + +# define VERTEX_ALLOTMENT 100 // HACK - I'm guessing this is big enough. + + Verify(vertexCount <= VERTEX_ALLOTMENT); + + static + Point3D + local_vertex_array[VERTEX_ALLOTMENT]; + + static + Logical + local_flag_array[VERTEX_ALLOTMENT]; + + int + lod_index; + + if (localToView == NULL) + { + return; + } + //------------------------------------------------------------- + // Find LOD index + //------------------------------------------------------------- + for(lod_index=0; lod_indexDraw( + graphics_view, + default_color, + localToView, + vertexArray, + local_vertex_array, + local_flag_array, + scale_value, + boxed_color + ); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Instance +// +Logical + L4GaugeImage::TestInstance() const +{ + return True; +} +//############################################################################ +// L4GaugeImageList +//############################################################################ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +L4GaugeImageList::L4GaugeImageList(MemoryStream *mem_stream) +{ + Test_Tell("L4GaugeImageList::L4GaugeImageList\n"); + Check_Pointer(this); + Check(mem_stream); + + int + i; + + //------------------------------------------------------------- + // Read the number of primitives from the stream + //------------------------------------------------------------- + MemoryStream_Read(mem_stream, &primitiveCount); + Verify(primitiveCount > 0); + //------------------------------------------------------------- + // Allocate the primitive list + //------------------------------------------------------------- + primitiveList = new L4GaugeImagePrimitive*[primitiveCount]; + Check_Pointer(primitiveList); + Register_Pointer(primitiveList); + //------------------------------------------------------------- + // Read the primitives + //------------------------------------------------------------- + for(i=0; iMakeEntryList(page_name); + + if (primitive_list == NULL) + { + DEBUG_STREAM << "Can't find the '" << page_name << "' page in the .GIM file!" + << endl; + result = False; + } + else + { + Check(primitive_list); + Register_Object(primitive_list); + //------------------------------------------------------------- + // Get the number of primitives + //------------------------------------------------------------- + int + primitive_count = primitive_list->EntryCount(); + + Test_Tell(" primitive_count = " << primitive_count << "\n"); + if (primitive_count <= 0) + { + DEBUG_STREAM << "The '"<GetFirstEntry(); + for (i=0; iGetName(), + primitive_entry->GetChar() + ); + + if (result == False) + { + break; + } + + primitive_entry = primitive_entry->GetNextEntry(); + } + } + //------------------------------------------------------------- + // Delete the primitive list + //------------------------------------------------------------- + Check(primitive_list); + Unregister_Object(primitive_list); + delete primitive_list; + } + Check_Fpu(); + return result; +} + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Support +// +Logical + L4GaugeImageList::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4GaugeImageList::Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + int boxed_color + ) +{ + Test_Tell( + "L4GaugeImageList::Draw(" << graphics_view << + ", " << default_color << + ", " << localToView << + ", " << untransformed_vertex_array << + ", " << transformed_vertex_array << + ", " << transformed_flag_array << + ", " << scale_factor << + ", " << boxed_color << + ")\n" + ); + Check(this); + Check(graphics_view); + Check(&localToView); + Check_Pointer(untransformed_vertex_array); + Check_Pointer(transformed_vertex_array); + Check_Pointer(transformed_flag_array); + + Check_Pointer(primitiveList); + + int + i; + L4GaugeImagePrimitive + **array_pointer = primitiveList; + + if (boxed_color != 0) + { + //-------------------------------------------------------- + // Initialize bounding box + //-------------------------------------------------------- + Rectangle2D + bounds(9999,9999,-9999,-9999); + //-------------------------------------------------------- + // Draw primitives, collect bounding data + //-------------------------------------------------------- + for(i=0; iDraw( + graphics_view, + default_color, + localToView, + untransformed_vertex_array, + transformed_vertex_array, + transformed_flag_array, + scale_factor, + &bounds + ); + } + //-------------------------------------------------------- + // Draw the bounding box + //-------------------------------------------------------- + graphics_view->SetColor(boxed_color); + + graphics_view->MoveToAbsolute( + bounds.bottomLeft.x-4, + bounds.bottomLeft.y-4 + ); + graphics_view->DrawRectangleToAbsolute( + bounds.topRight.x+4, + bounds.topRight.y+4 + ); + } + else + { + //-------------------------------------------------------- + // Just draw it + //-------------------------------------------------------- + for(i=0; iDraw( + graphics_view, + default_color, + localToView, + untransformed_vertex_array, + transformed_vertex_array, + transformed_flag_array, + scale_factor, + NULL + ); + } + } + Check_Fpu(); +} + +//############################################################################ +// L4GaugeImagePrimitive +//############################################################################ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +L4GaugeImagePrimitive::L4GaugeImagePrimitive(MemoryStream *mem_stream) +{ + Test_Tell("L4GaugeImagePrimitive::L4GaugeImagePrimitive\n"); + Check_Pointer(this); + Check(mem_stream); + + int + i, + n; + //-------------------------------------------------------------- + // Read the primitive type ID, use the input stream accordingly + //-------------------------------------------------------------- + MemoryStream_Read(mem_stream, &n); + type = (primitiveType) n; + + switch(type) + { + case primitiveVector: + Test_Tell(" primitiveVector\n"); + //-------------------------------------------------------- + // Read the attribute and color + //-------------------------------------------------------- + MemoryStream_Read(mem_stream, &color); + MemoryStream_Read(mem_stream, &attributes); + Test_Tell(" color = " << color << "\n"); + Test_Tell(" attributes = " << hex << attributes << dec << "\n"); + //-------------------------------------------------------- + // Read the vertex index count + //-------------------------------------------------------- + MemoryStream_Read(mem_stream, &data.vector.indexCount); + Test_Tell(" indexCount = " << data.vector.indexCount << "\n"); + Verify(data.vector.indexCount > 0); + //-------------------------------------------------------- + // Allocate the index table + //-------------------------------------------------------- + data.vector.indexList = new int[data.vector.indexCount]; + Check_Pointer(data.vector.indexList); + Register_Pointer(data.vector.indexList); + //-------------------------------------------------------- + // Read the indices + //-------------------------------------------------------- + for(i=0; i 0) + int + check_length = strlen(data)+1; +# endif + + while(*scan != '\0') + { + Verify((scan-data) < check_length); + //-------------------------------------------------------- + // Skip white space + //-------------------------------------------------------- + while (isspace(*scan)) + { + ++scan; + } + //-------------------------------------------------------- + // Parse non-space string + //-------------------------------------------------------- + if (*scan == 'v') + { + int + n; + //-------------------------------------------------------- + // Convert to value, save in array + //-------------------------------------------------------- + ++scan; // ignore 'v' + for(n=0; isdigit(*scan); ++scan) + { + n = (n*10) + (*scan - '0'); + } + Test_Tell(" " << n << "\n"); + + if (index_count < MAX_INDICES) + { + index[index_count++] = n; + } + } + else if (*scan == 'a') + { + char + buffer[64], + *dest; + //-------------------------------------------------------- + // Collect the name + //-------------------------------------------------------- + for( + i=0, dest=buffer; + i<(sizeof(buffer)-1); + ++i,++scan,++dest + ) + { + if (isspace(*scan)) + { + break; + } + if (*scan == '\0') + { + break; + } + *dest = *scan; + } + *dest = '\0'; + //-------------------------------------------------------- + // Search for the name + //-------------------------------------------------------- + if ( + GroupAttribute::Search( + buffer, + &color_value, + &attribute_value + ) == False + ) + { + DEBUG_STREAM << "Couldn't find attribute group '" << + buffer << "'!" << endl; + } + } + } + //-------------------------------------------------------- + // Write the attributes + //-------------------------------------------------------- + Test_Tell(" color=" << color_value << "\n"); + MemoryStream_Write(mem_stream, &color_value); + Test_Tell(" attribute=" << attribute_value << "\n"); + MemoryStream_Write(mem_stream, &attribute_value); + //-------------------------------------------------------- + // Write the vertex index count + //-------------------------------------------------------- + if (index_count == 0) + { + DEBUG_STREAM << "No vertex indices in primitive!" << endl; + result = False; + } + else + { + Test_Tell(" index_count=" << index_count << "\n"); + MemoryStream_Write(mem_stream, &index_count); + //-------------------------------------------------------- + // Write the indices + //-------------------------------------------------------- + for(i=0; i < index_count; ++i) + { + MemoryStream_Write(mem_stream, &index[i]); + } + } + } + else + { + DEBUG_STREAM << "Unsupported primitive ("<< type_name << ") in .GIM file!" + << endl; + result = False; + } + Check_Fpu(); + return result; +} + + +//============================================================================ +// TestInstance +//============================================================================ +Logical + L4GaugeImagePrimitive::TestInstance() const +{ + return True; +} +//============================================================================ +// Draw +//============================================================================ +void + L4GaugeImagePrimitive::Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + Rectangle2D *bounds + ) +{ + Test_Tell( + "L4GaugeImagePrimitive::Draw(" << graphics_view << + ", " << default_color << + ", " << localToView << + ", " << untransformed_vertex_array << + ", " << transformed_vertex_array << + ", " << transformed_flag_array << + ", " << scale_factor << + ", " << bounds << + ")\n" + ); + + Check(this); + Check(graphics_view); + Check(&localToView); + Check_Pointer(untransformed_vertex_array); + Check_Pointer(transformed_vertex_array); + Check_Pointer(transformed_flag_array); + + //----------------------------------------------- + // Draw primitive + //----------------------------------------------- + switch(type) + { + case primitiveVector: + if (data.vector.indexCount > 1) + { + //----------------------------------------------- + // Set color + //----------------------------------------------- + if (color != 0) + { + default_color = color; + } + graphics_view->SetColor(default_color); + + int + i, + *index_pointer(data.vector.indexList), + index; + Point3D + *dest; + //----------------------------------------------- + // Move to starting point + //----------------------------------------------- + index = *index_pointer++; + + dest = &transformed_vertex_array[index]; + + TransformVertex( + localToView, + untransformed_vertex_array[index], + dest, + transformed_flag_array[index], + scale_factor, + bounds + ); + + + Test_Tell("Start at " << index << "=" << *dest << "\n"); + graphics_view->MoveToAbsolute((int)dest->x,(int)dest->z); + //----------------------------------------------- + // Draw subsequent lines + //----------------------------------------------- + for(i=data.vector.indexCount-1; i>0; --i) + { + index = *index_pointer++; + + dest = &transformed_vertex_array[index]; + + TransformVertex( + localToView, + untransformed_vertex_array[index], + dest, + transformed_flag_array[index], + scale_factor, + bounds + ); + + Test_Tell("Draw to " << index << "=" << *dest << "\n"); + graphics_view->DrawLineToAbsolute((int)(dest->x),(int)(dest->z)); + } + } + break; + default: + Warn("L4GaugeImagePrimitive::Draw: Evil type_id!"); + break; + } + Check_Fpu(); +} + +void + L4GaugeImagePrimitive::TransformVertex( + AffineMatrix &local_to_view, + Point3D &untransformed_vertex, + Point3D *transformed_vertex, + Logical &transformed_flag, + Scalar scale_factor, + Rectangle2D *bounds + ) +{ + Check(this); + Check_Pointer(transformed_vertex); + + //----------------------------------------- + // Transform only if not already done + //----------------------------------------- + if (! transformed_flag) + { + if (attributes & attributeUnscaled) + { + //----------------------------------------- + // Unscaled: pre-multiply by scaling factor + //----------------------------------------- + Point3D + temp; + + temp = untransformed_vertex; + temp *= scale_factor; + Check_Fpu(); + + transformed_vertex->Multiply( + temp, + local_to_view + ); + Check_Fpu(); + } + else + { + //----------------------------------------- + // Normally scaled: transform the vertex + //----------------------------------------- + transformed_vertex->Multiply( + untransformed_vertex, + local_to_view + ); + Check_Fpu(); + } + + //----------------------------------------- + // Round, and fix 'y' sign + //----------------------------------------- + transformed_vertex->x += .5; + transformed_vertex->z = -transformed_vertex->z + .5; + + //----------------------------------------------- + // Set the 'transformed' flag + //----------------------------------------------- + transformed_flag = True; + } + + //----------------------------------------------- + // Accumulate bounds + //----------------------------------------------- + if (bounds != NULL) + { + if (transformed_vertex->x < bounds->bottomLeft.x) + { + bounds->bottomLeft.x = transformed_vertex->x; + } + if (transformed_vertex->x > bounds->topRight.x) + { + bounds->topRight.x = transformed_vertex->x; + } + + if (transformed_vertex->z < bounds->bottomLeft.y) + { + bounds->bottomLeft.y = transformed_vertex->z; + } + if (transformed_vertex->z > bounds->topRight.y) + { + bounds->topRight.y = transformed_vertex->z; + } + } + Check_Fpu(); +} + + + diff --git a/CODE/RP/MUNGA_L4/L4GAUIMA.HPP b/CODE/RP/MUNGA_L4/L4GAUIMA.HPP new file mode 100644 index 0000000..5839586 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4GAUIMA.HPP @@ -0,0 +1,279 @@ +//===========================================================================// +// File: l4gauima.hpp // +// Project: MUNGA Brick: Gauge Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/19/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4GAUIMA_HPP) +# define L4GAUIMA_HPP + +# if !defined(ENTITY_HPP) +# include "entity.hpp" +# endif + +# if !defined(AFFNMTRX_HPP) +# include "affnmtrx.hpp" +# endif + +# if !defined(GRAPH2D_HPP) +# include "graph2d.hpp" +# endif + +# if !defined(MEMSTRM_HPP) +# include "memstrm.hpp" +# endif + + class L4GaugeImage; + class L4GaugeImageList; + class L4GaugeImagePrimitive; + + class L4GaugeImageListResource; + class L4GaugeImagePrimitiveResource; + class L4GaugeImageResource; + + + + //####################################################################### + // L4GaugeImage + //####################################################################### + class L4GaugeImage SIGNATURED + { + public: + //-------------------------------------------------------------------- + // Create L4GaugeImage from memory stream + //-------------------------------------------------------------------- + L4GaugeImage(MemoryStream *mem_stream); + + static L4GaugeImage * + Make(const char *file_name); + static L4GaugeImage * + Make(ResourceDescription::ResourceID new_resource_id); + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + ~L4GaugeImage(); + //-------------------------------------------------------------------- + // TestInstance + //-------------------------------------------------------------------- + Logical + TestInstance() const; + + //-------------------------------------------------------------------- + // CreateL4GaugeImageStream + //-------------------------------------------------------------------- + static ResourceDescription::ResourceID + CreateL4GaugeImageStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + Draw( + Scalar LOD_value, // smaller = more detail (1.0 = 'normal') + Scalar scale_value, // metersPerPixel + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + int boxed_color = 0 + ); + + protected: + static Logical + MemoryStreamWrite( + MemoryStream *mem_stream, + NotationFile *gim_file + ); + + //==================================================================== + // Protected data + //==================================================================== + int + vertexCount, // number of vertices in vertexArray + LODCount; // number of seperate LOD's + Point3D + *vertexArray; // pointer to array of vertices + Scalar + *LODScales; // pointer to array of scalar 'scale' values + L4GaugeImageList + **LODList; + // LODList points to an array of pointers to + // L4GaugeImageLists. + }; + + //####################################################################### + // L4GaugeImageList + //####################################################################### + class L4GaugeImageList SIGNATURED + { + friend class L4GaugeImage; + + protected: + //-------------------------------------------------------------------- + // Create L4GaugeList from memory stream + //-------------------------------------------------------------------- + L4GaugeImageList(MemoryStream *mem_stream); + + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + ~L4GaugeImageList(); + //-------------------------------------------------------------------- + // TestInstance + //-------------------------------------------------------------------- + Logical + TestInstance() const; + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + static Logical + MemoryStreamWrite( + MemoryStream *mem_stream, + NotationFile *gim_file, + const char *page_name + ); + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + int boxed_color + ); + + //==================================================================== + // Protected data + //==================================================================== + int + primitiveCount; // number of primitives in primitiveList + L4GaugeImagePrimitive + **primitiveList; + // primitiveList points to an array of pointers to + // L4GaugeImagePrimitives. + }; + + //####################################################################### + // L4GaugeImagePrimitive + //####################################################################### + class L4GaugeImagePrimitive SIGNATURED + { + friend class L4GaugeImageList; + + protected: + //-------------------------------------------------------------------- + // Create L4GaugeImagePrimitive from memory stream + //-------------------------------------------------------------------- + L4GaugeImagePrimitive(MemoryStream *mem_stream); + static int + CreateL4GaugeImagePrimitiveResource( + NotationFile *gim_file, + const char *gim_name, + const ResourceDirectories *directories, + char *primitive_data, + L4GaugeImagePrimitiveResource *prim_res + ); + + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + ~L4GaugeImagePrimitive(); + //-------------------------------------------------------------------- + // TestInstance + //-------------------------------------------------------------------- + Logical + TestInstance() const; + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + static Logical + MemoryStreamWrite( + MemoryStream *mem_stream, + const char *type_name, + const char *data + ); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + Rectangle2D *bounds + ); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + TransformVertex( + AffineMatrix &local_to_view, + Point3D &untransformed_vertex, + Point3D *transformed_vertex, + Logical &transformed_flag, + Scalar scale_factor, + Rectangle2D *bounds + ); + + //-------------------------------------------------------------------- + // These are the supported attribute types. + //-------------------------------------------------------------------- + enum + { + attributeNormal=0, + attributeUnscaled=0x0001 + }; + //-------------------------------------------------------------------- + // These are the supported primitive types. + //-------------------------------------------------------------------- + enum primitiveType + { + primitiveVector=0, + numberOfTypes + }; + + //==================================================================== + // Protected data + //==================================================================== + int + attributes, // general attributes + color; // a specially parsed attribute + + primitiveType + type; // the primitive's type + + union + { + //-------------------------------- + // type = primitiveVector + //-------------------------------- + struct + { + int + indexCount, // the number of indices + *indexList; // pointer to an array of indices + } + vector; + } + data; + + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4GAUIMM.HPP b/CODE/RP/MUNGA_L4/L4GAUIMM.HPP new file mode 100644 index 0000000..7d2d545 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4GAUIMM.HPP @@ -0,0 +1,7 @@ +//===========================================================================// +// File: l4gaures.hpp // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//===========================================================================// + +// OBSOLETED ON 8-4-95 by cpb. Functionality now contained in L4WRHOUS.HPP diff --git a/CODE/RP/MUNGA_L4/L4GAUTUL.CPP b/CODE/RP/MUNGA_L4/L4GAUTUL.CPP new file mode 100644 index 0000000..90ea793 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4GAUTUL.CPP @@ -0,0 +1,122 @@ +//===========================================================================// +// File: vectlist.cpp // +// Project: MUNGA Brick: Gauge Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/19/95 CPB Initial coding. // +// 06/01/95 CPB Resourcified. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include + +#if !defined(L4GAUIMA_HPP) +# include +#endif + +#if !defined(GAUGALRM_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +ResourceDescription::ResourceID + L4Tool::CreateModelGaugeImageStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + return + L4GaugeImage::CreateL4GaugeImageStream( + resource_file, + model_name, + model_file, + directories + ); +} + +ResourceDescription::ResourceID + L4Tool::CreateModelGaugeMissionReviewStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories */*directories*/ + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + //Check_Pointer(directories); + + ResourceDescription::ResourceID + res_id = ResourceDescription::NullResourceID; + + //---------------------------------------------------------------------- + // Check to see if the model has a mission review page + //---------------------------------------------------------------------- + const char + *pixelmap_name; + + if ( + model_file->GetEntry( + "gaugeMissionReview", + "pixelmap", + &pixelmap_name + ) + ) + { + //------------------------------------------------------------- + // Create a dynamic memory stream, write out the data + //------------------------------------------------------------- + DynamicMemoryStream + *stream = new DynamicMemoryStream(); + + Check(stream); + Register_Object(stream); + + int + length = strlen(pixelmap_name); + MemoryStream_Write(stream, &length); + + for( ; length>0; --length, ++pixelmap_name) + { + MemoryStream_Write(stream, (char *) pixelmap_name); + } + //------------------------------------------------------------- + // Create the resource description, assign an ID + //------------------------------------------------------------- + ResourceDescription + *res_desc_stream = + resource_file->ResourceFile::AddResourceMemoryStream( + model_name, + ResourceDescription::GaugeMissionReviewStreamResourceType, + 1, + ResourceDescription::Preload, + stream + ); + + Check(res_desc_stream); + res_id = res_desc_stream->resourceID; + + Check(stream); + Unregister_Object(stream); + delete stream; + + cout << "GaugeMissionReview res_id = " << res_id << "\n"; + } + //------------------------------------------------------------- + // Return the new ResourceID + //------------------------------------------------------------- + Check_Fpu(); + return res_id; +} + + diff --git a/CODE/RP/MUNGA_L4/L4GREND.CPP b/CODE/RP/MUNGA_L4/L4GREND.CPP new file mode 100644 index 0000000..32b1d90 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4GREND.CPP @@ -0,0 +1,858 @@ +//===========================================================================// +// File: l4grend.cc // +// Project: MUNGA Brick: LBE4 Gauge Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/10/95 CPB Initial coding. // +// 04/12/95 CPB Moved BuildGraphicsPorts in from RP/BTL4GRND.CPP. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4APP_HPP) +# include +#endif + +#if !defined(TIME_HPP) +# include // for profiling +#endif + +#if !defined(L4GREND_HPP) +# include +#endif + +#if !defined(L4GAUGE_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(L4PLASMA_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) cout << n +#else +# define Test_Tell(n) +#endif + +// +//############################################################################# +// L4MethodDescription list +//############################################################################# +// +MethodDescription + ChainToPrevious = METHOD_DESCRIPTION_CHAIN(NULL); // Null:end of chain + +MethodDescription + *L4MethodDescription[] = + { + &MakeConfigMethodDescription, + &MakeExternConfigMethodDescription, + &BackgroundReconfig::methodDescription, + &BackgroundLine::methodDescription, + &BackgroundRect::methodDescription, + &BackgroundFilledRect::methodDescription, + &BackgroundPixelmap::methodDescription, + &BackgroundBitmap::methodDescription, + &NumericDisplayScalar::methodDescription, + &NumericDisplaySpeed::methodDescription, + &NumericDisplayInteger::methodDescription, + &DigitalClock::methodDescription, + &RankAndScore::methodDescription, + &BarGraphSolidScalar::methodDescription, + &BarGraphPixelMapScalar::methodDescription, + &ColorState::methodDescription, + &TwoState::methodDescription, + &SegmentArcNormalized::methodDescription, + &ChainToPrevious + }; + +// +//############################################################################# +// L4GaugeRenderer +//############################################################################# +// +L4GaugeRenderer::L4GaugeRenderer(): + GaugeRenderer() +{ + // + //--------------------------------------------------------------------- + // Ensure that graphicsDisplay is NULL + //--------------------------------------------------------------------- + // + graphicsDisplay = NULL; + externalDisplay = NULL; + + palettesAreActive = True; + scrambleVideoFlag = False; + + char + *mode_string = getenv("L4GAUGE"); + // + //--------------------------------------------------------------------- + // NOTE that L4Application::Initialize() searches for the environment + // variable "L4GAUGE" to determine whether or not to create + // a gauge renderer. + //--------------------------------------------------------------------- + // + if (mode_string != NULL) + { + // + //--------------------------------------------------------------------- + // Attempt to initialize external display + //--------------------------------------------------------------------- + // + char + *plasma_string = getenv("L4PLASMA"); + + if (plasma_string != NULL) + { + if (strnicmp(plasma_string, "COM2", 4) == 0) + { + Tell("Plasma display created on COM2\n"); + externalDisplay = new PlasmaDisplay(PCS_COM2); + } + else + { + Tell("Plasma display created on COM1\n"); + externalDisplay = new PlasmaDisplay(PCS_COM1); + } + + if (externalDisplay != NULL) + { + Register_Object(externalDisplay); + } + } + // + //--------------------------------------------------------------------- + // Attempt to initialize main display + //--------------------------------------------------------------------- + //------------------------------------------------- + // Search notation file for specified resolution + //------------------------------------------------- + // + NotationFile + notation_file("GAUGE\\L4GAUGE.INI"); + + if (!notation_file.PageExists(mode_string)) + { + Tell("L4GaugeRenderer::L4GaugeRenderer - '" << + mode_string << + "' not found in L4GAUGE.INI!\n" + ); + } + else + { + // + //------------------------------------------------- + // Requested resolution exists, read parameters + //------------------------------------------------- + // + int + mode(0), + width(640), + height(480), + page_size(64), + gran(64), + bpl(640*2), + pfp(0), + special(0), + q(0); + + q += notation_file.GetEntry(mode_string, "mode", &mode); + q += notation_file.GetEntry(mode_string, "width", &width); + q += notation_file.GetEntry(mode_string, "height", &height); + q += notation_file.GetEntry(mode_string, "sizeInKB", &page_size); + q += notation_file.GetEntry(mode_string, "granularityInKB", &gran); + q += notation_file.GetEntry(mode_string, "bytesPerLine", &bpl); + q += notation_file.GetEntry(mode_string, "pageFcnPtr", &pfp); + q += notation_file.GetEntry(mode_string, "special", &special); + + if (q == 8) + { + graphicsDisplay = new + SVGA16( + mode, + width, + height, + page_size, + gran, + bpl, + pfp, + special + ); + if (graphicsDisplay != NULL) + { + Register_Object(graphicsDisplay); + } + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// ~L4GaugeRenderer +//############################################################################# +// +L4GaugeRenderer::~L4GaugeRenderer() +{ +# if defined (LOCAL_TEST) + Tell("L4GaugeRenderer::~L4GaugeRenderer()\n"); +# endif + Check(this); + + int i; + + //---------------------------------------------------- + // Make sure all gauges removed first + //---------------------------------------------------- + Remove(0); + //---------------------------------------------------- + // Delete the graphics ports + //---------------------------------------------------- + for(i=0; iUpdatePalette(); + } + + Check_Fpu(); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +Logical + L4GaugeRenderer::ExecuteBackgroundDisplayUpdate() +{ + Check(this); + + Logical + result = False; // False == 'all done' + + //-------------------------------------------------------- + // Update external annunciator + // + // Allow the plasma display to continue if there's + // more background time available. + // + // This method is still called if taskmode is set to + // 'foreground'. If it's called in 'foreground' mode, + // it really means that we're still waiting for foreground + // to begin processing, so we might as well update the + // external display (if needed). + //-------------------------------------------------------- + if (externalDisplay != NULL) + { + Check(externalDisplay); + result = externalDisplay->Update(False); // returns 'False' if done + } + //------------------------------------------------------- + // Update display ONLY in 'copy' mode + //-------------------------------------------------------- + if (taskMode == copy) + { + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + + if (graphicsDisplay->Update(False) == False) + { + //-------------------------------------------------------- + // Tell executionImplementation that we're basically done. + //-------------------------------------------------------- + taskMode = foreground; + } + else + { + result = True; // We're not done yet! + } + } + } + return result; +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + L4GaugeRenderer::NotifyOfNewInterestingEntity( + Entity *interesting_entity + ) +{ + SET_GAUGE_RENDERER(); + Check(this); + Check(interesting_entity); + //---------------------------------------------- + // Make sure gaugeImage exists for entity + //---------------------------------------------- + Check(warehousePointer); + + ((L4Warehouse*)warehousePointer)->gaugeImageBin.Get( + interesting_entity->GetResourceID() + ); + //---------------------------------------------- + // Update gaugeRenderer + //---------------------------------------------- + GaugeRenderer::NotifyOfNewInterestingEntity(interesting_entity); + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntity +//############################################################################# +// +void + L4GaugeRenderer::NotifyOfBecomingUninterestingEntity( + Entity *uninteresting_entity + ) +{ + SET_GAUGE_RENDERER(); + Check(this); + Check(uninteresting_entity); + //---------------------------------------------- + // Remove gaugeImage if no longer used + //---------------------------------------------- + Check(warehousePointer); + + ((L4Warehouse*)warehousePointer)->gaugeImageBin.Release( + uninteresting_entity->GetResourceID() + ); + //---------------------------------------------- + // Update gaugeRenderer + //---------------------------------------------- + GaugeRenderer::NotifyOfBecomingUninterestingEntity(uninteresting_entity); + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); +} + +// +//############################################################################# +// BuildGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::BuildGraphicsPort( + int port_number, + const char *name, + int rotation, + int bitAllocation, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ) +{ + Test_Tell("L4GaugeRenderer::BuildGraphicsPort\n"); + Check(this); + + if (graphicsDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + // + //--------------------------------------------------------- + // If it already exists, delete it + //--------------------------------------------------------- + // + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Test_Tell("...deleting existing port\n"); + Check(graphics_port); + Unregister_Object(graphics_port); + delete graphics_port; + } + // + //--------------------------------------------------------- + // Attempt to create it + //--------------------------------------------------------- + // + graphicsPort[port_number] = new L4GraphicsPort( + (Video16BitBuffered *) graphicsDisplay, + name, + rotation, + bitAllocation, + palette_ID, + enable_ID + ); + + graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + Test_Tell("...new port at " << graphics_port << "\n"); + // + //--------------------------------------------------------- + // If created, register it and build the palette + //--------------------------------------------------------- + // + if (graphics_port != NULL) + { + Check(graphics_port); + Register_Object(graphics_port); + // + // Set the palette for the port + // (Note: secondary uses lowest 8 bits) + // + if ((bitAllocation > 0) && (bitAllocation < 0x0100)) + { + Test_Tell("...secondary\n"); + graphics_port->SetSecondaryPalette(palette); + } + else + { + Test_Tell("...auxiliary\n"); + graphics_port->SetAuxiliaryPalette(); + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// RemapGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::RemapGraphicsPort( + int port_number, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ) +{ + Check(this); + Test_Tell("L4GaugeRenderer::RemapGraphicsPort\n"); + + if (graphicsDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + //--------------------------------------------------------- + // If it exists, change the palette ID and set the palette + //--------------------------------------------------------- + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Check(graphics_port); + // + // Set the palette ID + // + graphics_port->SetPaletteID(palette_ID); + graphics_port->SetEnableID(enable_ID); + + // + // Set the palette for the port + // (Note: secondary uses lowest 8 bits) + // + + int + bit_mask = graphics_port->GetBitMask(); + + if (bit_mask & 0x00FF) // must be secondary + { + Test_Tell("...secondary\n"); + Verify(palette != NULL); + graphics_port->SetSecondaryPalette(palette); + } + else + { + Test_Tell("...auxiliary\n"); + graphics_port->SetAuxiliaryPalette(); + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// BuildExternalGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::BuildExternalGraphicsPort( + int port_number, + const char *name, + int /*bitAllocation*/ + ) +{ + Check(this); + Test_Tell( + "L4GaugeRenderer::BuildExternalGraphicsPort(" << port_number << ")\n" + ); + + if (externalDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + // + //--------------------------------------------------------- + // If it already exists, delete it + //--------------------------------------------------------- + // + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Test_Tell("...deleting existing port\n"); + Check(graphics_port); + Unregister_Object(graphics_port); + delete graphics_port; + } + // + //--------------------------------------------------------- + // Attempt to create it + //--------------------------------------------------------- + // + graphicsPort[port_number] = new L4BytePort( + (Video8BitBuffered *) externalDisplay, + name, + 0 // rotation + ); + + graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + Test_Tell("...new port at " << graphics_port << "\n"); + // + //--------------------------------------------------------- + // If created, register it + //--------------------------------------------------------- + // + if (graphics_port != NULL) + { + Check(graphics_port); + Register_Object(graphics_port); + } + } + Check_Fpu(); +} + +// +//############################################################################# +// FadeToWhite, FadeToGame +//############################################################################# +// +void + L4GaugeRenderer::FadeToWhite(Scalar number_of_seconds) +{ + Check(this); + Verify(number_of_seconds >= 0.0); // zero is allowed (instant change) + +// cout << "L4GaugeRenderer::FadeToWhite(" << number_of_seconds << ")\n"; + + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + ((SVGA16 *)graphicsDisplay)->FadeToWhite(number_of_seconds); + } + Check_Fpu(); +} + +void + L4GaugeRenderer::FadeToNormal(Scalar number_of_seconds) +{ + Check(this); + Verify(number_of_seconds >= 0.0); // zero is allowed (instant change) + +// cout << "L4GaugeRenderer::FadeToNormal(" << number_of_seconds << ")\n"; + + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + ((SVGA16 *)graphicsDisplay)->FadeToPalettes(number_of_seconds); + } + Check_Fpu(); +} + +// +//############################################################################# +// Configure +//############################################################################# +// +void + L4GaugeRenderer::ConfigureForModel( + const char *configuration_name, + Entity *entity + ) +{ + Check(this); + Check_Pointer(configuration_name); + + Test_Tell( + "L4GaugeRenderer::ConfigureForModel(" << + configuration_name << ", " << + entity << ")\n" + ); + + Check(application); + Check(entity); + + Mission + *mission = application->GetCurrentMission(); + Check(mission); + + const char + *model_name = mission->GetGameModel(); + Check_Pointer(model_name); + + char + full_name[64]; + + Str_Copy(full_name, model_name, sizeof(full_name)); + Str_Cat(full_name, configuration_name, sizeof(full_name)); + + Test_Tell( + "L4GaugeRenderer::ConfigureForModel, full_name=" << full_name << + ")\n" + ); + + Configure(full_name, entity); + Check_Fpu(); +} + +// +//############################################################################# +// SpecialEffect +//############################################################################# +// +void + L4GaugeRenderer::SpecialEffect( + VideoEffectType type, + Scalar duration + ) +{ + Check(this); + + switch (type) + { + case scrambleVideo: + if (graphicsDisplay != NULL) + { + scrambleVideoFlag = True; + scrambleVideoTimeout = ((Scalar)Now()) + duration; + + Check(graphicsDisplay); + ((SVGA16*) graphicsDisplay)->FunkyVideo(True); + } + break; + + // other modes go here + + } + Check_Fpu(); +} + +void + L4GaugeRenderer::ProcessVideoEffects() +{ + Check(this); + Check(graphicsDisplay); + + Time + now = Now(); + + if (scrambleVideoFlag) + { + if (now >= scrambleVideoTimeout) + { + scrambleVideoFlag = False; + ((SVGA16*) graphicsDisplay)->FunkyVideo(False); + } + } + + Check_Fpu(); +} + +//-------------------------------------------------------------------- +// Profiling support +//-------------------------------------------------------------------- +Scalar + L4GaugeRenderer::GetCurrentFramePercentage() +{ + Check(this); + return Get_Frame_Percent_Used(); +} + + + + diff --git a/CODE/RP/MUNGA_L4/L4GREND.HPP b/CODE/RP/MUNGA_L4/L4GREND.HPP new file mode 100644 index 0000000..d96d9af --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4GREND.HPP @@ -0,0 +1,182 @@ +//===========================================================================// +// File: l4gauge.hh // +// Project: MUNGA Brick: LBE4 Gauge Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/10/95 CPB Initial coding. // +// 04/12/95 CPB Moved BuildGraphicsPorts in from RP/BTL4GRND.HPP. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4GREND_HPP) +# define L4GREND_HPP + +# if !defined(GAUGREND_HPP) +# include +# endif + +# if !defined(L4VB16_HPP) +# include +# endif + +# if !defined(L4PLASMA_HPP) +# include +# endif + +# if !defined(L4GAUIMA_HPP) +# include +# endif + +# if !defined(L4WRHOUS_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4GaugeRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class L4GaugeRenderer: + public GaugeRenderer + { + public: + + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + L4GaugeRenderer(); + ~L4GaugeRenderer(); + + void + LocalEmergencyShutdown(); + + Logical + TestInstance() const; + + //-------------------------------------------------------------------- + // Profiling support + //-------------------------------------------------------------------- + protected: + Scalar + GetCurrentFramePercentage(); + //-------------------------------------------------------------------- + // GraphicsPort methods + //-------------------------------------------------------------------- + public: + void + BuildGraphicsPort( + int port_number, + const char *name, + int rotation, + int bitAllocation, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ); + + void + RemapGraphicsPort( + int port_number, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ); + + void + BuildExternalGraphicsPort( + int port_number, + const char *name, + int bitAllocation + ); + + // + //-------------------------------------------------------------------- + // 'palette ramping' + //-------------------------------------------------------------------- + // + void + FadeToWhite(Scalar number_of_seconds); + void + FadeToNormal(Scalar number_of_seconds); + // + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- + // + GraphicsDisplay + *GetExternalDisplay() + { + Check(this); + return externalDisplay; + } + + // + //-------------------------------------------------------------------- + // Configuration + //-------------------------------------------------------------------- + // + void + ConfigureForModel( + const char *configuration_name, + Entity *entity + ); + // + //-------------------------------------------------------------------- + // ExecuteImplementation + //-------------------------------------------------------------------- + // + protected: + void + ExecuteForeground(); + Logical + ExecuteBackgroundDisplayUpdate(); + void + LoadMissionImplementation( + Mission *mission + ); + virtual void + NotifyOfNewInterestingEntity(Entity *entity); + virtual void + NotifyOfBecomingUninterestingEntity(Entity *entity); + void + ShutdownImplementation(); + void + SuspendImplementation(); + void + ResumeImplementation(); + // + //-------------------------------------------------------------------- + // Video effects + //-------------------------------------------------------------------- + // + public: + void + SpecialEffect(VideoEffectType type, Scalar duration); + + protected: + + void + ProcessVideoEffects(); + + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + protected: + Logical + palettesAreActive; + + GraphicsDisplay + *graphicsDisplay, + *externalDisplay; + + Logical + scrambleVideoFlag; + Time + scrambleVideoTimeout; + }; + + +#endif diff --git a/CODE/RP/MUNGA_L4/L4HOST.CPP b/CODE/RP/MUNGA_L4/L4HOST.CPP new file mode 100644 index 0000000..bde4310 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4HOST.CPP @@ -0,0 +1,61 @@ +//===========================================================================// +// File: l4host.cpp // +// Project: MUNGA Brick: Connection Library // +// Contents: additional L4 data types and functions for hosts // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/09/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4HOST_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for l4host +// +L4Host::L4Host( + HostID host_ID, + HostType host_type, + NetworkAddress network_address, + unsigned long network_socket, + const CString &net_name): + Host( + host_ID, + host_type, + network_address), + SymbolicName(net_name) +{ + NetworkSocket = network_socket; + // ConnectStatus = NoNetworkConnectionStatus; + pad_head = 0; + pad_tail = 0; + pad_size = L4HOST_PAD_BUFFER_SIZE; + #if defined(TRACE_SEND_BUFFER) + sprintf(sendBufferTraceName,"Send Buffer %d",network_address&0xff); + sendBufferTrace = + new TraceOf( + sendBufferTraceName, + 0, + Trace::IntegerType, + TraceSample::IntegerSnapshot + ); + Register_Object(sendBufferTrace); + sendBufferTrace->TakeSnapshot(4096); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for l4host +// +L4Host::~L4Host() +{ +} + diff --git a/CODE/RP/MUNGA_L4/L4HOST.HPP b/CODE/RP/MUNGA_L4/L4HOST.HPP new file mode 100644 index 0000000..c9bfcb6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4HOST.HPP @@ -0,0 +1,115 @@ +//===========================================================================// +// File: l4host.hpp // +// Project: MUNGA Brick: Connection Library // +// Contents: additional L4 data types and functions for hosts // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/09/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4HOST_HPP) +# define L4HOST_HPP + +# if !defined(HOST_HPP) +# include "host.hpp" +# endif + +# if !defined(CSTR_HPP) +# include "cstr.hpp" +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4Host ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define L4HOST_PAD_BUFFER_SIZE 4096 + + // + //-------------------------------------------------------------------- + // L4Host + // + // Derived from Host, so we can add a place to store the host's network + // socket pointer. + //-------------------------------------------------------------------- + // + + class L4Host: + public Host + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, and testing + //-------------------------------------------------------------------- + // + L4Host( + HostID host_ID, + HostType host_type, + NetworkAddress network_address, + unsigned long NetworkSocket, + const CString &net_name); + ~L4Host(); + // + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- + // +#if 0 + enum ConnectionStatus + { + NoNetworkConnectionStatus, // Initial state, host just created with no net link + OpeningConnectionStatus, // Waiting for completion of an active open to this host + ListeningConnectionStatus, // Waiting for this host to connect to us + OnLineConnectionStatus // Host is on-line and ready + }; + ConnectionStatus + GetConnectStatus() + {return ConnectStatus;} + void + SetConnectStatus(ConnectionStatus new_status) + {ConnectStatus = new_status;} +#endif + unsigned long + GetNetworkSocket() + {return NetworkSocket;} + void + SetNetworkSocket(unsigned long net_socket) + {NetworkSocket = net_socket;} + CString + GetSymbolicName() + {return SymbolicName;} + // + // Nasty to make these things public but I'll have to clean them later + // + public: + #if defined(TRACE_SEND_BUFFER) + TraceOf + *sendBufferTrace; + char + sendBufferTraceName[50]; + #endif + char + pad_buffer[L4HOST_PAD_BUFFER_SIZE]; // a place to buffer up messages + unsigned short + pad_size, // total size of the pad buffer + pad_head, // circular buffer pointers for keeping track of the + pad_tail; // data in the pad buffer. + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + private: + unsigned long + NetworkSocket; // address of the network socket this host uses +#if 0 + ConnectionStatus + ConnectStatus; // current connection status +#endif + CString + SymbolicName; // Text version of net address from egg + }; +#endif diff --git a/CODE/RP/MUNGA_L4/L4ICOM.CPP b/CODE/RP/MUNGA_L4/L4ICOM.CPP new file mode 100644 index 0000000..4a56209 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4ICOM.CPP @@ -0,0 +1,1054 @@ +//===========================================================================// +// File: icom.cpp // +// Project: MUNGA Brick: Controls // +// Contents: Interface specification for intercom class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/18/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4ICOM_HPP) +# include +#endif + +#if !defined(L4HOST_HPP) +# include +#endif + +#if !defined(L4APP_HPP) +# include +#endif + +#if !defined(L4GREND_HPP) +# include +#endif + +#if !defined(HOSTMGR_HPP) +# include +#endif + +//----------------------------------------------------------- +// Timing values (in seconds) for CB button control +// All values derived experimentally +//----------------------------------------------------------- +#define SEEK_STEP_TIME 0.28 // seek step delay +#define NORMAL_STEP_TIME 0.05 // normal step delay +#define BEEP_TIME 0.2 // length of beep + +//----------------------------------------------------------- +// Special code & data to test recalibration: +// set to '1' to create and use 'home' button +//----------------------------------------------------------- +#if 1 +# define HOMETEST + static ControlsButton + resetButton; + enum + { + resetButtonNumber = LBE4ControlsManager::ButtonSecondary6 + }; +#endif +//----------------------------------------------------------- +// Debugging aid +//----------------------------------------------------------- +#if 0 +# define LOCAL_TEST +# define Test_Tell(n) cout << n << flush; +#else +# define Test_Tell(n) +#endif + +//----------------------------------------------------------- +// Button/lamp assignments +//----------------------------------------------------------- +static int + channelButtonNumber[L4Icom::numberOfChannels] = + { + LBE4ControlsManager::ButtonAuxUpperCenter1, + LBE4ControlsManager::ButtonAuxUpperCenter2, + LBE4ControlsManager::ButtonAuxUpperCenter3, + LBE4ControlsManager::ButtonAuxUpperCenter4, + LBE4ControlsManager::ButtonAuxUpperCenter5, + LBE4ControlsManager::ButtonAuxUpperCenter6, + LBE4ControlsManager::ButtonAuxUpperCenter7 + }; + +#if 0 + enum + { + // + // TEST I/O + // + pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8, + homeSensorInput = LBE4ControlsManager::ButtonPanic, + pttRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight5, + ampEnableOutput = LBE4ControlsManager::ButtonAuxLowerRight6, + IncrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight7, + DecrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight8 + }; +#else + enum + { + // + // These are the "real" assignments + // + pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8, + homeSensorInput = LBE4ControlsManager::ButtonIcomSensor, + pttRelayOutput = LBE4ControlsManager::LampIcomPTTRelay, + ampEnableOutput = LBE4ControlsManager::LampIcomAmpEnable, + IncrementRelayOutput = LBE4ControlsManager::LampIcomIncRelay, + DecrementRelayOutput = LBE4ControlsManager::LampIcomDecRelay + }; +#endif + +//----------------------------------------------------------- +// Handy routine to mute audio output +//----------------------------------------------------------- +void + amp_enable(LBE4ControlsManager * controls_manager, Logical on) +{ + controls_manager->SetLamp( + ampEnableOutput, + (on ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidOff + ) + ); + Check_Fpu(); +} + +//########################################################################## +//############################ L4Icom ################################ +//########################################################################## + +//--------------------------------------------------------------------- +// Creator +//--------------------------------------------------------------------- +L4Icom::L4Icom(HostID host_id, int channel_offset) +: +Icom(host_id,0) +{ + Test_Tell("L4Icom::L4Icom(" << host_id << ", " << channel_offset << ")\n"); + Check_Pointer(this); + //-------------------------------------- + // Initialize values + //-------------------------------------- + channelOffset = channel_offset; + + Check(application); + controlsManager = (LBE4ControlsManager *) + application->GetControlsManager(); + Check(controlsManager); + + hardwareChannel = Icom::undefinedChannel; + previousChannel = Icom::undefinedChannel; + previousPTTStatus = False; + //-------------------------------------- + // Clear controls inputs + //-------------------------------------- + homeSensor = 0; + channelButton = 0; + pttButton = 0; + //-------------------------------------- + // Enable only if allowed + //-------------------------------------- + char + *controlString(getenv("L4INTERCOM")); + + if (controlString != NULL) + { + //-------------------------------------- + // Seek channel 40, move to 1st channel + //-------------------------------------- + Recalibrate(); + } + else + { + //-------------------------------------- + // Don't even try. + //-------------------------------------- + state = disabled; + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Destructor +//--------------------------------------------------------------------- +L4Icom::~L4Icom() +{ + Test_Tell("L4Icom::~L4Icom()\n"); + Check(this); + //-------------------------------------- + // Make sure intercom is turned off + //-------------------------------------- + SetPTTStatusValue(False); + amp_enable(controlsManager, False); + //-------------------------------------- + // Make note of failure state + //-------------------------------------- + if (state == failed) + { + Tell("L4Icom::~L4Icom(), Icom had failed!\n"); + NotationFile + *failureFile = new NotationFile("FAILURE.LOG"); + Check(failureFile); + + failureFile->SetEntry("Intercom","seekError",1); + + delete failureFile; + } + //-------------------------------------- + // The plug automatically unlinks + // from the L4Icom Manager upon deletion. + //-------------------------------------- + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Test instance +//--------------------------------------------------------------------- +Logical + L4Icom::TestInstance() const +{ + Icom::TestInstance(); + Check_Fpu(); + return True; +} + +//--------------------------------------------------------------------- +// SetChannelValue +//--------------------------------------------------------------------- +void + L4Icom::SetChannelValue(int new_channel) +{ + Test_Tell("L4Icom::SetChannelValue(" << new_channel << ")\n"); + Check(this); + + if ((state != disabled) && (state != failed)) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + Icom::SetChannelValue(new_channel); + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Set PTTStatusValue +//--------------------------------------------------------------------- +void + L4Icom::SetPTTStatusValue(Logical new_ptt) +{ + Test_Tell("L4Icom::SetPTTStatusValue(" << new_ptt << ")\n"); + Check(this); + + if (state == onChannel) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + Icom::SetPTTStatusValue(new_ptt); + //-------------------------------------- + // Turn on/off PTT output and lamp + //-------------------------------------- + if (previousPTTStatus != PTTStatus) + { + previousPTTStatus = PTTStatus; + + Check(controlsManager); + int + relay_output = + PTTStatus ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidOff; + + controlsManager->SetLamp(pttRelayOutput, relay_output); + + controlsManager->SetLamp( + pttButtonNumber, + (PTTStatus ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidDim + ) + ); + } + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// SetPACaptiveValue +//--------------------------------------------------------------------- +void + L4Icom::SetPACaptiveValue(Logical new_pa) +{ + Test_Tell("L4Icom::SetPACaptiveValue(" << new_pa << ")\n"); + Check(this); + + //----------------------------------------------- + // If entering captivity, disable channel select + //----------------------------------------------- + if (new_pa && (!PACaptive)) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + Icom::SetPACaptiveValue(new_pa); + //-------------------------------------- + // turn off PTT lamp + //-------------------------------------- + controlsManager->SetLamp( + pttButtonNumber, + LBE4ControlsManager::LampSolidOff + ); + //-------------------------------------- + // Turn off channel indicators + //-------------------------------------- + ChannelSelectState(False); + } + //----------------------------------------------- + // If exiting captivity, enable channel select + //----------------------------------------------- + if ((!new_pa) && PACaptive) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + // This must be done BEFORE + // attempting to set the PTT status! + // (hence the duplicated call) + //-------------------------------------- + Icom::SetPACaptiveValue(new_pa); + + ChannelSelectState(True); + previousPTTStatus = 2; // non-Logical value, forces update + SetPTTStatusValue(PTTStatus); // force hardware update + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Recalibrate +//--------------------------------------------------------------------- +void + L4Icom::Recalibrate() +{ + Test_Tell("L4Icom::Recalibrate()\n"); + Check(this); + + seekRequired = False; + timeAccumulator = 0.0; + seekCount = 84; // twice around plus a few more + ChannelSelectState(False); // Turn off selection lamps + amp_enable(controlsManager, False); // turn off the speaker + state = seek40; + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Update +//--------------------------------------------------------------------- +void + L4Icom::Update(Scalar delta_t) +{ + Test_Tell("L4Icom::Update(" << delta_t << ")\n"); + Check(this); + + //------------------------------------------------------------------ + // Do nothing if disabled or failed! + //------------------------------------------------------------------ + if ((state == disabled) || (state == failed)) + { + Check_Fpu(); + return; + } + //------------------------------------------------------------------ + // PTT control + //------------------------------------------------------------------ + if (state == onChannel) + { + if (pttButton > 0) + { + SetPTTStatus(True); + pttButton = 0; + } + else if (pttButton < 0) + { + SetPTTStatus(False); + pttButton = 0; + } + } + else if (previousPTTStatus) + { + SetPTTStatus(False); + } + + //------------------------------------------------------------------ + // Channel selection + //------------------------------------------------------------------ + if (channelSelectEnabled) + { + //-------------------------------------- + // Process button if pressed + //-------------------------------------- + if (channelButton > 0) + { + //-------------------------------------- + // Convert button press to icom channel + //-------------------------------------- + int + button_number = channelButton - 1, // convert to button number + new_channel = Icom::undefinedChannel; + + for(int i=0; i 0) + { + //------------------------------------------- + // Found 40! + //------------------------------------------- + Test_Tell("--> reachedChannel\n"); + hardwareChannel = (40-1); + state = reachedChannel; + //------------------------------------------- + // Display auxiliary intercom labels + //------------------------------------------- + { + Check(application); + + L4GaugeRenderer + *gauge_renderer = ((L4Application *)application)-> + GetGaugeRenderer(); + Check(gauge_renderer); + + gauge_renderer->Configure("intercomEnable", (Entity *) NULL); + } + //------------------------------------------- + // Everybody starts up on the 'first' channel + //------------------------------------------- + if (PACaptive) + { + channelBeforePA = channelOffset; + } + else + { + ChannelSelectState(True); + SetChannel(channelOffset); + } + //------------------------------------------- + // Update the lamp display + //------------------------------------------- + ChannelStatusUpdate(); + } + //------------------------------------------- + // Try next channel + //------------------------------------------- + else + { + DecrementChannel(); + } + } + break; + + //--------------------------------------------------- + case offChannel: + if (WaitedLongEnough(NORMAL_STEP_TIME)) + { + int + delta = channel - hardwareChannel; + if (delta == 0) + { + state = reachedChannel; + } + else + { + //------------------------------------------- + // Choose direction, modulo 40 + //------------------------------------------- + // channel = desired channel + // hardwareChannel = current channel + //------------------------------------------- + if (delta > 20) + { + delta -= 40; + } + else if (delta < -20) + { + delta += 40; + } + + if (delta < 0) + { + DecrementChannel(); + } + else + { + IncrementChannel(); + } + //------------------------------------------- + // Update the lamp display + //------------------------------------------- + ChannelStatusUpdate(); + } + } + break; + + //--------------------------------------------------- + // reachedChannel: this is a delay to allow to CB + // to finish "beeping" before the audio is turned on. + //--------------------------------------------------- + case reachedChannel: + if (WaitedLongEnough(BEEP_TIME)) + { + Test_Tell("L4Icom::Update, reachedChannel --> onChannel\n"); + amp_enable(controlsManager, True); + state = onChannel; + } + break; + //--------------------------------------------------- + case onChannel: + Test_Tell("L4Icom::Update, onChannel\n"); + + if (channel != hardwareChannel) + { + state = offChannel; + timeAccumulator = NORMAL_STEP_TIME; // bypass the delay + amp_enable(controlsManager, False); // mute the output + } + break; + //--------------------------------------------------- + case disabled: + case failed: + break; + } + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// LongEnough +//--------------------------------------------------------------------- +Logical + L4Icom::WaitedLongEnough(Scalar delay_time) +{ + Test_Tell("L4Icom::WaitedLongEnough(" << delay_time >> ") "); + Check(this); + + //------------------------------------------- + // Check to see if delayed long enough + //------------------------------------------- + if (timeAccumulator >= delay_time) + { + Test_Tell("long enough!\n"); + timeAccumulator = 0.0; + Check_Fpu(); + return True; + } + else + { + Test_Tell("\n"); + Check_Fpu(); + return False; + } +} + +//--------------------------------------------------------------------- +// IncrementChannel +//--------------------------------------------------------------------- +void + L4Icom::IncrementChannel() +{ + Test_Tell("L4Icom::IncrementChannel()\n"); + Check(this); + Check(controlsManager); + + //-------------------------------------- + // Increment the channel number counter + //-------------------------------------- + if (++hardwareChannel > (40-1)) + { + hardwareChannel = 0; + } + //-------------------------------------- + // Press the 'inc' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + IncrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // ...and again, for a fixed delay + //-------------------------------------- + controlsManager->SetLamp( + IncrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // Release the 'inc' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + IncrementRelayOutput, + LBE4ControlsManager::LampSolidOff + ); + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// DecrementChannel +//--------------------------------------------------------------------- +void + L4Icom::DecrementChannel() +{ + Test_Tell("L4Icom::DecrementChannel()\n"); + Check(this); + Check(controlsManager); + + //-------------------------------------- + // Decrement the channel number counter + //-------------------------------------- + if (--hardwareChannel < 0) + { + hardwareChannel = (40-1); + } + //-------------------------------------- + // Press the 'dec' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + DecrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // ...and again, for a fixed delay + //-------------------------------------- + controlsManager->SetLamp( + DecrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // Release the 'dec' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + DecrementRelayOutput, + LBE4ControlsManager::LampSolidOff + ); + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// ChannelStatusUpdate +//--------------------------------------------------------------------- +void + L4Icom::ChannelStatusUpdate() +{ + Test_Tell("L4Icom::ChannelStatusUpdate()\n"); + Check(this); + Check(controlsManager); + + int + logical_channel_number; + + if (channelSelectEnabled) + { + //-------------------------------------- + // Has the channel changed? + //-------------------------------------- + if (previousChannel != hardwareChannel) + { + //---------------------------------------- + // Yes. Is the previous channel undefined? + //---------------------------------------- + if (previousChannel != Icom::undefinedChannel) + { + //-------------------------------------- + // No, set previous button to dim + //-------------------------------------- + logical_channel_number = previousChannel - channelOffset; + if (logical_channel_number < L4Icom::numberOfChannels) + { + controlsManager->SetLamp( + channelButtonNumber[logical_channel_number], + LBE4ControlsManager::LampSolidDim + ); + } + } + previousChannel = hardwareChannel; + //-------------------------------------- + // Is the new channel undefined? + //-------------------------------------- + if (previousChannel != Icom::undefinedChannel) + { + //-------------------------------------- + // No, set current button to bright + //-------------------------------------- + logical_channel_number = hardwareChannel - channelOffset; + if (logical_channel_number < L4Icom::numberOfChannels) + { + controlsManager->SetLamp( + channelButtonNumber[logical_channel_number], + LBE4ControlsManager::LampSolidBright + ); + } + } + } + } + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// ChannelSelectState +//--------------------------------------------------------------------- +void + L4Icom::ChannelSelectState(Logical state) +{ + Test_Tell("L4Icom::ChannelStatusUpdate(" << state << ")\n"); + Check(this); + Check(controlsManager); + + int + i, + logical_channel_number; + + if ((state != disabled) && (state != failed)) + { + channelSelectEnabled = True; + + for(i=0; iSetLamp( + channelButtonNumber[i], + (i==logical_channel_number ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidDim + ) + ); + } + } + else + { + channelSelectEnabled = False; + + for(i=0; iSetLamp( + channelButtonNumber[i], + LBE4ControlsManager::LampSolidOff + ); + } + } + Check_Fpu(); +} + +//########################################################################## +//######################## L4IcomManager ############################# +//########################################################################## + +//-------------------------------------------------------------------------- +// Virtual Data support +// + +Derivation + L4IcomManager::ClassDerivations( + IcomManager::ClassDerivations, + "L4IcomManager" + ); + +L4IcomManager::SharedData + L4IcomManager::DefaultData( + L4IcomManager::ClassDerivations, + L4IcomManager::MessageHandlers + ); + +//-------------------------------------------------------------------------- +// Creator +// + +L4IcomManager::L4IcomManager( + SharedData &shared_data +): + IcomManager(shared_data), + localIcom(NULL) +{ + Test_Tell("L4IcomManager::L4IcomManager()\n"); + Check_Pointer(this); + + previousUpdateTime = Now(); + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +// Destructor +// +L4IcomManager::~L4IcomManager() +{ + Test_Tell("L4IcomManager::~L4IcomManager()\n"); + Check(this); + + // We don't need to delete the local Icom object: it's a member + // of the instanceList in the IcomManager class, which is deleted + // by the IcomManager destructor. + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +Logical + L4IcomManager::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +//-------------------------------------------------------------------------- +L4Icom * + L4IcomManager::MakeIcom(HostID host_id, int /*unit_number*/) +{ + Test_Tell("L4IcomManager::MakeIcom(" << host_id << ")\n"); + Check(this); + + //------------------------------------------ + // Create, register icom object + //------------------------------------------ + L4Icom + *icom = new L4Icom(host_id, 0); // HACK - eventually set channel offset based on cockpit group! + Check(icom); + Register_Object(icom); + //------------------------------------------ + // Add to global list + //------------------------------------------ + instanceList.Add(icom); + //------------------------------------------ + // Get local host ID + // (we need to do because the local host is + // created quite late in the whole process) + //------------------------------------------ + Check(application); + HostManager + *host_manager = application->GetHostManager(); + Check(host_manager); + Host + *local_host = host_manager->GetLocalHost(); + Check(local_host); + HostID + local_host_id = local_host->GetHostID(); + //------------------------------------------ + // If assigned to a local host, make + // this intercom object local as well + //------------------------------------------ + Test_Tell( + "L4IcomManager::MakeIcom local_host_id = " << local_host_id << "\n" + ); + Test_Tell( + "L4IcomManager::MakeIcom host_id = " << host_id << "\n" + ); + if (host_id == local_host_id) + { + Test_Tell("L4IcomManager::MakeIcom, set local icom\n"); + //----------------------------------------------------------------- + // Set localIcom socket + //----------------------------------------------------------------- + Verify(localIcom.GetCurrent() == NULL); + localIcom.AddPlug(icom); + //----------------------------------------------------------------- + // Add connections + //----------------------------------------------------------------- +#if 0 + Check(icom->controlsManager); + ControlsUpdateManager + *button_pointer; + //------------------------------------------ + // Add connection to home sensor + //------------------------------------------ + button_pointer = &icom->controlsManager->buttonGroup[homeSensorInput]; + Check(button_pointer); + button_pointer->Add( + ModeManager::ModeAlwaysActive, &icom->homeSensor, icom + ); + //------------------------------------------ + // Add connections to channel buttons + //------------------------------------------ + for(int i=0; icontrolsManager->buttonGroup[channelButtonNumber[i]]; + Check(button_pointer); + button_pointer->Add( + L4ModeManager::ModeIntercom, &icom->channelButton, icom + ); + icom->controlsManager->MakeLinkedLamp(channelButtonNumber[i]); + } +# if defined(HOMETEST) + //------------------------------------------ + // Add connection to reset button + //------------------------------------------ + button_pointer = + &icom->controlsManager->buttonGroup[resetButtonNumber]; + Check(button_pointer); + button_pointer->Add( + ModeManager::ModeAlwaysActive, &resetButton, icom + ); + + resetButton = 0; +# endif + //------------------------------------------ + // Add connection to PTT button + //------------------------------------------ + button_pointer = &icom->controlsManager->buttonGroup[pttButtonNumber]; + Check(button_pointer); + button_pointer->Add( + ModeManager::ModeAlwaysActive, &icom->pttButton, icom + ); + icom->controlsManager->MakeLinkedLamp(pttButtonNumber); +#endif + } + + Check_Fpu(); + return icom; +} + +//-------------------------------------------------------------------------- +void + L4IcomManager::LoadMission(Mission *mission) +{ + Check(this); + IcomManager::LoadMission(mission); + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + L4IcomManager::Shutdown() +{ + Check(this); + IcomManager::Shutdown(); + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + L4IcomManager::Execute() +{ +// Test_Tell("L4IcomManager::Execute()\n"); + Check(this); + + Scalar + delta_t; + Time + right_now; + +# if defined(HOMETEST) + //------------------------------------------ + // If reset button pressed, recalibrate + //------------------------------------------ + if (resetButton > 0) + { + resetButton = 0; + + L4Icom + *local_icom = localIcom.GetCurrent(); + + if (local_icom != NULL) + { + cout << "L4IcomManager::Execute, Reset!!!!!\n"; + local_icom->Recalibrate(); + } + } +# endif + //------------------------------------------ + // Get time, generate delta_t + //------------------------------------------ + right_now = Now(); + delta_t = (Scalar) (right_now - previousUpdateTime); + + if (delta_t > 0.0) + { + previousUpdateTime = right_now; + //------------------------------------------ + // Process local icom object + //------------------------------------------ + L4Icom + *local_icom = localIcom.GetCurrent(); + + if (local_icom != NULL) + { + local_icom->Update(delta_t); + } + } + Check_Fpu(); +} diff --git a/CODE/RP/MUNGA_L4/L4ICOM.HPP b/CODE/RP/MUNGA_L4/L4ICOM.HPP new file mode 100644 index 0000000..8edc7be --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4ICOM.HPP @@ -0,0 +1,194 @@ +//===========================================================================// +// File: icom.hpp // +// Project: MUNGA Brick: Controls // +// Contents: Interface specification for intercom class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/14/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4ICOM_HPP) +# define L4ICOM_HPP + +# if !defined(ICOM_HPP) +# include +# endif + +# if !defined(L4CTRL_HPP) +# include +# endif + +# if !defined(TIME_HPP) +# include +# endif + + //########################################################################## + //############################ L4Icom ################################ + //########################################################################## + class L4Icom: + public Icom + { + friend class L4IcomManager; + + public: + L4Icom(HostID host_id, int channel_offset); + ~L4Icom(); // base destructor is virtual + Logical + TestInstance() const; + + //-------------------------------------------------- + // Channel offset accessor + //-------------------------------------------------- + int + GetChannelOffset() + { + Check(this); + return channelOffset; + } + //-------------------------------------------------- + // public data + //-------------------------------------------------- + ControlsButton + pttButton; + + enum + { + numberOfChannels=7 + }; + + protected: + //-------------------------------------------------- + // These methods are used to locally set the value + // for the channel, PTT, and PA status. + // + // The difference between these methods and the + // public methods defined in the base class is that + // these methods are called by both the base class + // public routines and the event receiver to actually + // set the values involved. Making them virtual + // allows derived classes to be notified of changes + // (but also requires that all derived classes + // explicitly call the overridden methods!) + //-------------------------------------------------- + void + SetChannelValue(int new_channel); // base method is virtual + void + SetPTTStatusValue(Logical new_ptt); // base method is virtual + void + SetPACaptiveValue(Logical new_pa); // base method is virtual + //-------------------------------------------------- + // Recalibrate hardware + //-------------------------------------------------- + void + Recalibrate(); + //-------------------------------------------------- + // Hardware control method + //-------------------------------------------------- + void + Update(Scalar delta_t); + + private: + Logical + WaitedLongEnough(Scalar how_long); + void + IncrementChannel(); + void + DecrementChannel(); + void + ChannelStatusUpdate(); + void + ChannelSelectState(Logical state); + //-------------------------------------------------- + // Protected data + //-------------------------------------------------- + protected: + LBE4ControlsManager + *controlsManager; + + ControlsButton + homeSensor, + channelButton; + Scalar + timeAccumulator; + int + hardwareChannel, + previousChannel, + channelOffset, + seekCount; + int + previousPTTStatus; + Logical + channelSelectEnabled, + seekRequired; + enum + { + disabled = -2, + failed = -1, + seek40, + offChannel, + reachedChannel, + onChannel, + } + state; + }; + + //########################################################################## + //######################## L4IcomManager ############################# + //########################################################################## + class L4IcomManager: + public IcomManager + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + L4IcomManager( + SharedData &shared_data=DefaultData + ); + ~L4IcomManager(); // base destructor is virtual + + Logical + TestInstance() const; + + L4Icom * + MakeIcom(HostID host_id, int unit_number=0); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // LoadMission, Shutdown methods + // ...these are declared virtual in ICOM.HPP and must chain back to + // the previous methods. + // + public: + void + LoadMission(Mission *mission); + void + Shutdown(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Periodic update function + // + void + Execute(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // protected data + // + protected: + Time + previousUpdateTime; + + SlotOf + localIcom; + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4JOYSTK.HPP b/CODE/RP/MUNGA_L4/L4JOYSTK.HPP new file mode 100644 index 0000000..b366452 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4JOYSTK.HPP @@ -0,0 +1,118 @@ +//===========================================================================// +// File: PCjoystk.hh // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC joystick interface routines // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// ??/??/?? JMA Initial coding. // +// 01/04/95 CPB Made pretty. // +// 01/20/95 CPB Added PC_Joystick_Mask // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(L4JOYSTK_HPP) + +# define L4JOYSTK_HPP + +# if !defined(STYLE_HPP) +# include "c:\source\munga\style.hpp" +# endif + +# define PCJ1_Button1 0x10 +# define PCJ1_Button2 0x20 +# define PCJ2_Button1 0x40 +# define PCJ2_Button2 0x80 +# define PC_All_Buttons 0xF0 + + // These are used to build "mask" values, below +# define PCJ_AnalogChannel1 0x01 +# define PCJ_AnalogChannel2 0x02 +# define PCJ_AnalogChannel3 0x04 +# define PCJ_AnalogChannel4 0x08 +# define PC_All_Analog 0x0F + + // Definitions for standard old 2-axis joystick +# define PCJ_Standard_Button1 0x10 +# define PCJ_Standard_Button2 0x20 +# define PCJ_Standard_Mask PCJ_AnalogChannel1|PCJ_AnalogChannel2 + + // Definitions for Flightstick Pro (CH products) + // + // These states are mutually exclusive and ordered by decreasing + // priority (only the highest priority state is returned). + // Yes, this means that you cannot activate two states at a time: + // while you hold the "thumb joystick", you cannot fire. +# define PCJ_FSP_Up 0xF0 // "thumb joystick" up +# define PCJ_FSP_Down 0x70 // "thumb joystick" down +# define PCJ_FSP_Left 0x30 // "thumb joystick" left +# define PCJ_FSP_Right 0xB0 // "thumb joystick" right +# define PCJ_FSP_Trigger 0x10 // Trigger +# define PCJ_FSP_LButton 0x20 // Leftmost button +# define PCJ_FSP_RButton 0x40 // Rightmost button +# define PCJ_FSP_CButton 0x80 // Center button + +# define PCJ_FSP_Mask PCJ_AnalogChannel1|PCJ_AnalogChannel2|\ + PCJ_AnalogChannel4 + + // Handy equates for reading the analog values +# define PCJ_FSP_X PC_Joystick1_Raw_X; +# define PCJ_FSP_Y PC_Joystick1_Raw_Y; +# define PCJ_FSP_Dial PC_Joystick2_Raw_Y; + + // Definitions for Thrustmaster + // + // The "hat" actually is connected to resistors on + // analog channel 3. + // Full value is open + // Up is low value + // Down is 1/2 value + // Left is 3/4 value + // Right is 1/4 value + // +# define PCJ_TM_Trigger 0x10 // Trigger +# define PCJ_TM_ThumbHigh 0x20 // Button next to "hat" +# define PCJ_TM_ThumbMid 0x40 // Button halfway down stick +# define PCJ_TM_ThumbLow 0x80 // Lowest thumb button + +# define PCJ_TM_Mask PCJ_AnalogChannel1|PCJ_AnalogChannel2|\ + PCJ_AnalogChannel4 + + // Handy equates for reading the analog values +# define PCJ_FSP_X PC_Joystick1_Raw_X; +# define PCJ_FSP_Y PC_Joystick1_Raw_Y; +# define PCJ_FSP_Dial PC_Joystick2_Raw_Y; + + + extern "C" Word PC_Joystick1_Raw_X, PC_Joystick1_Raw_Y; + extern "C" Word PC_Joystick2_Raw_X, PC_Joystick2_Raw_Y; + extern "C" Byte PC_Joystick_Buttons; + + // + // The PC_Joystick_Mask defaults at power-up to all four channels. + // It should be set according to one of the PCJ_...Mask values from above. + // This will speed up joystick updates by ignoring unused analog channels. + // + extern "C" Byte PC_Joystick_Mask; + + extern "C" void PC_Joystick_Update(void); + + extern "C" void test1(void); + extern "C" void test2(Byte a, Word b, LWord l, char *p); + extern "C" void test3(void); + extern "C" void test4(Byte a, Word b, LWord l, char *p); + + // + // In watcom, force stack-based addressing + // + +# if defined(__WATCOMC__) +# pragma aux PC_Joystick_Update parm []; +# pragma aux test1 parm []; +# pragma aux test2 parm []; +# pragma aux test3 parm []; +# pragma aux test4 parm []; +# endif + +#endif diff --git a/CODE/RP/MUNGA_L4/L4KEYBD.CPP b/CODE/RP/MUNGA_L4/L4KEYBD.CPP new file mode 100644 index 0000000..97ecbe3 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4KEYBD.CPP @@ -0,0 +1,37 @@ +//===========================================================================// +// File: PCkeybd.cc // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC keyboard interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/19/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#include +#include + +int PC_Keyboard_Read(void) +{ + int c; + + if (!kbhit()) // if keyboard has not been hit, return zero + { + return(0); + } + else + { + c = getch(); // keyboard was hit, get code + if (c == 0) // zero: next character is extended code + { + c = getch() | 0x0100; // flag as extended + } + return(c); // return the value + } +} diff --git a/CODE/RP/MUNGA_L4/L4KEYBD.HPP b/CODE/RP/MUNGA_L4/L4KEYBD.HPP new file mode 100644 index 0000000..2c563fe --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4KEYBD.HPP @@ -0,0 +1,142 @@ +//===========================================================================// +// File: l4keybd.hpp // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC keyboard interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/19/95 CPB Initial coding. // +// 11/16/95 KEO Add additional keycodes. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// +#if !defined(L4KEYBD_HPP) +# define L4KEYBD_HPP + +# if !defined(STYLE_HPP) +# include +# endif + // + //---------------------------------------------------------------- + // Handy keycode definitions + //---------------------------------------------------------------- + // +# define PCK_ESC 0x001B // "escape" key +# define PCK_ENTER 0x000D // the ever-popular "enter" key +# define PCK_TAB 0x0009 // the obvious "tab" key + // + //---------------------------------------------------------------- + // Extended keycodes: function keys + //---------------------------------------------------------------- + // +# define PCK_F1 0x013B +# define PCK_F2 0x013C +# define PCK_F3 0x013D +# define PCK_F4 0x013E +# define PCK_F5 0x013F +# define PCK_F6 0x0140 +# define PCK_F7 0x0141 +# define PCK_F8 0x0142 +# define PCK_F9 0x0143 +# define PCK_F10 0x0144 +# define PCK_F11 0x0185 +# define PCK_F12 0x0186 + // + //---------------------------------------------------------------- + // Extended keycodes: ctrl-function keys + //---------------------------------------------------------------- + // +# define PCK_CTL_F1 0x015E +# define PCK_CTL_F2 0x015F +# define PCK_CTL_F3 0x0160 +# define PCK_CTL_F4 0x0161 +# define PCK_CTL_F5 0x0162 +# define PCK_CTL_F6 0x0163 +# define PCK_CTL_F7 0x0164 +# define PCK_CTL_F8 0x0165 +# define PCK_CTL_F9 0x0166 +# define PCK_CTL_F10 0x0167 +# define PCK_CTL_F11 0x0189 +# define PCK_CTL_F12 0x018A + // + //---------------------------------------------------------------- + // Extended keycodes: alt-function keys + //---------------------------------------------------------------- + // +# define PCK_ALT_F1 0x0168 +# define PCK_ALT_F2 0x0169 +# define PCK_ALT_F3 0x016A +# define PCK_ALT_F4 0x016B +# define PCK_ALT_F5 0x016C +# define PCK_ALT_F6 0x016D +# define PCK_ALT_F7 0x016E +# define PCK_ALT_F8 0x016F +# define PCK_ALT_F9 0x0170 +# define PCK_ALT_F10 0x0171 +# define PCK_ALT_F11 0x018B +# define PCK_ALT_F12 0x018C + // + //---------------------------------------------------------------- + // Extended keycodes: cursor keys (numeric keypad WITH NUMLOCK OFF!) + //---------------------------------------------------------------- + // +# define PCK_INS 0x0152 +# define PCK_DEL 0x0153 +# define PCK_HOME 0x0147 +# define PCK_UP 0x0148 +# define PCK_PGUP 0x0149 +# define PCK_LEFT 0x014B +# define PCK_RIGHT 0x014D +# define PCK_END 0x014F +# define PCK_DOWN 0x0150 +# define PCK_PGDN 0x0151 + // + //---------------------------------------------------------------- + // Extended keycodes: ctrl-cursor keys + //---------------------------------------------------------------- + // +# define PCK_CTL_INS 0x0192 +# define PCK_CTL_DEL 0x0193 +# define PCK_CTL_HOME 0x0177 +# define PCK_CTL_UP 0x018D +# define PCK_CTL_PGUP 0x0184 +# define PCK_CTL_LEFT 0x0173 +# define PCK_CTL_RIGHT 0x0174 +# define PCK_CTL_END 0x0175 +# define PCK_CTL_DOWN 0x0191 +# define PCK_CTL_PGDN 0x0176 + // + //---------------------------------------------------------------- + // Extended keycodes: alt-cursor keys + //---------------------------------------------------------------- + // +# define PCK_ALT_INS 0x01A2 +# define PCK_ALT_DEL 0x01A3 +# define PCK_ALT_HOME 0x0197 +# define PCK_ALT_UP 0x0198 +# define PCK_ALT_PGUP 0x0199 +# define PCK_ALT_LEFT 0x019B +# define PCK_ALT_RIGHT 0x019D +# define PCK_ALT_END 0x019F +# define PCK_ALT_DOWN 0x01A0 +# define PCK_ALT_PGDN 0x01A1 + // + //---------------------------------------------------------------- + // Extended keycodes: alt-keys + //---------------------------------------------------------------- + // +# define PCK_ALT_W 0x0111 +# define PCK_ALT_R 0x0113 +# define PCK_ALT_P 0x0119 +# define PCK_ALT_F 0x0121 +# define PCK_ALT_K 0x0125 +# define PCK_ALT_V 0x012F +# define PCK_ALT_SLASH 0x0135 + + extern int PC_Keyboard_Read(void); // returns code or zero if no key + +#endif +//===========================================================================// + diff --git a/CODE/RP/MUNGA_L4/L4LAMP.CPP b/CODE/RP/MUNGA_L4/L4LAMP.CPP new file mode 100644 index 0000000..baa62c1 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4LAMP.CPP @@ -0,0 +1,411 @@ +//===========================================================================// +// File: l4lamp.cpp // +// Project: MUNGA Brick: LBE4 Gauge Renderer // +// Contents: LBE4 Lamp manager code // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/19/96 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#define PRELOAD_ART + +#if !defined(VDATA_HPP) +# include +#endif + +#if !defined(L4LAMP_HPP) +# include +#endif + +#if !defined(L4WRHOUS_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) cout << n +#else +# define Test_Tell(n) +#endif + +//######################################################################### +//############################# L4LampManager ############################# +//######################################################################### +L4LampManager::L4LampManager(LBE4ControlsManager *controls_manager): + LampManager() +{ + Check(controls_manager); + controlsManager = controls_manager; + + previousLampState = new int[LBE4ControlsManager::LampCount]; + Register_Pointer(previousLampState); + lampActiveFlag = new Logical[LBE4ControlsManager::LampCount]; + Register_Pointer(lampActiveFlag); + //----------------------------------------- + // Clear L4 lamp state tables + //----------------------------------------- + int + i; + + Check_Pointer(previousLampState); + for(i=0; i< LBE4ControlsManager::LampCount; ++i) + { + previousLampState[i] = RIO::solid + RIO::state1Off + RIO::state2Off; + } + Check_Fpu(); +} + +L4LampManager::~L4LampManager() +{ + Check(this); + + Unregister_Pointer(previousLampState); + delete[] previousLampState; + previousLampState = NULL; + + Unregister_Pointer(lampActiveFlag); + delete[] lampActiveFlag; + lampActiveFlag = NULL; + + Check_Fpu(); +} + +Logical + L4LampManager::TestInstance() const +{ + Check_Fpu(); + return LampManager::TestInstance(); +} + +void + L4LampManager::Update(ModeMask current_mode_mask) +{ + Check(this); + Logical + flush_inactive_lamps = (current_mode_mask != previousModeMask); + int + i; + + if (flush_inactive_lamps) + { + //--------------------------------------- + // Mark all lamps as inactive + //--------------------------------------- + Check_Pointer(lampActiveFlag); + for(i=0; i< LBE4ControlsManager::LampCount; ++i) + { + lampActiveFlag[i] = False; + } + } + //--------------------------------------- + // Update LampManager, set lamp outputs, + // and mark active lamps + //--------------------------------------- + LampManager::Update(current_mode_mask); + + if (flush_inactive_lamps) + { + //--------------------------------------- + // Turn off inactive lamps + //--------------------------------------- + Check_Pointer(lampActiveFlag); + for(i=0; i< LBE4ControlsManager::LampCount; ++i) + { + if (lampActiveFlag[i] == False) + { + AssertNewLampValue(i, RIO::solid+RIO::state1Off+RIO::state2Off); + } + } + } + Check_Fpu(); +} + +void + L4LampManager::AssertNewLampValue(int lamp_number, int lamp_value) +{ + Check(this); + + Verify(lamp_number >= 0); + Verify(lamp_number < LBE4ControlsManager::LampCount); + //-------------------------------------- + // Update external hardware + //-------------------------------------- + Check_Pointer(previousLampState); + if (previousLampState[lamp_number] != lamp_value) + { + previousLampState[lamp_number] = lamp_value; + //-------------------------------------- + // Send RIO command to update L4 lamp + //-------------------------------------- + Check(controlsManager); + controlsManager->SetLamp(lamp_number, lamp_value); + } + + Check_Fpu(); +} + +//######################################################################### +//################################ L4Lamp ################################# +//######################################################################### +L4Lamp::L4Lamp( + LampID lamp_number, + ModeMask mode_mask, + L4LampManager *lamp_manager +) : + Lamp(lamp_number, mode_mask, (LampManager *) lamp_manager) +{ + automatic = True; + automaticValue = (ControlsButton) 0; + previousAutomaticValue = automaticValue; + + SetState(LampStateDim); + + Check_Fpu(); +} + +L4Lamp::~L4Lamp() +{ + Check(this); + SetState(LampStateOff); + Check_Fpu(); +} + +Logical + L4Lamp::TestInstance() const +{ + return Lamp::TestInstance(); +} + +void + L4Lamp::SetAutomaticOperation(Logical automatic_flag) +{ + Check(this); + automatic = automatic_flag; + Check_Fpu(); +} + +void + L4Lamp::Update(Logical force_notification) +{ + Check(this); + + //-------------------------------------- + // Tell manager we're still active + //-------------------------------------- + if (lampID >= 0) + { + if (lampID < LBE4ControlsManager::LampCount) + { + Check_Pointer(((L4LampManager *)manager)->lampActiveFlag); + ((L4LampManager *)manager)->lampActiveFlag[lampID] = True; + } + } + //-------------------------------------- + // Update state if automatic + //-------------------------------------- + if (automatic) + { + if (previousAutomaticValue != automaticValue) + { + previousAutomaticValue = automaticValue; + + if (previousAutomaticValue > 0) + { + SetState(LampStateOn); + } + else + { + SetState(LampStateDim); + } + } + else if (force_notification) + { + NotifyOfStateChange(); + } + } + else if (force_notification) + { + NotifyOfStateChange(); + } + Check_Fpu(); +} + +void + L4Lamp::NotifyOfStateChange() +{ + Check(this); + Check((L4LampManager *) manager); + + int + output_value; + + if (alertActive) + { + switch(previousState) + { + default: + output_value = RIO::flashFast + RIO::state1Off + RIO::state2Dim; + break; + + case LampStateDim: + case LampStateOn: + output_value = RIO::flashFast + RIO::state1Dim + RIO::state2Bright; + break; + } + } + else + { + switch(previousState) + { + default: + output_value = RIO::solid + RIO::state1Off + RIO::state2Off; + break; + + case LampStateDim: + output_value = RIO::solid + RIO::state1Dim + RIO::state2Dim; + break; + + case LampStateOn: + output_value = RIO::solid + RIO::state1Bright + RIO::state2Bright; + break; + } + } + + ((L4LampManager *) manager)->AssertNewLampValue(lampID, output_value); + Check_Fpu(); +} + +//######################################################################### +//############################# L4VirtualLamp ############################# +//######################################################################### +L4GraphicLamp::L4GraphicLamp( + LampID lamp_id, + ModeMask mode_mask, + GaugeRenderer *the_renderer, + int graphics_port_number, + int left, int bottom, + const char *map_name, + int bg_color, int fg_color, + Logical opaque_flag +) : + GraphicLamp( + lamp_id, + mode_mask, + the_renderer->GetLampManager(), + the_renderer, + graphics_port_number + ) +{ + //-------------------------------------------- + // Build copy of map name + //-------------------------------------------- + Check_Pointer(map_name); + mapName = new char[strlen(map_name)+1]; + Register_Pointer(mapName); + strcpy(mapName, map_name); + //-------------------------------------------- + // Get the image + //-------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + warehouse->bitMapBin.Get(mapName); +# endif + + opaque = opaque_flag; + bgColor = bg_color; + fgColor = fg_color; + localView.SetOrigin(left, bottom); + Check_Fpu(); +} + +L4GraphicLamp::~L4GraphicLamp() +{ + Check(this); + Check_Pointer(mapName); + //-------------------------------------------- + // Release the preloaded image + //-------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + warehouse->bitMapBin.Release(mapName); +# endif + //-------------------------------------------- + // Delete the copy of the name + //-------------------------------------------- + Check_Pointer(mapName); + delete[] mapName; + mapName = NULL; + Check_Fpu(); +} + +Logical + L4GraphicLamp::TestInstance() const +{ + return GraphicLamp::TestInstance(); +} + +void + L4GraphicLamp::NotifyOfStateChange() +{ + Check(this); + //-------------------------------------------- + // Get the bitmap + //-------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + BitMap + *bitmap = warehouse->bitMapBin.Get(mapName); + + if (bitmap != NULL) + { + Check(bitmap); + //-------------------------------------------- + // Set the color + //-------------------------------------------- + if (previousState <= LampStateOff) + { + localView.SetColor(bgColor); + } + else + { + localView.SetColor(fgColor); + } + //-------------------------------------------- + // Draw the bitmap + //-------------------------------------------- + if (opaque) + { + localView.DrawBitMapOpaque(bgColor, 0, bitmap); + } + else + { + localView.DrawBitMap(0, bitmap); + } + //-------------------------------------------- + // Release the bitmap + //-------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(mapName); + } + Check_Fpu(); +} + diff --git a/CODE/RP/MUNGA_L4/L4LAMP.HPP b/CODE/RP/MUNGA_L4/L4LAMP.HPP new file mode 100644 index 0000000..c137cb1 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4LAMP.HPP @@ -0,0 +1,169 @@ +//===========================================================================// +// File: l4lamp.hpp // +// Project: MUNGA Brick: Gauge Module // +// Contents: Interface specification for L4 Lamps // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/16/96 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4LAMP_HPP) +# define L4LAMP_HPP + + class L4LampManager; + class L4Lamp; + class L4GraphicLamp; + +# if !defined(LAMP_HPP) +# include "lamp.hpp" +# endif + +# if !defined(L4CTRL_HPP) +# include "l4ctrl.hpp" +# endif + + //######################################################################### + //############################# L4LampManager ############################# + //######################################################################### + class L4LampManager: + public LampManager + { + friend class L4Lamp; + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- + public: + L4LampManager(LBE4ControlsManager *controls_manager); + ~L4LampManager(); + + Logical + TestInstance() const; + + virtual void + Update(ModeMask current_mode_mask); + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- + protected: + void + AssertNewLampValue(int lamp_number, int lamp_value); + + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- + protected: + LBE4ControlsManager + *controlsManager; + int + *previousLampState; + Logical + *lampActiveFlag; + }; + + //######################################################################### + //################################ L4Lamp ################################# + //######################################################################### + class L4Lamp : + public Lamp + { + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- + public: + enum + { + LampStateDim = Lamp::NextLampState, + NextLampState + }; + + L4Lamp( + LampID lamp_number, + ModeMask mode_mask, + L4LampManager *lamp_manager + ); + + ~L4Lamp(); + + Logical + TestInstance() const; + + void + SetAutomaticOperation(Logical automatic_flag = True); + + protected: + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- + void + Update(Logical force_notify_of_state_change = False); + void + NotifyOfStateChange(); + //---------------------------------------------------------------------- + // Public data + //---------------------------------------------------------------------- + public: + ControlsButton + automaticValue; // controls lampState if 'automatic' is true + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- + protected: + ControlsButton + previousAutomaticValue; + Logical + automatic; + int + alertValue; + }; + + //######################################################################### + //############################# L4GraphicLamp ############################# + //######################################################################### + class L4GraphicLamp : + public GraphicLamp + { + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- + public: + L4GraphicLamp( + LampID lamp_number, + ModeMask mode_mask, + GaugeRenderer *renderer, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int bg_color, int fg_color, + Logical opaque_flag = True + ); + + ~L4GraphicLamp(); + + Logical + TestInstance() const; + + protected: + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- + void + NotifyOfStateChange(); + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- + protected: + Logical + opaque; + char + *mapName; + int + bgColor, + fgColor; + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4MOUSE.CPP b/CODE/RP/MUNGA_L4/L4MOUSE.CPP new file mode 100644 index 0000000..5f9384a --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4MOUSE.CPP @@ -0,0 +1,188 @@ +//===========================================================================// +// File: PCmouse.cc // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC mouse interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/24/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4MOUSE_HPP) +# include +#endif + +#define MOUSEINT 0x33 + +// +//############################################################################ +// Creator - reset the driver and check for existence +// +//############################################################################ +// +Mouse::Mouse() +{ + Check_Pointer(this); + + // + //----------------------------------------------- + // Reset driver and read status + //----------------------------------------------- + // + _AX = 0; + geninterrupt(MOUSEINT); + + // + //----------------------------------------------- + // AX will be zero if error, 0xFFFF if ok. + // BX is the number of buttons. + //----------------------------------------------- + // + if (_AX == 0xFFFF) + { + ButtonCount = _BX; + Errors = 0; + } + else + { + Errors = 1; + ButtonCount = 0; + } + Check_Fpu(); +} + +Logical + Mouse::TestInstance() const +{ + return True; +} + +// +//############################################################################ +// ReadCounters - return how many 'mickeys' the mouse has moved +// since the last call +//############################################################################ +// +void + Mouse::ReadCounters(int *xp, int *yp) +{ + Check(this); + Check_Pointer(xp); + Check_Pointer(yp); + + if (Errors) + { + *xp = 0; + *yp = 0; + } + else + { + // + //----------------------------------------------- + // Read motion counters + //----------------------------------------------- + // + _AX = 0x000B; + geninterrupt(MOUSEINT); + + // + //----------------------------------------------- + // CX = UNSIGNED x counter, + // DX = UNSIGNED y counter. + // These must be converted to signed values. + //----------------------------------------------- + // + int a = _CX; + int b = _DX; + if (a & 0x8000) + { + a |= (int)(~65535L); + } + if (b & 0x8000) + { + b |= (int)(~65535L); + } + + *xp = a; + *yp = b; + } + Check_Fpu(); +} + +// +//############################################################################ +// ButtonPressed - return the number of times a given button was pressed +// since the last call +//############################################################################ +// +int + Mouse::ButtonPressed(int buttonNum) +{ + Check(this); + if (Errors) + { + return 0; + } + else + { + // + //----------------------------------------------- + // Read button press data + //----------------------------------------------- + // + _AX = 0x0005; + _BX = (unsigned short) buttonNum; + geninterrupt(MOUSEINT); + + // + //----------------------------------------------- + // AX = current button states + // BX = number of times pressed since last call + //----------------------------------------------- + // + return (int) _BX; + } +} + +// +//############################################################################ +// ButtonReleased - return the number of times a given button was released +// since the last call +//############################################################################ +// +int + Mouse::ButtonReleased(int buttonNum) +{ + Check(this); + if (Errors) + { + return 0; + } + else + { + // + //----------------------------------------------- + // Read button press data + //----------------------------------------------- + // + _AX = 0x0006; + _BX = (unsigned short) buttonNum; + geninterrupt(MOUSEINT); + + // + //----------------------------------------------- + // AX = current button states + // BX = number of times pressed since last call + //----------------------------------------------- + // + return _BX; + } +} + + diff --git a/CODE/RP/MUNGA_L4/L4MOUSE.HPP b/CODE/RP/MUNGA_L4/L4MOUSE.HPP new file mode 100644 index 0000000..9474fc5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4MOUSE.HPP @@ -0,0 +1,37 @@ +//===========================================================================// +// File: PCMouse.hh // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC mouse interface class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/30/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(L4MOUSE_HPP) + + #define L4MOUSE_HPP + + #if !defined(STYLE_HPP) + #include + #endif + + class Mouse SIGNATURED + { + public: + Mouse(); + ~Mouse() + {} + void ReadCounters(int *xp, int *yp); + int ButtonPressed(int buttonNum); + int ButtonReleased(int buttonNum); + Logical + TestInstance() const; + + int ButtonCount; // number of buttons on mouse + int Errors; // non-zero if bad things happened + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4MPPR.CPP b/CODE/RP/MUNGA_L4/L4MPPR.CPP new file mode 100644 index 0000000..da802bb --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4MPPR.CPP @@ -0,0 +1,393 @@ +//===========================================================================// +// File: L4mppr.cc // +// Project: MUNGA Brick: Hardware-specific controls module // +// Contents: Implementation specification for L4 mapper // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/20/95 JM Initial Coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4MPPR_HPP) +# include +#endif + +#if !defined(L4CTRL_HPP) +# include +#endif + +#if !defined(L4KEYBD_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#define PEDAL_SCALE 2.0f + +//########################################################################## +//#################### CameraL4Mapper ####################### +//########################################################################## + +//############################################################################# +// Shared Data Support +// + +CameraL4Mapper::SharedData + CameraL4Mapper::DefaultData( + CameraL4Mapper::ClassDerivations, + CameraL4Mapper::MessageHandlers, + CameraL4Mapper::AttributeIndex, + CameraL4Mapper::StateCount + ); +Derivation + CameraL4Mapper::ClassDerivations( + CameraControlsMapper::ClassDerivations, + "CameraL4Mapper" + ); + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraL4Mapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraL4Mapper, Keypress) +}; + +CameraL4Mapper::MessageHandlerSet + CameraL4Mapper::MessageHandlers( + ELEMENTS(CameraL4Mapper::MessageHandlerEntries), + CameraL4Mapper::MessageHandlerEntries, + CameraControlsMapper::MessageHandlers + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraL4Mapper::KeypressMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + switch (message->dataContents) + { + case PCK_F1: + Tell("Aligning Joystick...\n"); + controls->BeginAlignJoystick(); + break; + case PCK_F2: + Tell("Joystick Aligned...\n"); + controls->EndAlignJoystick(); + break; + + case '>': + rightPedal = 1.0f; + break; + case '<': + leftPedal = 1.0f; + break; + case ' ': + leftPedal = rightPedal = 0.0f; + break; + + default: + CameraControlsMapper::KeypressMessageHandler(message); + break; + } +} + +//############################################################################# +// Model Support +// +void + CameraL4Mapper::InterpretControls(Scalar) +{ + // + //---------------------------------------- + // Sum the pedal inputs + //---------------------------------------- + // + pedalsPosition = rightPedal - leftPedal; + pedalsPosition *= PEDAL_SCALE; +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraL4Mapper::CameraL4Mapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data + ) + : CameraControlsMapper(owner, subsystem_ID, subsystem_resource, shared_data) +{ + SetPerformance(&CameraL4Mapper::InterpretControls); + + leftPedal = 0.0f; + rightPedal = 0.0f; + + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + controls + ->joystickGroup[LBE4ControlsManager::JoystickPhysical] + .Add(ModeManager::ModeAlwaysActive, &stickPosition, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickTrigger] + .Add(ModeManager::ModeAlwaysActive, &driveCamera, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickThumbHigh] + .Add(ModeManager::ModeAlwaysActive, &slideOrClamp, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft] + .Add( + ModeManager::ModeAlwaysActive, + this, + DecrementCameraMessageID, + this + ); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight] + .Add( + ModeManager::ModeAlwaysActive, + this, + IncrementCameraMessageID, + this + ); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickPinky] + .Add( + ModeManager::ModeAlwaysActive, + this, + DeleteCameraInstanceMessageID, + this + ); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickThumbLow] + .Add( + ModeManager::ModeAlwaysActive, + this, + CreateCameraInstanceMessageID, + this + ); + + controls + ->keyboardGroup[LBE4ControlsManager::KeyboardPC] + .Add( + ModeManager::ModeAlwaysActive, + this, + KeypressMessageID, + this + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraL4Mapper::~CameraL4Mapper() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraL4Mapper::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +//########################################################################## +//#################### CameraThrustmasterMapper ####################### +//########################################################################## + +//############################################################################# +// Shared Data Support +// + +CameraThrustmasterMapper::SharedData + CameraThrustmasterMapper::DefaultData( + CameraThrustmasterMapper::ClassDerivations, + CameraThrustmasterMapper::MessageHandlers, + CameraThrustmasterMapper::AttributeIndex, + CameraThrustmasterMapper::StateCount + ); +Derivation + CameraThrustmasterMapper::ClassDerivations( + CameraL4Mapper::ClassDerivations, + "CameraThrustmasterMapper" + ); + +//############################################################################# +// Model Support +// +void + CameraThrustmasterMapper::InterpretControls(Scalar time_slice) +{ + // + //---------------------------------------- + // Use the hat buttons to set the throttle + //---------------------------------------- + // + if (throttleUp > 0) + { + throttlePosition = 1.0f; + reverseThrust = 0; + } + else if (throttleDown > 0) + { + throttlePosition = 1.0f; + reverseThrust = 1; + } + else + { + throttlePosition = 0.0f; + reverseThrust = 0; + } + + CameraL4Mapper::InterpretControls(time_slice); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraThrustmasterMapper::CameraThrustmasterMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data + ) + : CameraL4Mapper(owner, subsystem_ID, subsystem_resource, shared_data) +{ + SetPerformance(&CameraThrustmasterMapper::InterpretControls); + + throttleUp = throttleDown = 0; + + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp] + .Add(ModeManager::ModeAlwaysActive, &throttleUp, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown] + .Add(ModeManager::ModeAlwaysActive, &throttleDown, this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraThrustmasterMapper::~CameraThrustmasterMapper() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraThrustmasterMapper::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +//############################################################################# +//################################ RIOMapper ################################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +CameraRIOMapper::SharedData + CameraRIOMapper::DefaultData( + CameraRIOMapper::ClassDerivations, + CameraRIOMapper::MessageHandlers, + CameraRIOMapper::AttributeIndex, + CameraRIOMapper::StateCount + ); + +Derivation + CameraRIOMapper::ClassDerivations( + CameraL4Mapper::ClassDerivations, + "CameraRIOMapper" + ); + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraRIOMapper::CameraRIOMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + CameraL4Mapper(owner, subsystem_ID, subsystem_resource, shared_data) +{ + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + // + //----------------- + // Throttle mapping + //----------------- + // + controls + ->scalarGroup[LBE4ControlsManager::ScalarThrottle] + .Add(ModeManager::ModeAlwaysActive, &throttlePosition, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonThrottle1] + .Add(ModeManager::ModeAlwaysActive, &reverseThrust, this); + + // + //-------------- + // Pedal mapping + //-------------- + // + controls + ->scalarGroup[LBE4ControlsManager::ScalarLeftPedal] + .Add(ModeManager::ModeAlwaysActive, &leftPedal, this); + + controls + ->scalarGroup[LBE4ControlsManager::ScalarRightPedal] + .Add(ModeManager::ModeAlwaysActive, &rightPedal, this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraRIOMapper::~CameraRIOMapper() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraRIOMapper::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/MUNGA_L4/L4MPPR.HPP b/CODE/RP/MUNGA_L4/L4MPPR.HPP new file mode 100644 index 0000000..2243c20 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4MPPR.HPP @@ -0,0 +1,174 @@ +//===========================================================================// +// File: L4mppr.hpp. // +// Project: MUNGA Brick: Hardware-specific controls module // +// Contents: Interface specification for L4 mapper // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/20/95 JM Initial Coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(L4MPPR_HPP) +# define L4MPPR_HPP + +#if !defined (CONTROLS_HPP) +# include "controls.hpp" +#endif + +#if !defined (CAMMPPR_HPP) +# include "cammppr.hpp" +#endif + + //########################################################################## + //#################### CameraL4Mapper ####################### + //########################################################################## + class CameraL4Mapper : + public CameraControlsMapper + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messaging Support + // + public: + void + KeypressMessageHandler(ReceiverDataMessageOf *message); + + protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (CameraL4Mapper::*Performance)(Scalar time_slice); + + void + InterpretControls(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + public: + CameraL4Mapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); + ~CameraL4Mapper(); + + Logical + TestInstance() const; + + protected: + ControlsScalar + leftPedal, + rightPedal; + }; + + //########################################################################## + //#################### CameraThrustmasterMapper ####################### + //########################################################################## + + class CameraThrustmasterMapper : + public CameraL4Mapper + { + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (CameraThrustmasterMapper::*Performance)(Scalar time_slice); + + void + InterpretControls(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + public: + CameraThrustmasterMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); + ~CameraThrustmasterMapper(); + + Logical + TestInstance() const; + + protected: + ControlsButton + throttleUp, + throttleDown; + }; + + //########################################################################## + //########################### CameraRIOMapper ######################## + //########################################################################## + + class CameraRIOMapper : + public CameraL4Mapper + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + public: + CameraRIOMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); + ~CameraRIOMapper(); + + Logical + TestInstance() const; + }; + +#endif + + + diff --git a/CODE/RP/MUNGA_L4/L4MSSN.CPP b/CODE/RP/MUNGA_L4/L4MSSN.CPP new file mode 100644 index 0000000..1e46677 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4MSSN.CPP @@ -0,0 +1,228 @@ +//===========================================================================// +// File: l4msson.cc // +// Project: MUNGA Brick: Application // +// Contents: Implementation Details for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/19/95 JMA Initial coding. // +// 09/12/95 JM Put Back in Munga Added Munga L4 level Player Data // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if 0 +// THIS FILE IS OBSOLETE AS OF 11-1-95 cpb + + +#include "l4munga.hpp" + +#if !defined(L4MSSN_HPP) +# include "l4mssn.hpp" +#endif + +#if !defined(L4HOST_HPP) +# include "l4host.hpp" +#endif + +#if !defined(MISSION_HPP) +# include "mission.hpp" +#endif + +//########################################################################## +//########################## L4Mission ################################ +//########################################################################## + +// +//############################################################################# +//############################################################################# +// +L4Mission::L4Mission( + NotationFile *notation_file, + ResourceFile *resources +): + Mission(notation_file, resources) +{ + for(int i=0; i < Player::numberOfNameBitmaps; ++i) + { + nameBitmap[i] = NULL; + } +} + +// +//############################################################################# +//############################################################################# +// +L4Mission::~L4Mission() +{ + for(int i=0; iGetHostManager(); + Check(host_manager); + L4Host *host = (L4Host*)host_manager->GetLocalHost(); + Check(host); + CString player_node = host->GetSymbolicName(); + + // + //----------------- + // Get Vehicle name + //----------------- + // + gameModel = NULL; + const char* player_model = NULL; + notation_file->GetEntry(player_node, "vehicle", &player_model); + if (!player_model) + { + DEBUG_STREAM << "Error: vehicle not specified!\n"; + Exit(1); + } + Check_Pointer(player_model); + gameModel = strdup(player_model); + Register_Pointer(gameModel); + // + //----------------- + // Get DropZone name + //----------------- + // + dropZoneName = NULL; + const char* drop_zone = NULL; + notation_file->GetEntry(player_node, "dropzone", &drop_zone); + if (!drop_zone) + { + DEBUG_STREAM << "Error: dropzone not specified!\n"; + Exit(1); + } + Check_Pointer(drop_zone); + dropZoneName = strdup(drop_zone); + Register_Pointer(dropZoneName); + // + //------------------ + // Set DropZone Host + //------------------ + // + dropZoneHost = False; + notation_file->GetEntry(player_node, "loadzones", &dropZoneHost); + // + //----------------- + // Get Color name + //----------------- + // + colorName = NULL; + const char* color_name = NULL; + notation_file->GetEntry(player_node, "color", &color_name); + if (!color_name) + { + DEBUG_STREAM << "Error: color not specified!\n"; + Exit(1); + } + Check_Pointer(color_name); + colorName = strdup(color_name); + Register_Pointer(colorName); + // + //----------------- + // Get Badge name + //----------------- + // + badgeName = NULL; + const char* badge_name = NULL; + notation_file->GetEntry(player_node, "badge", &badge_name); + if (!badge_name) + { + DEBUG_STREAM << "Error: badge not specified!\n"; + Exit(1); + } + Check_Pointer(badge_name); + badgeName = strdup(badge_name); + Register_Pointer(badgeName); + + // + //----------------------------------------------- + // Get the Role name "General" if not listed + //----------------------------------------------- + // + positionName = NULL; + const char* position_name = NULL; + notation_file->GetEntry(player_node, "position", &position_name); + if(!position_name) + { + position_name = strdup("General"); + } + Check_Pointer(position_name); + positionName = strdup(position_name); + Register_Pointer(positionName); + // + //--------------------------------------- + // Assign an integer value for the teamID + //--------------------------------------- + // + const char* team_name; + notation_file->GetEntry(player_node, "team", &team_name); + int team_count; + + NameList + *team_namelist = notation_file->MakeEntryList("teams"); + + teamID = -1; + if (team_namelist) + { + Register_Object(team_namelist); + team_count = team_namelist->EntryCount(); + if(team_count) + { + int current_id=0; + NameList::Entry *team_entry = team_namelist->GetFirstEntry(); + while(team_entry) + { + if (strcmp(team_name, team_entry->GetChar()) == 0) + { + teamID = current_id; + break; + } + current_id++; + team_entry = team_entry->GetNextEntry(); + } + } + Unregister_Object(team_namelist); + delete team_namelist; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4Mission::TestInstance() const +{ + Mission::TestInstance(); + return True; +} +#endif diff --git a/CODE/RP/MUNGA_L4/L4MSSN.HPP b/CODE/RP/MUNGA_L4/L4MSSN.HPP new file mode 100644 index 0000000..7014ba1 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4MSSN.HPP @@ -0,0 +1,50 @@ +//===========================================================================// +// File: l4mssn.hh // +// Project: MUNGA Brick: Application // +// Contents: Implementation Details for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/19/95 JMA Initial coding. // +// 09/12/95 JM Put Back in Munga & Added Munga L4 level Player Data // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined (L4MSSN_HPP) + #define L4MSSN_HPP + +# if !defined(MISSION_HPP) +# include "mission.hpp" +# endif + +#if 0 +// THIS FILE IS OBSOLETE AS OF 11-1-95 cpb + +//########################################################################## +//########################## L4Mission ################################ +//########################################################################## + + +class L4Mission : + public Mission +{ + public: + + L4Mission( + NotationFile *notation_file, + ResourceFile *resources + ); + ~L4Mission(); + + void + SetPlayerData(NotationFile *notation_file); + + Logical + TestInstance() const; + +}; + +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/L4NET.HPP b/CODE/RP/MUNGA_L4/L4NET.HPP new file mode 100644 index 0000000..43ef469 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4NET.HPP @@ -0,0 +1,464 @@ +//===========================================================================// +// File: l4net.hh // +// Project: MUNGA Brick: Network Manager // +// Contents: Interface specification for network brick // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/02/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4NET_HPP) +# define L4NET_HPP + +# if !defined(L4HOST_HPP) +# include +# endif + +# if !defined(NETWORK_HPP) +# include +# endif + +# if !defined(NETNUB_HPP) +# include +# endif + +# if !defined(HOSTMGR_HPP) +# include +# endif + + class NotationFile; + class L4NetworkManager__ReceiveEggFileMessage; + class L4NetworkManager__AcknowledgeEggFileMessage; + class L4NetworkManager__HostConnectedMessage; + class L4NetworkManager__HostDisconnectedMessage; + + class NetNub + { + friend int + Netnub_Open_File( + const char* filename, + int access, + unsigned int model + ); + friend int + Netnub_Write_File( + int handle, + void *buffer, + size_t length + ); + friend int + Netnub_Close_File(int handle); + + public: + static void + SendCommand(); + }; + + extern Netcom_Ptr + Net_Common_Ptr; + + //~~~~~~~~~~~~~~~~~~~~~ MessageQueue__SendRequest ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class MessageQueue__SendRequest: + public Plug + { + friend class HostMessageBuffer__MessageQueue; + friend class L4NetworkManager__MessageBuffer; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + MessageQueue__SendRequest( + NetworkClient::ClientID client_ID, + Receiver::Message *message + ); + ~MessageQueue__SendRequest(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + NetworkClient::ClientID + clientID; + Receiver::Message + *messageToSend; + }; + + //~~~~~~~~~~~~~~~~~~~ HostMessageBuffer__MessageQueue ~~~~~~~~~~~~~~~~~~~~~~ + + class HostMessageBuffer__MessageQueue: + public Node + { + friend class L4NetworkManager__MessageBuffer; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + HostMessageBuffer__MessageQueue(HostID host_ID); + ~HostMessageBuffer__MessageQueue(); + + Logical + TestInstance() const; + + void + AddSendRequest( + NetworkClient::ClientID client_ID, + Receiver::Message *message + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + HostID + hostID; + + typedef MessageQueue__SendRequest + SendRequest; + ChainOf + sendRequestSocket; + }; + + //~~~~~~~~~~~~~~~~~~ L4NetworkManager__MessageBuffer ~~~~~~~~~~~~~~~~~~~~~~~ + + class L4NetworkManager__MessageBuffer: + public Node + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public methods + // + public: + L4NetworkManager__MessageBuffer(L4NetworkManager *network_manager); + ~L4NetworkManager__MessageBuffer(); + + Logical + TestInstance() const; + + Logical + IsEmpty(); + void + AddSendRequest( + HostID host_ID, + NetworkClient::ClientID client_ID, + Receiver::Message *message + ); + void + AttemptToSend(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + L4NetworkManager + *networkManager; + typedef HostMessageBuffer__MessageQueue + MessageQueue; + TableOf + messageQueueSocket; + IteratorPosition + currentQueueIndex; + CollectionSize + bufferSize; + #ifdef LAB_ONLY + CollectionSize + messageCount, + maxBufferSize; + #endif + }; + + inline Logical + L4NetworkManager__MessageBuffer::IsEmpty() + { + Check(this); + return (bufferSize == 0); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ l4Network manager~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class L4NetworkManager: + public NetworkManager + { + friend class L4NetworkManager__MessageBuffer; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, Testing + // + public: + L4NetworkManager(); + ~L4NetworkManager(); + + static Logical + TestClass(); + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Network message methods + // + public: + void + Send( + Message *what, + ClientID to, + HostID host_ID); + void + ExclusiveBroadcast( + Message *what, + ClientID to + ); + + void + StartConnecting(Mission *mission); + + Logical + Shutdown(); + + Logical + CheckBuffers(NetworkPacket *packet); + + void + RemovePacket(NetworkPacket *packet); + + Logical + ExecuteBackground(); + + void + Marker(char *marker_text); + + void + Mode(NetworkMode myMode); + + void + CreateConsoleHost(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Network maintenance support + // + public: + int + netPlayerCount; + + enum NetworkState + { + NormalState, + ConsoleOnly + }; + + enum NetworkStartupMode + { + SlaveMode, + MasterMode + }; + + unsigned long + CheckSocket(unsigned long socket); + unsigned long + ResolveAddress(CString host_name); + unsigned long + GetMyAddress(); + unsigned long + OpenConnection( + int connection_type, // NETNUB_TCP_LISTEN or NETNUB_TCP_OPEN + int local_port, + int remote_port, + int internet_address + ); + void + CloseConnection(unsigned long socket_ptr); // socket address from netnub (to close) + Logical + GetNextMungaPacket( + NetworkPacket *network_packet, + HostManager::RemoteHostIterator* all_iterator + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + public: + // + // Message IDs + // + enum + { + AcknowledgeEggFileMessageID = NetworkManager::NextMessageID, + HostConnectedMessageID, + HostDisconnectedMessageID, + NextMessageID + }; + + // + // Message types + // + typedef L4NetworkManager__AcknowledgeEggFileMessage + AcknowledgeEggFileMessage; + typedef L4NetworkManager__HostConnectedMessage + HostConnectedMessage; + typedef L4NetworkManager__HostDisconnectedMessage + HostDisconnectedMessage; + // + // Message table + // + static const HandlerEntry + MessageHandlerEntries[]; + + static MessageHandlerSet + MessageHandlers; + + void + ReceiveEggFileMessageHandler( + ReceiveEggFileMessage *EggMessage + ); + void + AcknowledgeEggFileMessageHandler( + AcknowledgeEggFileMessage *AcknowledgeEgg + ); + void + HostConnectedMessageHandler( + HostConnectedMessage *HostConnected + ); + void + HostDisconnectedMessageHandler( + HostDisconnectedMessage *ConsoleDisconnect + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private methods + // + private: + typedef ChainOf + DroppedMessageHostSocket; + typedef ChainIteratorOf + DroppedMessageHostIterator; + + Logical + SendMessageToNetnub( + Message *message, + ClientID client_ID, + HostID host_ID + ); + void + SendBatchedMessageToNetnub( + Message *message, + ClientID client, + DroppedMessageHostSocket *dropped_message_host_socket + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private Data + // + private: + int + numberOfMungaHostsConnected, + numberOfConsoleHostsConnected, + remoteHostCount; + NetworkStartupMode + networkStartupMode; + Logical + eggAcknowledged; + NetworkState + currentNetworkState; + L4Host + *myConsoleHost; + HostID + nextOpenHostID; + IteratorPosition + lastHostIteratorPosition; + + typedef L4NetworkManager__MessageBuffer + MessageBuffer; + MessageBuffer + messageBuffer; + }; + + //~~~~~~~~~~~~~~~~~~~~~~ L4NetworkManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // L4NetworkManager__AcknowledgeEggFileMessage + // This message is sent back to the console to acknowledge receipt of the + // egg, it indicates this computer has established all it's connections and + // the console can procede with the next host + // + class L4NetworkManager__AcknowledgeEggFileMessage: + public NetworkManager::Message + { + public: + L4NetworkManager__AcknowledgeEggFileMessage(): + NetworkManager::Message( + L4NetworkManager::AcknowledgeEggFileMessageID, + sizeof(L4NetworkManager__AcknowledgeEggFileMessage) + ){} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // L4NetworkManager__HostConnectedMessage + // This message is generated internally by CheckBuffers and indicates that + // a host has connected up to us. This is an INTERNAL message only and is + // not ment to be sent on the network. + class L4NetworkManager__HostConnectedMessage: + public NetworkManager::Message + { + public: + L4NetworkManager__HostConnectedMessage(HostID host_id, + unsigned long network_address, + unsigned long stream_pointer): + NetworkManager::Message( + L4NetworkManager::HostConnectedMessageID, + sizeof(L4NetworkManager__HostConnectedMessage) + ), hostID(host_id), + networkAddress(network_address), + streamPointer(stream_pointer) {} + + HostID + hostID; + unsigned long + networkAddress; + unsigned long + streamPointer; + }; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // L4NetworkManager__HostDisconnectedMessage + // The console is expected to send us this message if it disconnects from us + // for any reason. This allows the local host to setup the internal state + // so the game will auto start even if the console can't stay connected to us + // for some reason (for example, the console simulator in the game code can't + // connect to more than one host at once). + // !!! CheckBuffers should poll the connection state of all the streams and + // generate this message automatically whenever a host drops off the net. + // !!! HACK At the moment this message is always treated as if it came from + // the console host, so it should only be sent down the console stream. + // + class L4NetworkManager__HostDisconnectedMessage: + public NetworkManager::Message + { + public: + L4NetworkManager__HostDisconnectedMessage(HostID host_id, + unsigned long stream_pointer): + NetworkManager::Message( + L4NetworkManager::HostDisconnectedMessageID, + sizeof(L4NetworkManager__HostDisconnectedMessage) + ), hostID(host_id), + streamPointer(stream_pointer) {} + HostID + hostID; + unsigned long + streamPointer; + }; + + +#endif diff --git a/CODE/RP/MUNGA_L4/L4NET.TCP b/CODE/RP/MUNGA_L4/L4NET.TCP new file mode 100644 index 0000000..7a2f268 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4NET.TCP @@ -0,0 +1,418 @@ + +#include "receiver.hpp" +#include "network.hpp" +#include "l4net.hpp" +#include "time.hpp" +#include "l4net.hpp" +extern "C" +{ + getch(); +} +// +//############################################################################## +//################# L4NetworkManager ####################### +//############################################################################## + +Logical + L4NetworkManager::TestClass() +{ +#if 0 + + + + + struct Track + { + long + departureTics; + HostID + sentBy; + long + serialNo; + char + name[120]; + }test_mess; + + + struct Traffic + { + //HostID + // echoedBy; + long + //currSerialNo, + //currArrivalTicks, + prevSerialNo, + prevArrivalTicks, + travelTimeTicksMax, + travelTimeTicksMin; + short + maxBunchSize, + bunchAmount; + long + //packets_sent, + packets_received; + + long + sequenceErrors; + }; + + Traffic traffic[10];//application->GetNetworkManager()->netPlayerCount]; + // ??? + + HostManager::RemoteHostIterator + remote_hosts(application->GetHostManager()); + Host + *this_host; + while ((this_host = remote_hosts.ReadAndNext()) != NULL) + { + Check(this_host); + HostID + this_hostID = this_host->GetHostID(); + traffic[this_hostID].prevSerialNo = 0; + traffic[this_hostID].prevArrivalTicks = 0; + traffic[this_hostID].travelTimeTicksMax= -1; + traffic[this_hostID].travelTimeTicksMin= 0x0fffffff; + traffic[this_hostID].maxBunchSize = 0; + traffic[this_hostID].bunchAmount = 0; + traffic[this_hostID].packets_received = 0; + traffic[this_hostID].sequenceErrors = 0; + + } + + HostID + my_hostID = application->GetHostManager()->GetLocalHostID(); + traffic[my_hostID].prevSerialNo = 0; + traffic[my_hostID].prevArrivalTicks = 0; + traffic[my_hostID].travelTimeTicksMax= -1; + traffic[my_hostID].travelTimeTicksMin= 0x0fffffff; + traffic[my_hostID].maxBunchSize = 0; + traffic[my_hostID].bunchAmount = 0; + traffic[my_hostID].packets_received = 0; + traffic[my_hostID].sequenceErrors = 0; + + + +// +//------------------------------------------- +// Get environmental variables: +// packet_period, packets_amount, echo_packet, print_packet +//------------------------------------------- +// + Scalar + packet_period, //sent + receive_period; //receive + long + packets_amount; + Logical + echo_packet, //=True, + print_packet; //=False; + int + broadcast_packet; //1 + char + *pp = getenv("PERIOD"); + if (pp != NULL) + { + packet_period = atof(pp); + } + else + { + packet_period = 1.0f; + } +cout<<"PERIOD = "< + what(Receiver::AnyMessageID, + sizeof(ReceiverDataMessageOf), + test_mess + ); + + Byte + message_buffer[NETWORKMANAGER_BUFFER_SIZE]; //512 + #if sizeof(NetworkPacketHeader) + sizeof(ReceiverDataMessageOf) >= \ + NETWORKMANAGER_BUFFER_SIZE + #error NETWORKMANAGER_BUFFER_SIZE too small! + #endif + + + NetworkPacket + *p = (NetworkPacket*)message_buffer; + + cout << "Packet size = " << + " sizeof(NetworkPacketHeader) + sizeof(ReceiverDataMessageOf) = " << + (sizeof(NetworkPacketHeader) + sizeof(ReceiverDataMessageOf)) << + endl; + + + Time + timer = Now(); + timer += 2.0f;//packet_period; //at the beginning it listens for 2 secs + + Time + receive_timer = Now(); + while(1) + { + + + //------------------------------------------------------------- + // Send + //------------------------------------------------------------- + if (packets < packets_amount) + { + if (timer < Now()) + { + packets++; + what.dataContents.serialNo++; + + //-------------------------- + //test testing sequence error + //-------------------------- + //if (what.dataContents.serialNo==5) + //{ + // what.dataContents.serialNo=6; + //} + + Time + departureTime = Now(); + what.dataContents.departureTics = departureTime.ticks; + + Check(application); + Check(application->GetNetworkManager()); + + for (int b=0; b + GetNetworkManager()-> + ExclusiveBroadcast( + &what, + NetworkManagerClientID + ); + } + + timer = Now(); + timer += packet_period; + + + } + } + else + { + if (packets == packets_amount) + { + packets++; + //----------------- + // set time to catch up left packets + //----------------- + timer = Now(); + timer += 2.0f; + } + else + { + if (timer < Now()) + { + //-------- + // exit + //-------- + break; + } + } + } + + //------------------------------------------------------------- + // Receive + //------------------------------------------------------------- + if (receive_timer < Now()) + { + + if (application->GetNetworkManager()->CheckBuffers(p)) + { + if (p->clientID != NetworkManagerClientID) + { + cout<<"p->messageData.messageID= "<messageData.messageID<messageData.messageLength= "<messageData.messageLength<clientID == NetworkManagerClientID) + //&& (p->messageData.messageID == Receiver::AnyMessageID) + //&& (p->messageData.messageLength == sizeof(ReceiverDataMessageOf)) + ) + { + Verify(p->messageData.messageID == Receiver::AnyMessageID); + Verify(p->messageData.messageLength == sizeof(ReceiverDataMessageOf)); + ReceiverDataMessageOf* + what_ptr = (ReceiverDataMessageOf*)(&p->messageData); + if (print_packet) + { + cout<dataContents.name<dataContents.sentBy != my_hostID)) + { + //----------------------------------------------------- + // Got their packet - Send back + //----------------------------------------------------- + Str_Copy(what_ptr->dataContents.name, + "RETURNED PACKET", + sizeof(what_ptr->dataContents.name) + ); + Check(application); + Check(application->GetNetworkManager()); + application-> + GetNetworkManager()-> + Send(what_ptr, + NetworkManagerClientID, + p->fromHost + ); + } + + + if (what_ptr->dataContents.sentBy == my_hostID) + { + //----------------------------------------------------- + // Got our own returned packet + // + // - Check serialNo; Get travel time; ... + //----------------------------------------------------- + traffic[p->fromHost].packets_received++; + //---------------- + // Get travel time + //---------------- + Time + travelTime = Now(); + travelTime.ticks -= what_ptr->dataContents.departureTics; + traffic[p->fromHost].travelTimeTicksMax = + Max(travelTime.ticks, traffic[p->fromHost].travelTimeTicksMax); + traffic[p->fromHost].travelTimeTicksMin = + Min(travelTime.ticks, traffic[p->fromHost].travelTimeTicksMin); + + //---------------- + // Check serialNo + //---------------- + if (what_ptr->dataContents.serialNo != + traffic[p->fromHost].prevSerialNo + 1) + { + traffic[p->fromHost].sequenceErrors++; + } + traffic[p->fromHost].prevSerialNo = what_ptr->dataContents.serialNo; + + } + } + } + + receive_timer = Now(); + receive_timer += receive_period; + } + }//while + + + if (broadcast_packet) + { + remote_hosts.First(); + while ((this_host = remote_hosts.ReadAndNext()) != NULL) + { + Check(this_host); + HostID + this_hostID = this_host->GetHostID(); + cout + <<"From " + < +# endif + +# if defined(TRACE_RIO_RECEIVE_PACKET) + extern BitTrace RIO_Receive_Packet; +# define SET_RIO_RECEIVE_PACKET() RIO_Receive_Packet.Set() +# define CLEAR_RIO_RECEIVE_PACKET() RIO_Receive_Packet.Clear() +# else +# define SET_RIO_RECEIVE_PACKET() +# define CLEAR_RIO_RECEIVE_PACKET() +# endif + +# if defined(TRACE_RIO_SEND_PACKET) + extern BitTrace RIO_Send_Packet; +# define SET_RIO_SEND_PACKET() RIO_Send_Packet.Set() +# define CLEAR_RIO_SEND_PACKET() RIO_Send_Packet.Clear() +# else +# define SET_RIO_SEND_PACKET() +# define CLEAR_RIO_SEND_PACKET() +# endif + + class PCSerialPacket; + class PCSerialPacketScanner; + + enum + { + PCSPAKInitErrDPMI = -2, + PCSPAKInitErrAlloc = -1, + PCSPAKInitOk = 0 + }; + + extern "C" int // see error codes, above + PCSPAKInit( + PCSerialPacket *ptr, + Word rate, + Word port, + Word intnum, + Byte *rxLength, + Word rxMaximum, + Byte *txLength, + Word txMaximum + ); + + extern "C" void + PCSPAKTerm( + PCSerialPacket *ptr + ); + + extern "C" Logical + PCSPAKTestInstance( + PCSerialPacket *ptr + ); + + extern "C" int + PCSPAKReceive( + PCSerialPacket *ptr, + Byte *destPtr + ); + + extern "C" void + PCSPAKSend( + PCSerialPacket *ptr, + Byte *srcPtr + ); + + extern "C" int + PCSPAKActive( + PCSerialPacket *ptr + ); + + extern "C" Word + PCSPAKErrors( + PCSerialPacket *ptr + ); + + extern "C" Logical + PCSPAKIRQState(); + + extern "C" int + PCSPAKIsSignatureBad( + const volatile PCSerialPacket *ptr + ); + + extern "C" int + PCSPAKReceiveCount( + PCSerialPacket *ptr + ); + + extern "C" int + PCSPAKTransmitCount( + PCSerialPacket *ptr + ); + + extern "C" void + PCSPAKSetDTR( + PCSerialPacket *ptr, + Logical on + ); + + // WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING + // Do NOT change ANY of the following lines without making + // corresponding changes in PCSerial.asm! PCSPAK.hh exists + // ONLY to inform C++ compilers of the data and structures + // used by PCSPAK.asm! + // WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING + + // These are purposely grouped as two parameters in one equate. + // The standard PC COM ports ALWAYS use these combinations. +# define PCSP_COM1 0x3F8,0x0C // portAddress,interruptNumber +# define PCSP_COM2 0x2F8,0x0B +# define PCSP_COM3 0x3E8,0X0C +# define PCSP_COM4 0x2E8,0x0B + + // Data rates +# define PCSP_300 0x0180 // 300 Baud +# define PCSP_1200 0x0060 // 1200 Baud +# define PCSP_2400 0x0030 // 2400 Baud +# define PCSP_9600 0x000C // 9600 Baud +# define PCSP_19P2 0x0006 // 19200 Baud +# define PCSP_38P4 0x0003 // 38400 Baud +# define PCSP_115K 0x0001 // 115,200 Baud (not supported on all PC's) + + // This is for INTERNAL USE only (reflects structure in .ASM file) + struct PCSerPackBuf + { + Word head, tail, tempHead, tempTail, count, tempIn, tempOut; + Byte data[512]; // was 256 before 7-13-95 cpb + // WARNING: make ABSOLUTELY SURE this matches pcspak.asm + }; + + class PCSerialPacket + { + friend class PCSerialPacketScanner; + + public: + PCSerialPacket() + { } + + ~PCSerialPacket() + { + PCSPAKTerm(this); + } + + // Only call Initialize(...) ONCE during the lifetime of the object! + int + Initialize( + Word rate, + Word port, + Word intNum, + Byte *rxLengths, + Word rxCount, + Byte *txLengths, + Word txCount + ) + { + return PCSPAKInit( + this, + rate, + port, + intNum, + rxLengths, + rxCount, + txLengths, + txCount + ); + } + + Logical + TestInstance() + { return PCSPAKTestInstance(this); } + + int + ReceivePacket(Byte *destPtr) // returns len (zero if none) + { + SET_RIO_RECEIVE_PACKET(); + int result = PCSPAKReceive(this, destPtr); + CLEAR_RIO_RECEIVE_PACKET(); + return result; + } + + void + SendPacket(Byte *srcPtr) // sends packet + { + SET_RIO_SEND_PACKET(); + PCSPAKSend(this, srcPtr); + CLEAR_RIO_SEND_PACKET(); + } + + // error bits returned by PCSerialPacket::Errors() + enum ErrorBits { + overrunError=0x0002, + parityError=0x0004, + framingError=0x0008, + breakDetect=0x0010, + initError=0x0100, + txEarlyReply=0x0200, + txAbandonPacket=0x0400, + txRestart=0x0800, + txNakReply=0x1000, + rxSequenceError=0x2000, + rxChecksumError=0x4000, + rxCommandError=0x8000 + }; + + int + ReceiveQueueCount() + { return PCSPAKReceiveCount(this); } + + int + TransmitQueueCount() + { return PCSPAKTransmitCount(this); } + + void + SetDTR(Logical on) + { PCSPAKSetDTR(this, on); } + + int + IsActive() + { return PCSPAKActive(this); } + + Word + Errors() // returns error value, clears it + { return PCSPAKErrors(this); } + +# if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile PCSerialPacket *ptr) + { return PCSPAKIsSignatureBad(ptr); } +# endif + + protected: + Word portBase; + Word Error; + + Byte enabled; + Byte txHoldOff; + Byte txReply; + Byte txState; + Byte txCount; + Byte txResetCount; + Byte txErrorCount; + Byte txIdleCount; + Byte txChecksum; + Byte txMaximum; + + Byte rxFlags; + Byte rxState; + Byte rxCount; + Byte rxChecksum; + Byte rxMaximum; + + LWord txLengthPtr; + LWord rxLengthPtr; + + LWord intDataPtr; +// LWord hackCount; //WGR previously missing: seen in pcspak.asm + + PCSerPackBuf txBuf; + PCSerPackBuf rxBuf; + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4PLASMA.CPP b/CODE/RP/MUNGA_L4/L4PLASMA.CPP new file mode 100644 index 0000000..75579ab --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4PLASMA.CPP @@ -0,0 +1,333 @@ +//===========================================================================// +// File: L4plasma.cpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for plasma display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/08/95 CPB Initial coding. // +// 06/15/95 CPB Changed to Video8BitBuffered, added transmission. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4PLASMA_HPP) +# include +#endif + +#if !defined(TIME_HPP) +# include +#endif + +//######################################################################## +//############################# PlasmaDisplay ############################ +//######################################################################## +PlasmaDisplay::PlasmaDisplay( + Word port, + Word int_num +): + Video8BitBuffered(plasmaWidth, plasmaHeight) +{ + //------------------------------------ + // Create serial interface + //------------------------------------ + pc_serial = new PCSerial(PCS_9600, PCS_N81, port, int_num); + if (pc_serial != NULL) + { + Register_Object(pc_serial); + pc_serial->FlowControlEnable(False); + //------------------------------------ + // Turn off the cursor + //------------------------------------ + static char + cursorOffString[] = { 27 /*ESC*/, 'G', (char) 0x00 }; + + pc_serial->SendString(cursorOffString, 3); + } + //------------------------------------ + // Clear update flag array + //------------------------------------ + currentTransferLine = 0; + updateInProgress = False; + + for(int i=0; iTransmitCharCount() <= 0) + { + if (!pc_serial->IsActive()) + { + break; + } + } + } + //--------------------------------------------------------------------- + // Delete the serial interface + //--------------------------------------------------------------------- + Unregister_Object(pc_serial); + delete pc_serial; + } + Check_Fpu(); +} + +Logical + PlasmaDisplay::TestInstance() const +{ + return Video8BitBuffered::TestInstance(); +} + +void + PlasmaDisplay::ShowInstance(char *indent) +{ + cout << indent << "Plasma:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + Video8BitBuffered::ShowInstance(temp); + Check_Fpu(); +} + + +void + sendLine( + PCSerial *pc_serial, + int line_number, + Byte *source_pointer, + int source_width + ) +{ + char + graphics[32]; // We only need 16...the extra is just in case. + int + x, + index; + Byte + byte, + byte_bit; + //-------------------------------------------- + // Send header + //-------------------------------------------- + graphics[0] = (char) 27; // ascii ESC + graphics[1] = 'P'; // graphics command + graphics[2] = (char) 0; // screen number + graphics[3] = (char) line_number; // Y position + graphics[4] = (char) 0; // X BYTE position + graphics[5] = (char) ((source_width+7)>>3); // width in bytes + graphics[6] = (char) 1; + + pc_serial->SendString(graphics, 7); + //-------------------------------------------- + // Send data + //-------------------------------------------- + byte = 0; + byte_bit = 0x80; + index = 0; + for(x=0; x>= 1; + // + // If entire byte collected, send it + // + if (byte_bit == 0) + { + Verify(index < sizeof(graphics)); + graphics[index++] = byte; + byte = 0; + byte_bit = 0x80; + } + } + // + // End of source line: send remaining bits + // + if (byte_bit != 0x80) + { + graphics[index++] = byte; + } + // + // Send graphics data + // + pc_serial->SendString(graphics, index); + Check_Fpu(); +} + +void + PlasmaDisplay::Scan(Logical forceAll) +{ + Word + changed_line = (Word) forceAll, + *changed_line_pointer = changedLine; + char + *update_pointer=updateFlag; + int + y; + + for(y=0; yTransmitCharCount() == 0) + { + total_count = plasmaHeight; + transfer_count = 4; + while(transfer_count>0) + { + //----------------------------------------- + // Transfer a line if it's ready + //----------------------------------------- + if (updateFlag[currentTransferLine]) + { + //----------------------------------------- + // Decrement the 'transfer count' + //----------------------------------------- + --transfer_count; + //----------------------------------------- + // Clear the 'update' flag + //----------------------------------------- + updateFlag[currentTransferLine] = 0; + //----------------------------------------- + // Send the line data to the display + //----------------------------------------- + sendLine( + pc_serial, + currentTransferLine, + pixelBuffer->Data.MapPointer + + (pixelBuffer->Data.Size.x * currentTransferLine), + pixelBuffer->Data.Size.x + ); + } + //----------------------------------------- + // Increment currentTransferLine + //----------------------------------------- + if (++currentTransferLine >= plasmaHeight) + { + currentTransferLine = 0; + } + //----------------------------------------- + // Reset to top if all lines scanned + //----------------------------------------- + if (--total_count < 0) + { + currentTransferLine = 0; // reset to top line + updateInProgress = False; + result = False; // False == 'all data sent' + break; + } + } + } + } + Check_Fpu(); + return result; +} + +void + PlasmaDisplay::WaitForUpdate() +{ + Time + end_time; + + end_time = Now(); + end_time += 5.0; // We'll wait this many seconds to update the display- + + while (updateInProgress) + { + Update(False); + + if (Now() >= end_time) + { + break; + } + } + Check_Fpu(); +} + + + + + + + + + diff --git a/CODE/RP/MUNGA_L4/L4PLASMA.HPP b/CODE/RP/MUNGA_L4/L4PLASMA.HPP new file mode 100644 index 0000000..c6bb04c --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4PLASMA.HPP @@ -0,0 +1,70 @@ +//===========================================================================// +// File: L4plasma.hpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for plasma display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 04/20/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4PLASMA_HPP) +# define L4PLASMA_HPP + +# if !defined(L4VB8_HPP) +# include +# endif + +# if !defined(L4SERIAL_HPP) +# include +# endif + + //######################################################################## + //################################ Plasma ################################ + //######################################################################## + class PlasmaDisplay : + public Video8BitBuffered + { + public: + enum + { + plasmaWidth=128, + plasmaHeight=32 + }; + + PlasmaDisplay(Word port, Word int_num); + + ~PlasmaDisplay(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + Logical + Update(Logical forceall); + + void + WaitForUpdate(); + + protected: + void + Scan(Logical forceall); + + Logical + forceAll, + updateInProgress; + + PCSerial + *pc_serial; + int + currentTransferLine; + char + updateFlag[32]; + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4RIO.CPP b/CODE/RP/MUNGA_L4/L4RIO.CPP new file mode 100644 index 0000000..0d4e443 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4RIO.CPP @@ -0,0 +1,1675 @@ +//===========================================================================// +// File: RIO.cc // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: Remote I/O interface // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/30/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4RIO_HPP) +# include +#endif + +#if !defined(L4CTRL_HPP) +# include +#endif + +#if defined(TRACE_RIO_RECEIVE_PACKET) + BitTrace RIO_Receive_Packet("RIO Receive Packet"); +#endif + +#if defined(TRACE_RIO_SEND_PACKET) + BitTrace RIO_Send_Packet("RIO Send Packet); +#endif + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +#define default_deadband_value 0.03 + +static Byte RIOLengths[] = { + 0, // CheckRequest + 0, // VersionRequest + 0, // AnalogRequest + 1, // ResetRequest + 2, // LampRequest + 2, // CheckReply + 2, // VersionReply + 10, // AnalogReply + 1, // ButtonPressed + 1, // ButtonReleased + 2, // KeyPressed + 2, // KeyReleased + 1 // TestModeChange +}; + +Byte RIO::reply_check_string[] = {RIO::CheckReply, 3, 2 }; +Byte RIO::reply_version_string[] = {RIO::VersionReply, 1, 23}; +Byte RIO::reply_button_press_string[] = {RIO::ButtonPressed, 22}; +Byte RIO::reply_button_release_string[]= {RIO::ButtonReleased, 22}; +Byte RIO::reply_key_press_string[] = {RIO::KeyPressed, 0, 4}; +Byte RIO::reply_key_release_string[] = {RIO::KeyReleased, 0, 4}; +Byte RIO::reply_test_enter_string[] = {RIO::TestModeChange, 1}; +Byte RIO::reply_test_exit_string[] = {RIO::TestModeChange, 0}; +Byte RIO::reply_analog_string[] = +{ + RIO::AnalogReply, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0 +}; + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Utilities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +int + CombinePair(Byte low_value, Byte high_value) +{ + int result; + + result = ((int) (low_value & 0x7F)) | (((int) high_value) << 7); + if (result & 0x2000) + { + result |= ~0x3FFF; + } + Check_Fpu(); + return result; +} + + +void + BoardError(NotationFile *notation_file, char *type, int position) +{ + Check(notation_file); + Check_Pointer(type); + + char + where[40]; + + sprintf(where, "%s@Slot=%d:Address=%d", type, position >> 3, position & 7); + notation_file->AppendEntry("RIOBoardErrors", "error", where); + Check_Fpu(); +} + +//########################################################################### +//############################ Joystick classes ############################# +//########################################################################### +const char *FilterChannel::highName = "high"; +const char *FilterChannel::centerName = "center"; +const char *FilterChannel::lowName = "low"; +const char *FilterChannel::joystickXName = "JoystickX"; +const char *FilterChannel::joystickYName = "JoystickY"; +const char *FilterChannel::throttleName = "Throttle"; +const char *FilterChannel::leftPedalName = "LeftPedal"; +const char *FilterChannel::rightPedalName = "RightPedal"; + +FilterChannel::FilterChannel(): + average(5,0) +{ + valuesFromFile = False; + previousValue = 0; + polarity = unipolar; + mode = unaligned; + deadbandScalar = default_deadband_value; + + lowerDeadband = 0; + upperDeadband = 0; + + Check_Fpu(); +} + +FilterChannel::FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_max +): + average(5,0) +{ + valuesFromFile = True; + previousValue = 0; + polarity = unipolar; + mode = normal; + deadbandScalar = default_deadband_value; + + pageName = page_name; + min = default_min; + max = default_max; + //------------------------------------------- + // Attempt to read calibration values from + // the notation file. If the values don't + // exist, then create them from the defaults. + //------------------------------------------- + if (init_file->GetEntry(pageName, highName, &max) == 0) + { + init_file->SetEntry(pageName, highName, default_max); + } + + if (init_file->GetEntry(pageName, lowName, &min) == 0) + { + init_file->SetEntry(pageName, lowName, default_min); + } + + center = (max-min)/2; + + Check_Fpu(); +} + +FilterChannel::FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_center, int default_max +): + average(5,0) +{ + valuesFromFile = True; + previousValue = 0; + polarity = bipolar; + mode = normal; + deadbandScalar = default_deadband_value; + + pageName = page_name; + min = default_min; + center = default_center; + max = default_max; + + //------------------------------------------- + // Attempt to read calibration values from + // the notation file. If the values don't + // exist, then create them from the defaults. + //------------------------------------------- + + if (init_file->GetEntry(pageName, highName, &max) == 0) + { + init_file->SetEntry(pageName, highName, default_max); + } + + if (init_file->GetEntry(pageName, centerName, ¢er) == 0) + { + init_file->SetEntry(pageName, centerName, default_center); + } + + if (init_file->GetEntry(pageName, lowName, &min) == 0) + { + init_file->SetEntry(pageName, lowName, default_min); + } + + CalculateDeadBands(); + + Check_Fpu(); +} + +FilterChannel::~FilterChannel() +{ + Check(this); + Check_Fpu(); +} + +void + FilterChannel::SetPolarity(PolarMode newPolarity) +{ + Check(this); + polarity = newPolarity; + + // HACK - filterchannel must be realigned when changing to bipolar! + + Check_Fpu(); +} + +void + FilterChannel::SetDeadBand(Scalar dead_band) +{ + Check(this); + + deadbandScalar = fabs(dead_band); + //--------------------------------------------------------- + // Recalculate deadbands and ranges if needed + //--------------------------------------------------------- + if (mode == normal) + { + CalculateDeadBands(); + } + Check_Fpu(); +} + +void + FilterChannel::BeginAlignment() +{ + Check(this); + //--------------------------------------------------------- + // Set bogus min/max, force update + //--------------------------------------------------------- + mode = unaligned; + min = 10000; + max = -10000; + Check_Fpu(); +} + +void + FilterChannel::EndAlignment(NotationFile *init_file) +{ + Check(this); + //--------------------------------------------------------- + // Save the most recent value as the center + //--------------------------------------------------------- + center = previousValue; + //------------------------------------------------------------ + // If channel was never adjusted, synthesize reasonable values + //------------------------------------------------------------ + // I don't trust abs(): saw weirdness. + int + delta = max-min; + if (delta < 0) + { + delta = -delta; + } + + if (delta < 10) + { + if (polarity == bipolar) + { + min = center-100; + max = center+100; + } + else + { + min = 0; + max = 100; + } + } + else + { + int + setback = delta/33; // move the edges in by 3% + + max -= setback; + min += setback; + } + //--------------------------------------------------------- + // Save the new values + //--------------------------------------------------------- + if (valuesFromFile) + { + if (init_file != NULL) + { + init_file->SetEntry(pageName, highName, max); + init_file->SetEntry(pageName, lowName, min); + + if (polarity == bipolar) + { + init_file->SetEntry(pageName, centerName, center); + } + } + } + //--------------------------------------------------------- + // Calculate real deadband values + //--------------------------------------------------------- + CalculateDeadBands(); + //--------------------------------------------------------- + // Go to normal mode + //--------------------------------------------------------- + mode = normal; + + Check_Fpu(); +} + +Scalar + FilterChannel::Update(int value) +{ + Check(this); + + Scalar + result = 0.0; + + previousValue = value; + + //--------------------------------------------------------- + // Generate average, use for min/max determination + //--------------------------------------------------------- + average.Add(value); + { + int + the_average = average.CalculateOlympicAverage(); + + if (the_average < min) { min = the_average; } + if (the_average > max) { max = the_average; } + } + //--------------------------------------------------------- + // Perform position calculations + //--------------------------------------------------------- + switch (polarity) + { + case unipolar: + { + //--------------------------------------------------------- + // Subtract 'min' from current value + //--------------------------------------------------------- + value -= min; + //--------------------------------------------------------- + // Subtract deadband value + //--------------------------------------------------------- + int + deadband_adjustment = (int) ((max-min)*deadbandScalar); + + value -= deadband_adjustment; + if (value > 0) + { + int + adjusted_maximum = max-deadband_adjustment; + + if (adjusted_maximum > 0) + { + result = ((Scalar)value)/adjusted_maximum; + } + } + } + break; + + case bipolar: + if (mode == unaligned) + { + //--------------------------------------------------------- + // Use 1/2 (max-min) as temporary center + //--------------------------------------------------------- + center = (max-min) >> 1; + //--------------------------------------------------------- + // Set temporary deadband values + //--------------------------------------------------------- + upperDeadband = (int) ((max-min)*deadbandScalar); + lowerDeadband= upperDeadband; + } + //--------------------------------------------------------- + // Adjust for center + //--------------------------------------------------------- + value -= center; + //--------------------------------------------------------- + // Generate scaled results + //--------------------------------------------------------- + if (value < 0) + { + value += lowerDeadband; + if (value < 0) + { + if (lowerRange > 0) + { + if (value <= -lowerRange) + { + result = -1.0; + } + else + { + result = ((Scalar) value)/lowerRange; + } + } + } + } + else + { + value -= upperDeadband; + if (value > 0) + { + if (upperRange > 0) + { + if (value >= upperRange) + { + result = 1.0; + } + else + { + result = ((Scalar) value)/upperRange; + } + } + } + } + break; + } + //--------------------------------------------------------- + // Return result + //--------------------------------------------------------- + Check_Fpu(); + +# if defined(DEBUG) + DEBUG_STREAM << pageName << ":" << value << "=" << result << "\n"; +# endif + + return result; +} + +Logical + FilterChannel::TestInstance() const +{ + return True; +} + +void + FilterChannel::CalculateDeadBands() +{ + Check(this); + + lowerDeadband = (int) ((center-min)*deadbandScalar + .5); + lowerRange = center - (min+lowerDeadband); + + upperDeadband = (int) ((max-center)*deadbandScalar + .5); + upperRange = (max-upperDeadband) - center; + +# if defined(DEBUG) + DEBUG_STREAM << "pageName =" << pageName <<"\n"; + DEBUG_STREAM << "min =" << min <<"\n"; + DEBUG_STREAM << "center=" << center <<"\n"; + DEBUG_STREAM << "max= " << max <<"\n"; + DEBUG_STREAM << "lowerDeadband= " << lowerDeadband <<"\n"; + DEBUG_STREAM << "lowerRange = " << lowerRange <<"\n"; + DEBUG_STREAM << "upperDeadband= " << upperDeadband <<"\n"; + DEBUG_STREAM << "upperRange = " << upperRange <<"\n"; +# endif + + Check_Fpu(); +} + + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ranger ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Ranger::Ranger( + const char *page_name, + int hardware_min, + int hardware_max, + Scalar deadband +){ + Check_Pointer(this); + + pageName = page_name; + hardwareMinimum = hardware_min; + hardwareMaximum = hardware_max; + + SetDeadBand(deadband); + //------------------------------------------------------------ + // We ASSUME that the control is at rest (center for joystick) + //------------------------------------------------------------ + ForceToZero(); + + Check_Fpu(); +} + +Ranger::~Ranger() +{ + Check(this); + Check_Fpu(); +} + +Logical + Ranger::TestInstance() const +{ + Check_Fpu(); + return True; +} + +void + Ranger::SetDeadBand(Scalar dead_band) +{ + Check(this); + + deadbandInteger = + (int)((hardwareMaximum - hardwareMinimum) * fabs(dead_band)); + + Check_Fpu(); +} + +void + Ranger::ForceToZero() +{ + Check(this); + sampledInputFlag = False; + Check_Fpu(); +} + +Scalar + Ranger::Update(int input) +{ + Check(this); + int + range; + Scalar + result = ((Scalar) 0); + + Verify(hardwareMaximum > hardwareMinimum); + //------------------------------------------------------------ + // Uncentered processing: slide offset to keep value + // within the proscribed range + //------------------------------------------------------------ + if (hardwareMinimum >= 0) // this designates an uncentered Ranger + { + //--------------------------------------------------------- + // Sample current input for offset value + //--------------------------------------------------------- + if (!sampledInputFlag) + { + sampledInputFlag = True; + + offset = -input; + //------------------------------------------ + // Initialize to reasonable values + //------------------------------------------ + highestInput = (hardwareMaximum*3)/4; + lowestInput = hardwareMinimum; + } + //------------------------------------------------------------ + // Add offset + //------------------------------------------------------------ + input += offset; + //------------------------------------------------------------ + // Slide offset if needed + //------------------------------------------------------------ + if (input > hardwareMaximum) + { + offset -= input-hardwareMaximum; + input = hardwareMaximum; + } + else if (input < hardwareMinimum) + { + offset -= input-hardwareMinimum; + input = hardwareMinimum; + } + //----------------------------------------------------------------- + // Keep track of limit (lowestValue will always be hardwareMinimum) + //----------------------------------------------------------------- + if (input > highestInput) + { + highestInput = input; + } + //------------------------------------------------------------ + // Generate scaled result + //------------------------------------------------------------ + input -= hardwareMinimum; // normalize to zero + + if (input > deadbandInteger) + { + range = highestInput - lowestInput - deadbandInteger; + + if (range > 0) + { + result = ((Scalar)(input-deadbandInteger))/(Scalar)range; + } + } + } + //------------------------------------------------------------ + // Centered processing: keep max, min of input to + // determine total range + //------------------------------------------------------------ + else + { + //--------------------------------------------------------- + // Sample current input for offset value + //--------------------------------------------------------- + if (!sampledInputFlag) + { + sampledInputFlag = True; + //------------------------------------------ + // Set offset such that this is the new zero + //------------------------------------------ + offset = -input; + //------------------------------------------ + // Initialize to reasonable values... + // ...add offset to reflect true limits + // that are available with this offset + //------------------------------------------ + // HardwareMinimum is known to be negative because of 'if' statement + Verify(hardwareMaximum > 0); + + highestInput = (hardwareMaximum*3)/4 + offset; + lowestInput = (hardwareMinimum*3)/4 + offset; + } + //------------------------------------------------------------ + // Adjust for offset + //------------------------------------------------------------ + input += offset; + + if (input > highestInput) + { + highestInput = input; + } + if (input < lowestInput) + { + lowestInput = input; + } + //--------------------------------------- + // Let's make sure before we continue... + //--------------------------------------- + Verify(highestInput >= lowestInput); + Verify(input <= highestInput); + Verify(input >= lowestInput); + //------------------------------------------------------------ + // Generate scaled result + //------------------------------------------------------------ + if (input < -deadbandInteger) + { + //--------------------------------------- + // Generate range + //--------------------------------------- + range = abs(lowestInput) - deadbandInteger; + //--------------------------------------- + // Generate scaled result + //--------------------------------------- + if (range > 0) + { + result = ((Scalar)(input+deadbandInteger))/(Scalar)range; + } + } + else if (input > deadbandInteger) + { + //--------------------------------------- + // Generate range + //--------------------------------------- + range = abs(highestInput) - deadbandInteger; + //--------------------------------------- + // Generate scaled result + //--------------------------------------- + if (range > 0) + { + result = ((Scalar)(input-deadbandInteger))/(Scalar)range; + } + } + } + + if (result > ((Scalar) 1.0)) + { + DEBUG_STREAM << + "Too high!" << + " input=" << input << " result=" << result << "\n" << + + pageName << + " offset=" << offset << + " lowestInput=" << lowestInput << + " highestInput=" << highestInput << + " deadbandInteger=" << deadbandInteger << + " range=" << range << + "\n"; + + result = ((Scalar) 1.0); +//Fail("Ranger::Update above 1.0"); + } + else if (result < ((Scalar)-1.0)) + { + DEBUG_STREAM << + "Too low!" << + " input=" << input << " result=" << result << "\n" << + + pageName << + " lowestInput=" << lowestInput << + " highestInput=" << highestInput << + " deadbandInteger=" << deadbandInteger << + " range=" << range << + "\n"; + + result = ((Scalar)-1.0); +//Fail("Ranger::Update below -1.0"); + } + + Verify(result <= ((Scalar) 1.0)); + Verify(result >= ((Scalar) -1.0)); + + Check_Fpu(); + return result; +} + +void + Ranger::Statistics(NotationFile *failure_file) +{ + Check(this); + Check(failure_file); + + int + range = highestInput - lowestInput, + hardware_range = hardwareMaximum - hardwareMinimum; + + Verify(hardware_range > 0); + + Scalar + range_percentage = ((Scalar) range)/hardware_range; + //--------------------------------- + // Report slippage + //--------------------------------- + if (range_percentage > (Scalar) 1.1) // allow 10% overrange + { + failure_file->SetEntry(pageName, "Overrange", range_percentage); + } + //--------------------------------- + // Report low range + //--------------------------------- + if (range_percentage < (Scalar) .50) + { + failure_file->SetEntry(pageName, "UnderRange", range_percentage); + } + Check_Fpu(); +} + +//######################################################################## +//############################### RIO #################################### +//######################################################################## + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RIO::RIO(Word port, Word intNum, Logical perform_tests): + PCSerialPacket() +{ + Tell("RIO initialization: variables\n"); + Check_Pointer(this); + + // + //--------------------------------------------------------------------- + // Initialize values + //--------------------------------------------------------------------- + // + TestModeActive = 0; + + Throttle = (Scalar) 0; + LeftPedal = (Scalar) 0; + RightPedal = (Scalar) 0; + JoystickX = (Scalar) 0; + JoystickY = (Scalar) 0; + + remoteRetryCount = 0; + remoteAbandonCount = 0; + remoteFullBufferCount = 0; + lineErrorCount = 0; + overrunCount = 0; + abandonCount = 0; + operational = True; +// discardCount = 0; + + failureFile = NULL; + failureFileOpenCount = 0; + // + //--------------------------------------------------------------------- + // Clear error log + //--------------------------------------------------------------------- + // + OpenFailureFile(); + Check(failureFile); + failureFile->DeletePage("RIOBoardErrors"); + failureFile->DeletePage("RIODeadLamps"); + failureFile->DeletePage("RIOErrors"); + CloseFailureFile(); + // + //--------------------------------------------------------------------- + // Read value ranges from notation file, initialize rangers + // + // Order of integers is: minimum, maximum, end-zone-range, deadband + //--------------------------------------------------------------------- + // + { +// NotationFile +// stat_file((const char *) "RIO.INI"); + + leftPedalRanger = new Ranger("LeftPedal", 0, 470, .0); + Register_Object(leftPedalRanger); + + rightPedalRanger = new Ranger("RightPedal", 0, 470, .0); + Register_Object(rightPedalRanger); + + throttleRanger = new Ranger("Throttle", 0, 800, .05); + Register_Object(throttleRanger); + + joystickXRanger = new Ranger("JoystickX", -96, 96, .05); + Register_Object(joystickXRanger); + + joystickYRanger = new Ranger("JoystickY", -97, 108, .05); + Register_Object(joystickYRanger); + } + // + //--------------------------------------------------------------------- + // Start the PCSerialPacket + //--------------------------------------------------------------------- + // + int + status = PCSerialPacket::Initialize( + PCSP_9600, + port, + intNum, + (Byte *) RIOLengths, + 13, + (Byte *) RIOLengths, + 13 + ); + + switch(status) + { + case PCSPAKInitOk: + // silent if OK + break; + case PCSPAKInitErrDPMI: + DEBUG_STREAM << "RIO::RIO DPMI error!\n"; + break; + case PCSPAKInitErrAlloc: + DEBUG_STREAM << "RIO::RIO buffer allocation error!\n"; + break; + default: + DEBUG_STREAM << "RIO::RIO unexpected init result=" << status << "!\n"; + break; + } + +#if 0 + extern Byte previousIMR, previousISR, previousIRR; + extern Byte middleIMR, middleISR, middleIRR; + extern Byte postIMR, postISR, postIRR; + extern Byte pcspakLSR, pcspakIER, pcspakIIR; + + DEBUG_STREAM << + hex << + "previousIMR=" << (int) (previousIMR & 0xFF) << + ", mid=" << (int) (middleIMR & 0xFF) << + ", post=" << (int) (postIMR & 0xFF) << "\n" << + + "previousISR=" << (int) (previousISR & 0xFF) << + ", mid=" << (int) (middleISR & 0xFF) << + ", post=" << (int) (postISR & 0xFF) << "\n" << + + "previousIRR=" << (int) (previousIRR & 0xFF) << + ", mid=" << (int) (middleIRR & 0xFF) << + ", post=" << (int) (postIRR & 0xFF) << "\n" << + + "pcspakLSR=" << (int) (pcspakLSR & 0xFF) << + ", pcspakIER=" << (int) (pcspakIER & 0xFF) << + ", pcspakIIR was=" << (int) (pcspakIIR & 0xFF) << "\n" << + dec; +#endif + + MajorRevision = 0xFF; + MinorRevision = 0xFF; + + if (perform_tests) + { + // + //--------------------------------------------------------------------- + // Reset remote I/O board + //--------------------------------------------------------------------- + // + Time + when; + int + bomb = 0; + + RIOEvent + dummy_event; + + Tell("RIO initialization: reset board\n"); + + // Reset RIO board + SetDTR(True); // Assert reset + when = Now(); + for(when += .1; Now() < when; ); + + SetDTR(False); // Retract reset + when = Now(); + for(when += 1.0; Now() < when; ); + + // + //--------------------------------------------------------------------- + // Wait for test mode to start (or bomb out) + //--------------------------------------------------------------------- + // + Tell("RIO initialization: check board\n"); + RequestCheck(); + + when = Now(); + when += 5.0; + while (!TestModeActive) + { + if (Now() > when) + { + bomb = 1; + DEBUG_STREAM << "RIO never came back from check request!\n"; + break; + } + GetNextEvent(&dummy_event); + } + // + //--------------------------------------------------------------------- + // Wait for test mode to finish (or bomb out) + //--------------------------------------------------------------------- + // + if (!bomb) + { + when = Now(); + when += 5.0; + while (TestModeActive) + { + if (Now() > when) + { + bomb = 1; + DEBUG_STREAM << "RIO never came back from test mode!\n"; + break; + } + GetNextEvent(&dummy_event); + } + } + // + //--------------------------------------------------------------------- + // Get version (or bomb out) + //--------------------------------------------------------------------- + // + + if (!bomb) + { + RequestVersion(); + when = Now(); + when += 5.0; + while (MajorRevision == 0xFF) + { + if (Now() > when) + { + DEBUG_STREAM << "RIO never came back from version request!\n"; + break; + } + GetNextEvent(&dummy_event); + } + } + } + + Tell("RIO initialization finished\n"); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +extern int historyIndex; +extern Byte history[]; + +enum +{ + txFlag=1, + rxFlag=2, + eventFlag=3 +}; + +enum +{ + IRQ_EVENT=0, + IRQ_EVENT_RX=1, + IRQ_EVENT_TX=2, + IRQ_EVENT_MSR=3, + IRQ_EVENT_LSR=4, + IRQ_EVENT_BOGUS=5, + + TX_EVENT_RESTART=10, + TX_EVENT_ABANDON=11, + TX_EVENT_DONE=12, + TX_EVENT_ACK=13, + TX_EVENT_NAK=14, + TX_EVENT_EARLY=15, + TX_EVENT_EMPTY=16, + TX_EVENT_KICK=17, + + RX_EVENT_FULL=20, + RX_EVENT_NOT_CMD=21, + RX_EVENT_FULLBODY=22, + RX_EVENT_NAK=23, + RX_EVENT_CKSMERR=24, + RX_EVENT_OK=25 +}; + +RIO::~RIO() +{ + Check(this); + +#if 0 + //--------------------------------------------------------------------- + // Save serial history for debugging + //--------------------------------------------------------------------- + // If you enable this, set KEEP_HISTORY in PCSPAK.ASM to '1' as well. + // Otherwise you will be viewing nonexistent history data. + const char + *commandName[13] = + { + "CheckReq", //=0x80 + "VersionReq", + "AnalogReq", + "ResetReq", + "LampReq", + "CheckReply", + "VersionReply", + "AnalogReply", + "ButtonPressed", + "ButtonReleased", + "KeyPressed", + "KeyReleased", + "TestModeChange" + }; + + + int i, type, j; + + cout << flush; + printf("tx\t\trx\t\tevent\n"); + printf("-----\t-----\t\t---------------------\n"); + for(i=0; i= 0x80) && (j <= 0x8C)) + { + printf("%s", commandName[j-0x80]); + } + else + { + printf("%02X", j); + } + printf("\n"); + break; + } + break; + case rxFlag: + printf("\t\t"); + switch(j) + { + case 0xFC: printf("ACK\n"); break; + case 0xFD: printf("NAK\n"); break; + case 0xFE: printf("RST\n"); break; + case 0xFF: printf("IDL\n"); break; + default: + if ((j >= 0x80) && (j <= 0x8C)) + { + printf("%s", commandName[j-0x80]); + } + else + { + printf("%02X", j); + } + printf("\n"); + break; + } + break; + case eventFlag: + printf("\t\t\t\t"); + switch(j) + { + case IRQ_EVENT: printf("IRQ entry\n"); break; + case IRQ_EVENT_RX: printf("IRQ_EVENT_RX\n"); break; + case IRQ_EVENT_TX: printf("IRQ_EVENT_TX\n"); break; + case IRQ_EVENT_MSR: printf("IRQ_EVENT_MSR\n"); break; + case IRQ_EVENT_LSR: printf("IRQ_EVENT_LSR\n"); break; + case IRQ_EVENT_BOGUS: printf("IRQ_EVENT_BOGUS\n"); break; + + case TX_EVENT_RESTART: printf("TX_EVENT_RESTART\n"); break; + case TX_EVENT_ABANDON: printf("TX_EVENT_ABANDON\n"); break; + case TX_EVENT_DONE: printf("TX_EVENT_DONE\n"); break; + case TX_EVENT_ACK: printf("TX_EVENT_ACK\n"); break; + case TX_EVENT_NAK: printf("TX_EVENT_NAK\n"); break; + case TX_EVENT_EARLY: printf("TX_EVENT_EARLY\n"); break; + case TX_EVENT_EMPTY: printf("TX_EVENT_EMPTY\n"); break; + case TX_EVENT_KICK: printf("TX_EVENT_KICK\n"); break; + + case RX_EVENT_FULL: printf("RX_EVENT_FULL\n"); break; + case RX_EVENT_NOT_CMD: printf("RX_EVENT_NOT_CMD\n"); break; + case RX_EVENT_FULLBODY: printf("RX_EVENT_FULLBODY\n"); break; + case RX_EVENT_NAK: printf("RX_EVENT_NAK\n"); break; + case RX_EVENT_CKSMERR: printf("RX_EVENT_CKSMERR\n"); break; + case RX_EVENT_OK: printf("RX_EVENT_OK\n"); break; + default: printf("unknown event %02X\n", j); break; + } + break; + } + } + fflush(stdout); +#endif + + //--------------------------------------------------------------------- + // Flush data to RIO + //--------------------------------------------------------------------- + RIOEvent + dummy_event; + + // This odd sequence of allocation, setting, and adding is necessary: + // if you try to combine them, the compiler gets confused as to which + // method to invoke for 'Now()'. + Time + then; + then = Now(); + then += 5.0; + while (Now() < then) + { + //------------------------------------------------- + // Drop out of loop when all packets have been + // transmitted and the last character has been sent + //------------------------------------------------- + if (TransmitQueueCount() <= 0) + { + if (!IsActive()) + { + break; + } + } + GetNextEvent(&dummy_event); + } + + //--------------------------------------------------------------------- + // Update failure log + //--------------------------------------------------------------------- +#if LOG_RIO_DATA + OpenFailureFile(); + Check(failureFile); + + failureFile->SetEntry("RIO","lineErrors",lineErrorCount); + failureFile->SetEntry("RIO","abandonedPackets",abandonCount); + failureFile->SetEntry("RIO","overruns",overrunCount); + failureFile->SetEntry("RIO","remoteRetry",remoteRetryCount); + failureFile->SetEntry("RIO","remoteAbandon",remoteAbandonCount); + failureFile->SetEntry("RIO","remoteFullBuffer",remoteFullBufferCount); + + CloseFailureFile(); +#endif + + //------------------------------------------- + // Update ranger statistics, delete rangers + //------------------------------------------- + { +// NotationFile +// stat_file((const char *) "RIO.INI"); + + Check(leftPedalRanger); +// leftPedalRanger->Statistics(&stat_file); + Unregister_Object(leftPedalRanger); + delete leftPedalRanger; + leftPedalRanger = NULL; + + Check(rightPedalRanger); +// rightPedalRanger->Statistics(&stat_file); + Unregister_Object(rightPedalRanger); + delete rightPedalRanger; + rightPedalRanger = NULL; + + Check(throttleRanger); +// throttleRanger->Statistics(&stat_file); + Unregister_Object(throttleRanger); + delete throttleRanger; + throttleRanger = NULL; + + Check(joystickXRanger); +// joystickXRanger->Statistics(&stat_file); + Unregister_Object(joystickXRanger); + delete joystickXRanger; + joystickXRanger = NULL; + + Check(joystickYRanger); +// joystickYRanger->Statistics(&stat_file); + Unregister_Object(joystickYRanger); + delete joystickYRanger; + joystickYRanger = NULL; + } + Check_Fpu(); +} + +Logical + RIO::TestInstance() const +{ + return True; +} + +extern Byte pic_isr, pic_imr, pic_irr; +extern Byte uart_iir; +extern Byte pcspak_active,pcspak_rxState,pcspak_txState; +extern Word pcspak_head,pcspak_tail; +extern Word pcspak_tempHead,pcspak_tempTail,pcspak_count; + +extern "C" void + PCSPAKState(PCSerialPacket *ptr); + +Logical + RIO::GetNextEvent(RIOEvent *destination) +{ + Check(this); + + Byte receive_buffer[256]; + Logical reply, looping; + Word errors; + +//PCSPAKState(this); +// +//cout << flush; +//printf( +// "RIO isr=%02X imr=%02X irr=%02X, iir=%02X, a=%1d c=%04X ts=%1d rs=%1d e=%X\n", +// pic_isr, pic_imr, pic_irr, +// uart_iir, +// pcspak_active, +// pcspak_count, +// pcspak_txState, pcspak_rxState, +// pcspak_tempHead,pcspak_tempTail, +// Errors() +//); +//fflush(stdout); + + if (! operational) + { + return False; + } + + errors = Errors(); + if (errors) + { + if (errors & PCSerialPacket::initError) + { + NotationFile + failure((const char *) "FAILURE.LOG"); + + failure.SetEntry("RIOErrors","error","initialization"); + operational = False; + } + else + { + if (errors & PCSerialPacket::txAbandonPacket) + { +//cout << "RIO:: packet abandoned\n"; + ++abandonCount; + } + if (errors & PCSerialPacket::overrunError) + { +//cout << "RIO:: overrun\n"; + ++overrunCount; + } + if (errors & + ( + PCSerialPacket::parityError | + PCSerialPacket::framingError | + PCSerialPacket::overrunError + ) + ) + { + ++lineErrorCount; + } + } + } + + do + { + looping = False; + + reply = ReceivePacket(receive_buffer); + if (reply) + { + switch(receive_buffer[0]) + { + case CheckReply: + switch(receive_buffer[1]) + { + case BoardMissing: + OpenFailureFile(); + BoardError(failureFile,"missing_board",(int) receive_buffer[2]); + CloseFailureFile(); + break; + + case BoardBad: + OpenFailureFile(); + BoardError(failureFile,"dead_board",(int) receive_buffer[2]); + CloseFailureFile(); + break; + + case LampBad: + OpenFailureFile(); + Check(failureFile); + failureFile->AppendEntry( + "RIODeadLamps", + "lamp", + LBE4ControlsManager::GetLampName((int) receive_buffer[2]) + ); + CloseFailureFile(); + break; + + case RestartCount: + remoteRetryCount += receive_buffer[2]; + break; + + case AbandonCount: + remoteAbandonCount += receive_buffer[2]; + break; + + case FullBufferCount: + remoteFullBufferCount += receive_buffer[2]; + break; + } + looping = True; // status events not sent to host + break; + + case VersionReply: + destination->Type = RIO::VersionEvent; + MajorRevision = receive_buffer[1]; + MinorRevision = receive_buffer[2]; + break; + + case AnalogReply: + destination->Type = RIO::AnalogEvent; + // + // NOTE: no data is sent in this packet. + // The application is expected to directly read + // the values in the object. + // + + //---------------------------------------- + // Discard the next N analog packets + // (set by ForceCenterJoystick) + //---------------------------------------- +// if (discardCount) +// { +// --discardCount; +// } +// else + { + Check(throttleRanger); + Throttle = throttleRanger->Update( + // Note (-): Throttle counts BACKWARDS + -CombinePair(receive_buffer[1], receive_buffer[2]) + ); + + Check(leftPedalRanger); + LeftPedal = leftPedalRanger->Update( + CombinePair(receive_buffer[3], receive_buffer[4]) + ); + + Check(rightPedalRanger); + RightPedal = rightPedalRanger->Update( + CombinePair(receive_buffer[5], receive_buffer[6]) + ); + + Check(joystickYRanger); + JoystickY = joystickYRanger->Update( + CombinePair(receive_buffer[7], receive_buffer[8]) + ); + + Check(joystickXRanger); + JoystickX = joystickXRanger->Update( + CombinePair(receive_buffer[9], receive_buffer[10]) + ); + } + break; + + case ButtonPressed: + destination->Type = RIO::ButtonPressedEvent; + destination->Data.Unit = receive_buffer[1]; + break; + + case ButtonReleased: + destination->Type = RIO::ButtonReleasedEvent; + destination->Data.Unit = receive_buffer[1]; + break; + + case KeyPressed: + destination->Type = RIO::KeyEvent; + destination->Data.Keyboard.Unit = receive_buffer[1]; + destination->Data.Keyboard.Key = receive_buffer[2]; + break; + + case TestModeChange: + if (receive_buffer[1] != 0) + { + Tell("RIO entered test mode\n"); + TestModeActive = 1; + + OpenFailureFile(); + Check(failureFile); + failureFile->DeletePage("RIOBoardErrors"); + failureFile->DeletePage("RIODeadLamps"); + } + else + { + Tell("RIO exited test mode\n"); + TestModeActive = 0; + CloseFailureFile(); + } + looping = True; // this event not sent to host + break; + + default: // discard unused or bogus packets + looping = True; + break; + } + } + } + while (looping); + + Check_Fpu(); + return reply; +} + +void + RIO::ForceCenterJoystick() +{ + Check(this); + +// ResetVerticalJoystick(); +// ResetHorizontalJoystick(); + //------------------------------------------- + // Make sure we don't use 'old' data + // (skip the next two packets) + // ...why 2? Just to make sure... + //------------------------------------------- +// discardCount = 2; + + Check(joystickXRanger); + joystickXRanger->ForceToZero(); + + Check(joystickYRanger); + joystickYRanger->ForceToZero(); + + Check_Fpu(); +} + +void + RIO::SetJoystickDeadBand(Scalar dead_band) +{ + Check(this); + + Check(joystickXRanger); + joystickXRanger->SetDeadBand(dead_band); + + Check(joystickYRanger); + joystickYRanger->SetDeadBand(dead_band); + + Check_Fpu(); +} + +void + RIO::SetThrottleDeadBand(Scalar dead_band) +{ + Check(this); + + Check(throttleRanger); + throttleRanger->SetDeadBand(dead_band); + + Check_Fpu(); +} + +void + RIO::SetPedalsDeadBand(Scalar dead_band) +{ + Check(this); + + Check(leftPedalRanger); + leftPedalRanger->SetDeadBand(dead_band); + + Check(rightPedalRanger); + rightPedalRanger->SetDeadBand(dead_band); + + Check_Fpu(); +} + +void + RIO::RequestCheck() +{ + Check(this); + static Byte request_check_string[] = { RIO::CheckRequest }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_check_string); + } + Check_Fpu(); +} + +void + RIO::RequestVersion() +{ + Check(this); + static Byte request_version_string[] = { RIO::VersionRequest }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_version_string); + } + Check_Fpu(); +} + +void + RIO::RequestAnalogUpdate() +{ + Check(this); + static Byte request_analog_string[] = { RIO::AnalogRequest }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_analog_string); + } + Check_Fpu(); +} + +void + RIO::GeneralReset() +{ + Check(this); + static Byte request_reset_string[] = { RIO::ResetRequest, 0 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_reset_string); + } + Check_Fpu(); +} + +void + RIO::ResetThrottle() +{ + Check(this); + static Byte request_throttle_string[] = { RIO::ResetRequest, 1 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_throttle_string); + } + Check_Fpu(); +} + +void + RIO::ResetLeftPedal() +{ + Check(this); + static Byte request_lpedal_string[] = { RIO::ResetRequest, 2 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_lpedal_string); + } + Check_Fpu(); +} + +void + RIO::ResetRightPedal() +{ + Check(this); + static Byte request_rpedal_string[] = { RIO::ResetRequest, 3 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_rpedal_string); + } + Check_Fpu(); +} + +void + RIO::ResetVerticalJoystick() +{ + Check(this); + static Byte request_vstick_string[] = { RIO::ResetRequest, 4 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_vstick_string); + } + Check_Fpu(); +} + +void + RIO::ResetHorizontalJoystick() +{ + Check(this); + static Byte request_hstick_string[] = { RIO::ResetRequest, 5 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_hstick_string); + } + Check_Fpu(); +} + +void + RIO::SetLamp(int lampNumber, int state) +{ + Check(this); + static Byte request_lamp_string[] = { RIO::LampRequest, 0, 0 }; + + if (operational) + { + request_lamp_string[1] = (Byte) (lampNumber & 0x7F); + request_lamp_string[2] = (Byte) (state & 0x7F); + SendPacket((Byte *) request_lamp_string); + } + Check_Fpu(); +} + +void + RIO::OpenFailureFile() +{ + Check(this); + + if (failureFileOpenCount == 0) + { + failureFile = new NotationFile("FAILURE.LOG"); + Check(failureFile); + Register_Object(failureFile); + } + ++failureFileOpenCount; + Check_Fpu(); +} + +void + RIO::CloseFailureFile() +{ + Check(this); + + --failureFileOpenCount; + if (failureFileOpenCount <= 0) + { + failureFileOpenCount = 0; + + Check(failureFile); + Unregister_Object(failureFile); + delete failureFile; + } + Check_Fpu(); +} + diff --git a/CODE/RP/MUNGA_L4/L4RIO.HPP b/CODE/RP/MUNGA_L4/L4RIO.HPP new file mode 100644 index 0000000..9262b4f --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4RIO.HPP @@ -0,0 +1,342 @@ +//===========================================================================// +// File: RIO.hh // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: Remote I/O interface class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/30/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(L4RIO_HPP) + +# define L4RIO_HPP + +# if !defined(L4PCSPAK_HPP) +# include "l4pcspak.hpp" +# endif + +# if !defined(NOTATION_HPP) +# include +# endif + +# if !defined(AVERAGE_HPP) +# include +# endif + + // These are purposely grouped as two parameters in one equate + // (See PCSPAK.HH). + // The standard PC COM ports ALWAYS use these combinations. +# define RIO_COM1 PCSP_COM1 +# define RIO_COM2 PCSP_COM2 +# define RIO_COM3 PCSP_COM3 +# define RIO_COM4 PCSP_COM4 + + + class FilterChannel SIGNATURED + { + public: + static const char *highName; + static const char *centerName; + static const char *lowName; + static const char *joystickXName; + static const char *joystickYName; + static const char *throttleName; + static const char *leftPedalName; + static const char *rightPedalName; + + enum AlignMode { unaligned, normal }; + enum PolarMode { unipolar, bipolar }; + + FilterChannel(); + FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_max + ); + FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_center, int default_max + ); + ~FilterChannel(); + void + SetPolarity(PolarMode newPolarity); + void + SetDeadBand(Scalar amount_of_deadband); + virtual void + BeginAlignment(); + virtual void + EndAlignment(NotationFile *init_file=NULL); + virtual Scalar + Update(int value); + Logical + TestInstance() const; + + protected: + void + CalculateDeadBands(); + + const char *pageName; + PolarMode polarity; + AlignMode mode; + int previousValue, min, max, center; + int lowerRange, lowerDeadband; + int upperRange, upperDeadband; + Scalar deadbandScalar; + Logical valuesFromFile; + AverageOf average; + }; + + + class RIO; + + class Ranger SIGNATURED + { + friend class RIO; + protected: + Ranger( + const char *page_name, + int default_min, + int default_max, + Scalar deadband_scalar + ); + + ~Ranger(); + + void + ForceToZero(); + void + SetDeadBand(Scalar amount_of_deadband); + Scalar + Update(int input); + Logical + TestInstance() const; + void + Statistics(NotationFile *stat_file); + + const char + *pageName; + Logical + sampledInputFlag; + int + offset, + hardwareMinimum, + hardwareMaximum, + hardwareRange, + deadbandInteger, + highestInput, + lowestInput; + }; + + class RIO : + public PCSerialPacket + { + protected: + enum RIOCommand{ + CheckRequest=0x80, + VersionRequest, + AnalogRequest, + ResetRequest, + LampRequest, + CheckReply, + VersionReply, + AnalogReply, + ButtonPressed, + ButtonReleased, + KeyPressed, + KeyReleased, + TestModeChange + }; + + public: + enum RIOStatusType { + BoardOk=0, BoardMissing=1, BoardBad=2, + LampBad=3, + RestartCount=4, AbandonCount=5, FullBufferCount=6 + }; + + enum LampState{ + solid=0, flashSlow=1, flashMed=2, flashFast=3, + state1Off=0x00, state1Dim=0x04, state1Bright=0x0C, + state2Off=0x00, state2Dim=0x10, state2Bright=0x30, + }; + + enum RIOEventType { + ButtonPressedEvent, + ButtonReleasedEvent, + KeyEvent, + AnalogEvent, + VersionEvent + }; + + struct RIOKeyPair + { + int Unit; + int Key; + }; + + struct RIOEvent + { + RIOEventType Type; + union + { + int Unit; + RIOKeyPair Keyboard; + }Data; + }; + + RIO(Word port, Word intNum, Logical perform_tests = True); + ~RIO(); + + Logical + TestInstance() const; + + Logical + GetNextEvent(RIOEvent *destinationPointer); + + void + ForceCenterJoystick(), + SetJoystickDeadBand(Scalar dead_band), + SetThrottleDeadBand(Scalar dead_band), + SetPedalsDeadBand(Scalar dead_band); + + void + RequestCheck(), + RequestVersion(), + RequestAnalogUpdate(); + + void + GeneralReset(), + ResetThrottle(), + ResetLeftPedal(), + ResetRightPedal(), + ResetVerticalJoystick(), + ResetHorizontalJoystick(); + + void + SetLamp(int lampNumber, int state); + + void + TestCheckReply(int type, int location) + { + RIO::reply_check_string[1] = (Byte) (type & 0x7F); + RIO::reply_check_string[2] = (Byte) (location & 0x7F); + SendPacket((Byte *)reply_check_string); + } + + void + TestVersionReply(int major, int minor) + { + RIO::reply_version_string[1] = (Byte) (major & 0x7F); + RIO::reply_version_string[2] = (Byte) (minor & 0x7F); + SendPacket((Byte *)reply_version_string); + } + + void + TestAnalogReply() + { + SendPacket((Byte *)reply_analog_string); + } + + void + TestButtonPressed(int button) + { + RIO::reply_button_press_string[1] = (Byte) (button & 0x7F); + SendPacket((Byte *)reply_button_press_string); + } + + void + TestButtonReleased(int button) + { + RIO::reply_button_release_string[1] = (Byte) (button & 0x7F); + SendPacket((Byte *)reply_button_release_string); + } + + void + TestKeyPressed(int board, int key) + { + RIO::reply_key_press_string[1] = (Byte) (board & 0x7F); + RIO::reply_key_press_string[2] = (Byte) (key & 0x7F); + SendPacket((Byte *)reply_key_press_string); + } + + void + TestKeyReleased(int board, int key) + { + RIO::reply_key_release_string[1] = (Byte) (board & 0x7F); + RIO::reply_key_release_string[2] = (Byte) (key & 0x7F); + SendPacket((Byte *)reply_key_release_string); + } + + void + TestEnterTestMode() + {SendPacket((Byte *)reply_test_enter_string);} + + void + TestExitTestMode() + {SendPacket((Byte *)reply_test_exit_string);} + + int + ReceiveQueueCount() + { return PCSerialPacket::ReceiveQueueCount(); } + + int + TransmitQueueCount() + { return PCSerialPacket::TransmitQueueCount(); } + + int + TestModeActive; + + Scalar + Throttle, LeftPedal, RightPedal, JoystickX, JoystickY; + + int + MajorRevision, MinorRevision; + + int remoteRetryCount; + int remoteAbandonCount; + int remoteFullBufferCount; + int lineErrorCount; + int abandonCount; + int overrunCount; + + int discardCount; // used by BeginAnalogCalibration() + + protected: + void + OpenFailureFile(); + + void + CloseFailureFile(); + + void + CheckErrors(); + + Logical + operational; + Ranger + *leftPedalRanger, *rightPedalRanger; + Ranger + *throttleRanger; + Ranger + *joystickXRanger, *joystickYRanger; + NotationFile + *failureFile; + int + failureFileOpenCount; + + static Byte reply_check_string[]; + static Byte reply_version_string[]; + static Byte reply_analog_string[]; + static Byte reply_button_press_string[]; + static Byte reply_button_release_string[]; + static Byte reply_key_press_string[]; + static Byte reply_key_release_string[]; + static Byte reply_test_enter_string[]; + static Byte reply_test_exit_string[]; + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4SERIAL.ASM b/CODE/RP/MUNGA_L4/L4SERIAL.ASM new file mode 100644 index 0000000..e42bf5a --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4SERIAL.ASM @@ -0,0 +1,1248 @@ +;=========================================================================== +; File: L$SERIAL.asm +; Project: MUNGA +; Contents: PC serial driver +;--------------------------------------------------------------------------- +; Date Who Modification +; -------- --- ----------------------------------------------------------- +; 01/16/95 CPB Initial coding +;--------------------------------------------------------------------------- +; Copyright (C) 1994, Virtual World Entertainment, Inc. +; All Rights reserved worldwide +; This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL +;=========================================================================== + +THE_WAY_IT_WAS equ 0 + + include l4asm.inc + include pcserial.inc + include pcpic.inc + include pcdpmi.inc +;=========================================================================== +; Equates +;=========================================================================== + +TICK MACRO ;debugging macro: ticks the speaker + + push dx + push ax + + mov dx,061h + in al,dx + + xor al,002h + out dx,al + + nop + nop + nop + + xor al,002h + out dx,al + + pop ax + pop dx +ENDM + +SPKR_SET MACRO ;debugging macro + + push dx + push ax + + mov dx,061h + in al,dx + + or al,002h + out dx,al + + pop ax + pop dx +ENDM + +SPKR_RESET MACRO ;debugging macro + + push dx + push ax + + mov dx,061h + in al,dx + + and al,(NOT 002h) + out dx,al + + pop ax + pop dx +ENDM + +SPKR_TOGGLE MACRO ;debugging macro + + push dx + push ax + + mov dx,061h + in al,dx + + xor al,002h + out dx,al + + pop ax + pop dx +ENDM + +;------------------------------------------------------------------------- +; Command buffer equates +; +; WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING +; Any modifications to this structure MUST be +; reflected in L4SERIAL.hpp!! +; +; BE ESPECIALLY CAREFUL IF 'BUFSIZE' IS CHANGED! +; +; WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING +;------------------------------------------------------------------------- +SERIALBUFSIZE EQU 1024 ;buffer size (must be power of 2) + +SERIALBUF STRUC + head dw 0 + tail dw 0 + count dw 0 + + data db SERIALBUFSIZE dup (?) +SERIALBUF ENDS + +;------------------------------------------------ +; SERBUFINIT macro +; Initializes SERIALBUF structure +;------------------------------------------------ +; Enter: +; esi = pointer to object containing SERIALBUF +; name = offset to SERIALBUF within object +;------------------------------------------------ +; Side effects: +; (none) +;------------------------------------------------ +SERBUFINIT MACRO name ;enter with object pointer in esi + + add esi,name ;;build SERIALBUF pointer in esi + + mov head[esi],0 + mov tail[esi],0 + mov count[esi],0 + + sub esi,name ;;restore esi +ENDM + +;------------------------------------------------ +; SERBUFPUT_AL macro +; Puts character in AL into SERIALBUF +;------------------------------------------------ +; Enter: +; esi = pointer to object containing SERIALBUF +; name = offset to SERIALBUF within object +;------------------------------------------------ +; Side effects: +; ebx modified +;------------------------------------------------ +SERBUFPUT_AL MACRO name + + add esi,name ;;build SERIALBUF pointer in esi + + xor ebx,ebx ;;get 'head' offset in ebx + mov bx,head[esi] + add esi,ebx ;;add to base + mov data[esi],al ;;write the data + sub esi,ebx ;;restore SERIALBUF pointer + + inc bx ;;bump 'head' + and bx,SERIALBUFSIZE-1 ;;limit it + mov head[esi],bx ;;save the new 'head' offset + + inc count[esi] ;;update the character count + + sub esi,name ;;restore esi +ENDM + +;------------------------------------------------ +; SERBUFGET_AL macro +; Gets character into AL from SERIALBUF +;------------------------------------------------ +; Enter: +; esi = pointer to object containing SERIALBUF +; name = offset to SERIALBUF within object +;------------------------------------------------ +; Side effects: +; ebx modified +;------------------------------------------------ +SERBUFGET_AL MACRO name + + add esi,name ;;build SERIALBUF pointer in ecx + + xor ebx,ebx ;;get 'tail' offset in ebx + mov bx,tail[esi] + + add esi,ebx ;;add to base + mov al,data[esi] ;;read the data + sub esi,ebx ;;restore SERIALBUF pointer + + inc bx ;;bump 'tail' + and bx,SERIALBUFSIZE-1 ;;limit it + mov tail[esi],bx ;;save the new 'tail' offset + + dec count[esi] ;;update the character count + + sub esi,name ;;restore esi +ENDM + +;------------------------------------------------ +; SERBUFSPACE_IN macro +; Returns input bytes available in SERIALBUF +;------------------------------------------------ +; Enter: +; esi = pointer to object containing SERIALBUF +; name = offset to SERIALBUF within object +; reg = register to use +;------------------------------------------------ +; Side effects: +; ax contains number of bytes available +;------------------------------------------------ +SERBUFSPACE_IN MACRO name,reg + + add esi,name ;;build SERIALBUF pointer in ecx + mov reg,SERIALBUFSIZE + sub reg,count[esi] + sub esi,name ;;restore esi +ENDM + +;------------------------------------------------ +; SERBUFSPACE_OUT macro +; Returns output bytes available in SERIALBUF +;------------------------------------------------ +; Enter: +; esi = pointer to object containing SERIALBUF +; name = offset to SERIALBUF within object +;------------------------------------------------ +; Side effects: +; ax contains number of bytes available +;------------------------------------------------ +SERBUFSPACE_OUT MACRO name + + add esi,name ;;build SERIALBUF pointer in ecx + mov ax,count[esi] + sub esi,name ;;restore esi +ENDM + +;------------------------------------------------------------------------- +; IRQ data equates +;------------------------------------------------------------------------- + +IRQDATA STRUC + irqHandler dd ? + irqThis dd ? + + irqOldOffset dd ? ;THE ORDER OF THESE TWO IS CRITICAL. + irqOldSelector dw ? ;See the interrupt handlers near the end. + + irqPort dw ? + + irqNum db ? + irqPICbit db ? + irqOldPICbits db ? + irqPadByte db ? +IRQDATA ENDS +;------------------------------------------------------------------------- +; PCSERIAL object equates +; +; WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING +; Any modifications to this structure MUST be +; reflected in PCSERIAL.hpp!! +; WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING +;------------------------------------------------------------------------- + +; +; Lower eight bits reserved for UART status +; +ERR_INIT EQU 0000000100000000b + +PCSERIAL STRUC + portBase dw ? ;base port address + ErrorValue dw ? + enabled db ? ;set if rx/tx enabled + txFlow db ? + flowOverride db ? + intDataPtr dd ? ;pointer to IRQDATA structure + + txBuf SERIALBUF <> + rxBuf SERIALBUF <> +PCSERIAL ENDS + +;=========================================================================== +; Data segment +;=========================================================================== +BEGIN_DATA + +data_selector dw ? +irq_com1 IRQDATA +irq_com2 IRQDATA +irq_com3 IRQDATA +irq_com4 IRQDATA + + public uartLSR,uartIER,uartIIR +uartLSR db 0 +uartIER db 0 +uartIIR db 0 + +END_DATA +;=========================================================================== +; Code segment +;=========================================================================== +BEGIN_CODE + +;------------------------------------------------------------------------- +; PCSerialInit() +; Constructor for serial driver interface +;------------------------------------------------------------------------- +; Enter: +; init_this = pointer to object +; init_rate = data rate +; init_format = data format +; init_port = address of serial port +; init_irq_num = interrupt number +;------------------------------------------------------------------------- +; Returns: +; (nothing) +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialInit + + ARG_DPTR init_this + ARG_WORD init_rate + ARG_WORD init_format + ARG_WORD init_port + ARG_WORD init_irq_num + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Save off the data selector so we can get it back later. + ;-------------------------------------------------------------- + ; ...In flat mode, CS and DS overlap, but CS is write-protected + ; and DS isn't. Therefore we can write DS to [data_selector] + ; and read it back from CS later. + ;-------------------------------------------------------------- + mov [data_selector],ds + ;-------------------------------------------------------------- + ; Disable interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + ;-------------------------------------------------------------- + ; Point ESI at object data + ;-------------------------------------------------------------- + mov esi,init_this + ;-------------------------------------------------------------- + ; Clear the data buffers + ;-------------------------------------------------------------- + SERBUFINIT rxBuf ;assumes esi points to object + SERBUFINIT txBuf ;assumes esi points to object + ;-------------------------------------------------------------- + ; Initialize values + ;-------------------------------------------------------------- + xor eax,eax + mov enabled[esi],al ;clear 'enabled' flag + mov ErrorValue[esi],ax ;clear errors + mov txFlow[esi],al ;flow control off + mov flowOverride[esi],al ;...use flow control + mov intDataPtr[esi],eax ;(flag as not allocated) + + mov ax,init_port ;get the port address + mov portBase[esi],ax ;save it + ;-------------------------------------------------------------- + ; Find unused IRQDATA structure + ;-------------------------------------------------------------- + mov ecx,4 + mov edi,OFFSET irq_com1 +searchLoop: + mov ax,irqPort[edi] ;is irqPort equal to zero? + je short searchDone ;yes, use this structure + add edi,SIZE IRQDATA ;no, move to next one + loop searchLoop + + mov ErrorValue[esi],ERR_INIT ;allocation failed, set errors! + jmp allocFailed + +searchDone: + mov ax,init_port ;save port address + mov irqPort[edi],ax + + mov ax,init_irq_num ;save interrupt number + mov irqNum[edi],al + ;-------------------------------------------------------------- + ; Save init_this in irq structure, irqPtr in "this" structure + ;-------------------------------------------------------------- + mov irqThis[edi],esi + mov intDataPtr[esi],edi + ;-------------------------------------------------------------- + ; Save the old PROTECTED MODE interrupt vector + ;-------------------------------------------------------------- + mov bl,irqNum[edi] ;bl has interrupt number + DPMI_GET_PROT_VECTOR ;returns cx:edx + mov irqOldSelector[edi],cx + mov irqOldOffset[edi],edx + ;-------------------------------------------------------------- + ; Set the new PROTECTED MODE interrupt vector + ;-------------------------------------------------------------- + mov bx,init_irq_num ;bl has interrupt number + mov cx,cs ;cx:edx has selector:offset + mov edx,irqHandler[edi] + DPMI_SET_PROT_VECTOR + jnc short allocOk ;carry clear, allocation succeeded + + mov ErrorValue[esi],ERR_INIT ;allocation failed, set errors! + jmp allocFailed +allocOk: + ;-------------------------------------------------------------- + ; Set baud rate + ;-------------------------------------------------------------- + mov dx,init_port ;get port address from stack + mov cx,init_rate ;set data rate + SETBAUD_CX ;macro from PCSERIAL.INC + ;-------------------------------------------------------------- + ; Set data format + ;-------------------------------------------------------------- + mov ax,init_format + SETFORMAT_AL +;##################################################################################### +IF THE_WAY_IT_WAS + ;-------------------------------------------------------------- + ; Clear interrupt sources, initialize flow control + ;-------------------------------------------------------------- + in al,dx ;read input, clear input irq + + add dx,UART_IIR ;point to interrupt ident reg + in al,dx ;read IIR to clear tx interrupt + in al,dx + in al,dx + sub dx,UART_IIR ;restore dx + + add dx,UART_MSR ;point to MSR + in al,dx ;read modem status reg to clear IRQ + sub dx,UART_MSR ;restore dx + + and al,UART_MSR_CTS ;save flow control bit (cts) + mov txFlow[esi],al + ;-------------------------------------------------------------- + ; Enable interrupts in PIC + ;-------------------------------------------------------------- + PIC_IMR_TO_AL ;save old PIC bits for termination test + mov irqOldPICbits[edi],al + + mov ax,init_irq_num ;get interrupt number + cmp ax,0000Ch ;COM1? + jnz short mustBeCom2 ;no, must be COM2 + mov bl,PIC_COM1COM3 ;yes, get COM1, COM3 enable + jmp short hasPicBits +mustBeCom2: + mov bl,PIC_COM2COM4 ;get COM2, COM4 enable +hasPicBits: + mov irqPICbit[edi],bl ;save for termination + ASSERT_PIC_REG bl + ;-------------------------------------------------------------- + ; Enable UART interrupts, RTS, and DTR + ;-------------------------------------------------------------- + ASSERT_IER UART_IER_RDR+UART_IER_THR+UART_IER_LSR+UART_IER_MSR + ASSERT_MCR UART_MCR_IRQ+UART_MCR_RTS+UART_MCR_DTR +;##################################################################################### +else + ;-------------------------------------------------------------- + ; Initialize PIC + ;-------------------------------------------------------------- + ;----------------------------- + ; Get master PIC data: + ; enable bit in bl, + ; interrupt number in bh + ;----------------------------- + mov ax,init_irq_num ;get interrupt number + cmp ax,0000Ch ;COM1? + jnz short mustBeCom2 ;no, must be COM2 + + mov bl,PIC_COM1COM3 ;yes, get COM1, COM3 enable... + mov bh,OCW2_SPEC_EOI+4 ;...and PIC specific EOI + jmp short hasPicBits + +mustBeCom2: + mov bl,PIC_COM2COM4 ;get COM2, COM4 enable... + mov bh,OCW2_SPEC_EOI+3 ;...and PIC specific EOI +hasPicBits: + mov irqPICbit[edi],bl ;save for termination + ;----------------------------- + ; Enable interrupts in PIC + ;----------------------------- + ASSERT_PIC_REG bl + ;----------------------------- + ; Make sure PIC interrupt + ; request is cleared + ;----------------------------- + mov al,bh ;output the specific EOI + out PIC_MASTER_0,al + ;-------------------------------------------------------------- + ; Initialize UART + ;-------------------------------------------------------------- + mov dx,init_port ;get port address from stack + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ; Diagnostics values + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + add dx,UART_IIR + in al,dx + mov uartIIR,al + sub dx,UART_IIR + ;----------------------------- + ; Disable UART interrupts + ;----------------------------- + RETRACT_MCR UART_MCR_IRQ ;This clears irq into PIC + ;----------------------------- + ; Disable all UART interrupt + ; sources. Not mandatory, + ; but a safe practice. + ;----------------------------- + RETRACT_IER UART_IER_ALL + ;----------------------------- + ; Enable UART interrupt sources + ;----------------------------- + ASSERT_IER UART_IER_ALL + ;----------------------------- + ; Enable UART interrupts, RTS + ;----------------------------- + ASSERT_MCR UART_MCR_IRQ+UART_MCR_RTS+UART_MCR_DTR + ;----------------------------- + ; Clear UART interrupt sources + ;----------------------------- + in al,dx ;clear receiver interrupt (read inputs) + in al,dx + + add dx,UART_MSR ;read modem status reg to clear IRQ + in al,dx ;discard the result + sub dx,UART_MSR + + add dx,UART_LSR ;read line status reg to clear IRQ + in al,dx ;read value + mov uartLSR,al ;(save for diagnostics) + sub dx,UART_LSR + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ; Diagnostics values + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + add dx,UART_IER + in al,dx + mov uartIER,al + sub dx,UART_IER +;##################################################################################### +endif + ;-------------------------------------------------------------- + ; Mark as 'enabled' + ;-------------------------------------------------------------- + mov enabled[esi],1 + +allocFailed: + ;-------------------------------------------------------------- + ; Reenable the old interrupt state and return + ;-------------------------------------------------------------- + DPMI_RESTORE_PREV_INT ;pops ax! +END_C_PROC + + +;------------------------------------------------------------------------- +; PCSerialTerm() +; Destructor for serial packet interface +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int zero if ok +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialTerm + + ARG_DPTR term_this + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Disable interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,term_this + mov eax,esi ;is it NULL? + or eax,eax + jz short skipError1 ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Turn off RTS, DTR, and interrupts + ;-------------------------------------------------------------- + mov dx,portBase[esi] + RETRACT_MCR UART_MCR_IRQ+UART_MCR_RTS+UART_MCR_DTR + + ; NOTE: from this point on, interrupts CANNOT occur from the UART. + + ;-------------------------------------------------------------- + ; If improperly allocated, skip 'release' + ;-------------------------------------------------------------- + mov eax,intDataPtr[esi] ;get pointer to IRQ data + or eax,eax + jz short skipError2 ;null pointer, skip release + + mov edi,eax ;place pointer in edi + ;-------------------------------------------------------------- + ; Mark IRQDATA record as unused + ;-------------------------------------------------------------- + mov irqPort[edi],0 + ;-------------------------------------------------------------- + ; Restore the old PROTECTED MODE interrupt vector + ;-------------------------------------------------------------- + mov bl,irqNum[edi] ;bl has interrupt number + mov cx,irqOldSelector[edi] ;cx:edx has selector:offset + mov edx,irqOldOffset[edi] + DPMI_SET_PROT_VECTOR + ;-------------------------------------------------------------- + ; Disable PIC channel + ;-------------------------------------------------------------- + mov bl,irqPICbit[edi] ;get our PIC bit + +;; mov al,irqOldPICbits[edi] ;get old PIC bits +;; not al ;invert (zero=on) +;; and al,bl ;was it enabled before we got to it? +;; jnz skipRetract ;yes, leave it enabled + + RETRACT_PIC bl ;no, turn it off + +skipRetract: + + xor eax,eax + jmp short skipRestore +skipError1: + mov eax,1 + jmp short skipRestore +skipError2: + mov eax,2 +skipRestore: + ;-------------------------------------------------------------- + ; Reenable the old interrupt state and return + ;-------------------------------------------------------------- + DPMI_RESTORE_PREV_INT ;pops ax! + + + ;;this routine does not properly return status yet + +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialReceive() +; Returns characters if available +;------------------------------------------------------------------------- +; Enter: +; rp_this = pointer to object +; Byte *destPtr = pointer to 128-byte destination buffer +; max_characters = size of destination buffer +;------------------------------------------------------------------------- +; Returns: +; int number of characters +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialReceive + + ARG_DPTR rp_this + ARG_DPTR rp_dest + ARG_DWORD rp_maximum + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,rp_this + mov eax,esi ;is it NULL? + or eax,eax + jz short spr_done ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Skip if disabled + ;-------------------------------------------------------------- + cmp enabled[esi],0 ;if disabled, don't even try + jne short recvOK + + xor eax,eax + jmp short spr_done +recvOK: + ;-------------------------------------------------------------- + ; Check character count + ;-------------------------------------------------------------- + xor edx,edx ;clear top of edx + mov dx,rxBuf.count[esi] ;get # of characters in dx + or dx,dx ;empty? + jz short spr_done ;yes, return zero + ;-------------------------------------------------------------- + ; Limit to maximum + ;-------------------------------------------------------------- + mov ecx,rp_maximum ;get the maximum + cmp edx,ecx ;total > max? + jle short recvNoLimit ;no, use total + mov edx,ecx ;yes, limit to maximum +recvNoLimit: +;;; ;-------------------------------------------------------------- +;;; ; Disable interrupts +;;; ;-------------------------------------------------------------- +;;; DPMI_DISABLE_INT + ;-------------------------------------------------------------- + ; Transfer data from buffer + ;-------------------------------------------------------------- + mov ecx,edx ;place count in ecx + mov edi,rp_dest ;get pointer to destination + cld ;make sure direction is ok +spr_loop: + SERBUFGET_AL rxBuf ;get character into al + stosb ;save it + loop spr_loop +;;; ;-------------------------------------------------------------- +;;; ; Reenable the old interrupt state +;;; ;-------------------------------------------------------------- +;;; DPMI_RESTORE_PREV_INT ;pops ax! + +spr_done: + mov eax,edx ;place count in eax + ;-------------------------------------------------------------- + ; Return count in eax + ;-------------------------------------------------------------- +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialFlowControl() +; Turns transmit fow control on or off +;------------------------------------------------------------------------- +; Enter: +; sp_this = pointer to object +; int count = non-zero = on +;------------------------------------------------------------------------- +; Returns: +; void +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialFlowControl + + ARG_DPTR sf_this + ARG_DWORD sf_enable + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,sf_this + mov eax,esi ;is it NULL? + or eax,eax + jz short sfDone ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; If enabled, turn it on: else, turn it off + ;-------------------------------------------------------------- + cmp sf_enable,0 + je short sfOff + + mov flowOverride[esi],0 ;turn it on (disable override) + jmp short sfDone +sfOff: + mov flowOverride[esi],1 ;turn it off (enable override) +sfDone: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialSend() +; Transmits serial buffer +;------------------------------------------------------------------------- +; Enter: +; sp_this = pointer to object +; Byte *sp_src = pointer to source buffer +; int count = number of bytes to send +;------------------------------------------------------------------------- +; Returns: +; void +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialSend + + ARG_DPTR sp_this + ARG_DPTR sp_src + ARG_DWORD sp_count + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,sp_this + mov eax,esi ;is it NULL? + or eax,eax + jz short sendSkip ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Wait for sufficient room + ;-------------------------------------------------------------- + cmp enabled[esi],0 ;if disabled, don't even try + je short sendSkip + + mov ecx,sp_count ;get request count + cmp ecx,SERIALBUFSIZE ;too big? + jge short sendSkip ;yes, don't even try! + +spt_wait: + SERBUFSPACE_IN txBuf,ax ;get buffer 'in' space + cmp ax,cx ;enough room? + jb short spt_wait ;no, hang out + ;-------------------------------------------------------------- + ; Disable interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + ;-------------------------------------------------------------- + ; Copy data into tx buffer + ;-------------------------------------------------------------- + mov edi,sp_src ;get pointer to source +spt_loop: + mov al,[edi] ;get the byte + inc edi ;increment the source pointer + SERBUFPUT_AL txBuf ;place it in the buffer + loop spt_loop + + mov dx,portBase[esi] ;set dx to port base address + call StartSending ;attempt to start tx interrupt + ;-------------------------------------------------------------- + ; Reenable the old interrupt state + ;-------------------------------------------------------------- + DPMI_RESTORE_PREV_INT ;pops ax! +sendSkip: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialActive() +; Returns transmitter 'active' state (=0 when all transmission is done). +;------------------------------------------------------------------------- +; Enter: +; pa_this = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int errors +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialActive + + ARG_DPTR pa_this + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,pa_this + mov eax,esi ;is it NULL? + or eax,eax + jz short actNULL ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Get 'active' status + ; + ; The LSR register has two bits reflecting the + ; transmitter state: + ; THR = transmit holding register (1=empty) + ; TSR = transmit serial register (1=empty) + ; + ; The transmission is completely finished when both of these + ; bits are high. + ;-------------------------------------------------------------- + xor eax,eax ;clear top of eax + + mov dx,portBase[esi] ;get the port base + add dx,UART_LSR ;get LSR + in al,dx + ;;sub dx,UART_LSR ;we usually subtract, no need here + + and al,UART_LSR_THR+UART_LSR_TSR ; remove all but THR,TSR + xor al,UART_LSR_THR+UART_LSR_TSR ; invert the bits +actNULL: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialErrors() +; Returns error bits: zero indicates no errors. +; The error code is cleared by this call as well. +;------------------------------------------------------------------------- +; Enter: +; pe_this = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int errors +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialErrors + + ARG_DPTR pe_this + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,pe_this + mov eax,esi ;is it NULL? + or eax,eax + jz short errNULL ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Get, clear error word + ;-------------------------------------------------------------- + mov ax,ErrorValue[esi] ;init error? + and ax,ERR_INIT + jnz short haveInitError ;yes, don't clear it + + xor ax,ax ;no, go ahead and clear it + xchg ax,ErrorValue[esi] +haveInitError: + and eax,0FFFFh ;make sure top of eax is clear +errNULL: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialTestInstance() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int True +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialTestInstance + mov eax,1 + ret +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialIsSignatureBad() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int False +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialIsSignatureBad + mov eax,0 + ret +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialReceiveCount() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int number of items in receive queue +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialReceiveCount + + ARG_DPTR prc_this + BUILD_STACK_FRAME + + mov esi,prc_this + xor eax,eax + mov ax,rxBuf.count[esi] +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialTransmitCount() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int number of items in transmit queue +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialTransmitCount + + ARG_DPTR ptc_this + BUILD_STACK_FRAME + + mov esi,ptc_this + xor eax,eax + mov ax,txBuf.count[esi] +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialSetRate(Word baud) +; Set new data rate for serial object +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +; baud = new data rate +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialSetRate + + ARG_DPTR ssr_this + ARG_WORD ssr_rate + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,ssr_this + ;-------------------------------------------------------------- + ; Set baud rate + ;-------------------------------------------------------------- + mov dx,portBase[esi] ;get port base address + mov cx,ssr_rate ;get data rate from stack + SETBAUD_CX ;macro from PCSERIAL.INC +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialSetDataFormat(Word dataFormat) +; Set new data format for serial object +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +; baud = new data format +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialSetDataFormat + + ARG_DPTR sdf_this + ARG_WORD sdf_format + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,sdf_this + ;-------------------------------------------------------------- + ; Set data format + ;-------------------------------------------------------------- + mov dx,portBase[esi] ;get port base address + mov ax,sdf_format + SETFORMAT_AL +END_C_PROC + +;------------------------------------------------------------------------- +; PCSerialLineStatus() +; Return state of line status register +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int line status +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSerialModemStatus + + ARG_DPTR sls_this + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,sls_this + ;-------------------------------------------------------------- + ; Get LSR data + ;-------------------------------------------------------------- + xor eax,eax ;clear returned value + + mov dx,portBase[esi] ;get port base address + add dx,UART_MSR + in al,dx +END_C_PROC + +;------------------------------------------------------------------------- +; StartSending - attempt to start transmitter (if allowed) +; ...called from the receive interrupt routine and PCSerialSend. +;------------------------------------------------------------------------- +; Enter: +; ESI = pointer to PCSERIAL structure +; DX = UART base address +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +; Side effects: +; Modifies al, bx +;------------------------------------------------------------------------- +StartSending PROC NOLANGUAGE NEAR + + add dx,UART_LSR ;get THR bit from LSR + in al,dx + sub dx,UART_LSR + + test al,UART_LSR_THR ;is there anything in the holding reg? + jz sptNoKick ;yes, interrupt will occur later + + cmp flowOverride[esi],0 ;use flow control? + jne sptNow ;no, just do it + cmp txFlow[esi],0 ;if flow control off, don't start! + je short sptNoKick +sptNow: + SERBUFGET_AL txBuf ;get a character from the buffer + out dx,al ;send it + +sptNoKick: + ret +StartSending ENDP + +;------------------------------------------------------------------------- +; Interrupt handlers +;------------------------------------------------------------------------- +IntHandler PROC NOLANGUAGE NEAR + ASSUME cs:_TEXT + +IntCom1: + pushad + mov edi,OFFSET irq_com1 ;point EDI at IRQDATA structure + call IntMain + popad + iret +;;; jmp cs:fword ptr [irq_com1.irqOldOffset] +IntCom2: + pushad + mov edi,OFFSET irq_com2 ;point EDI at IRQDATA structure + call IntMain + popad + iret +;;; jmp cs:fword ptr [irq_com2.irqOldOffset] +IntCom3: + pushad + mov edi,OFFSET irq_com3 ;point EDI at IRQDATA structure + call IntMain + popad + iret +;;; jmp cs:fword ptr [irq_com3.irqOldOffset] +IntCom4: + pushad + mov edi,OFFSET irq_com4 ;point EDI at IRQDATA structure + call IntMain + popad + iret +;;; jmp cs:fword ptr [irq_com4.irqOldOffset] + + ;-------------------------------------------------------------- + ; Serial interrupt handler main body + ;-------------------------------------------------------------- +IntMain: + push ds ;save registers + push es + mov ds,cs:[data_selector] ;get our DS + ASSUME ds:_DATA + +;;; SPKR_SET ;********************************************* + + ;-------------------------------------------------------------- + ; Get pointer to PCSERIAL structure, UART base address + ;-------------------------------------------------------------- + mov esi,irqThis[edi] + mov dx,irqPort[edi] + ;-------------------------------------------------------------- + ; Process all pending operations + ;-------------------------------------------------------------- +procLoop: + add dx,UART_IIR ;point to interrupt ident reg + in al,dx ;get interrupt source ID + sub dx,UART_IIR ;restore dx + + cmp al,001h ;if LSB is set, no interrupt + je procDone + ;-------------------------------------------------------------- + ; Receive character + ;-------------------------------------------------------------- + cmp al,UART_IIR_RDR ;receiver ready? + jne short procNoRx ;no, skip it + + in al,dx ;get character + SERBUFPUT_AL rxBuf ;save command character in buffer + jmp short procLoop +procNoRx: + ;-------------------------------------------------------------- + ; Send character + ;-------------------------------------------------------------- + cmp al,UART_IIR_THR ;transmitter ready? + jne short procNoTx ;no, skip it + + cmp txBuf.count[esi],0 ;any data to send? + je short procTxOff ;no, skip it + + cmp flowOverride[esi],0 ;use flow control? + jne procNow ;no, just do it + cmp txFlow[esi],0 ;flow enabled? + je short procTxOff ;no, skip it +procNow: + SERBUFGET_AL txBuf ;get a character from the buffer + out dx,al ;send it + jmp short procLoop + ;------------------------------ + ; Couldn't send, just exit + ;------------------------------ +procTxOff: + jmp procLoop + +procNoTx: + ;-------------------------------------------------------------- + ; Process modem status register change + ;-------------------------------------------------------------- + cmp al,UART_IIR_MSR ;MSR change? + jne short procNoMSR ;no, skip it + + add dx,UART_MSR ;read modem status reg to clear IRQ + in al,dx + sub dx,UART_MSR + + test al,UART_MSR_DCTS ;CTS changed? + jz short procNoDCTS + + test al,UART_MSR_CTS ;CTS active? + jz short procCTSoff + ;------------------------------ + ; Turn flow control on + ;------------------------------ + mov txFlow[esi],1 + + add dx,UART_LSR ;get THR bit from LSR + in al,dx + sub dx,UART_LSR + + test al,UART_LSR_THR ;is there anything in the holding reg? + jz procNoDCTS ;yes, must be active + + cmp txBuf.count[esi],0 ;any data to send? + je short procNoDCTS ;no, skip it + call StartSending ;yes, restart sending + jmp short procNoDCTS +procCTSoff: + ;------------------------------ + ; Turn flow control off + ;------------------------------ + mov txFlow[esi],0 +procNoDCTS: + jmp procLoop +procNoMSR: + ;-------------------------------------------------------------- + ; Process line status register change (error or break) + ;-------------------------------------------------------------- + ;MUST BE LSR CHANGE. No need to check IIR. + +;; cmp al,UART_IIR_LSR ;LSR change? +;; jne short procNoLSR ;no, skip it + + add dx,UART_LSR ;read line status reg to clear IRQ + in al,dx ;read value + sub dx,UART_LSR + + and ax,UART_LSR_ERRS ;remove non-error bits + or ErrorValue[esi],ax ;OR with current error state + jmp procLoop +procDone: + ;-------------------------------------------------------------- + ; PIC port write + ; (allows future interrupts to occur) + ;-------------------------------------------------------------- + PIC_RESET_MASTER + ;-------------------------------------------------------------- + ; Restore registers, return from SUBROUTINE (not interrupt!) + ;-------------------------------------------------------------- +;;; SPKR_RESET ;********************************************* + + pop es + pop ds + ret + +IntHandler ENDP + +END_CODE + + END + + diff --git a/CODE/RP/MUNGA_L4/L4SERIAL.HPP b/CODE/RP/MUNGA_L4/L4SERIAL.HPP new file mode 100644 index 0000000..fb78fe5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4SERIAL.HPP @@ -0,0 +1,260 @@ +//===========================================================================// +// File: L4Serial.hh // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC serial interface class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/04/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(L4SERIAL_HPP) + +# define L4SERIAL_HPP + +# if !defined(STYLE_HPP) +# include +# endif + + // WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING + // Do NOT change ANY of the following lines without making + // corresponding changes in PCSerial.asm! PCSerial.hh exists + // ONLY to inform C++ compilers of the data and structures + // used by PCSerial.asm! + // WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING + + // These are purposely grouped as two parameters in one equate. + // The standard PC COM ports ALWAYS use these combinations. + #define PCS_COM1 0x3F8,0x0C // portAddress,interruptNumber + #define PCS_COM2 0x2F8,0x0B + #define PCS_COM3 0x3E8,0X0C + #define PCS_COM4 0x2E8,0x0B + + // Data rates + #define PCS_300 0x0180 // 300 Baud + #define PCS_1200 0x0060 // 1200 Baud + #define PCS_2400 0x0030 // 2400 Baud + #define PCS_9600 0x000C // 9600 Baud + #define PCS_19P2 0x0006 // 19200 Baud + #define PCS_38P4 0x0003 // 38400 Baud + #define PCS_115K 0x0001 // 115,200 Baud (not supported on all PC's) + + // Data formats + #define PCS5D 0x0000 // 5 data bits + #define PCS6D 0x0001 // 6 data bits + #define PCS7D 0x0002 // 7 data bits + #define PCS8D 0x0003 // 8 data bits + + #define PCS1S 0x0000 // one stop bit + #define PCS2S 0x0004 // two stop bits + + #define PCSNP 0x0000 // no parity + #define PCSOP 0x0008 // odd parity + #define PCSEP 0x0018 // even parity + #define PCSMP 0x0028 // mark parity (untested) + #define PCSSP 0x0038 // space parity (untested) + + // some popular combinations- + #define PCS_N81 (PCS8D|PCS1S|PCSNP) // no parity, 8 data, 1 stop + #define PCS_E81 (PCS8D|PCS1S|PCSEP) // even parity, 8 data, 1 stop + #define PCS_O81 (PCS8D|PCS1S|PCSOP) // odd parity, 8 data, 1 stop + + // Flow control +// #define PCS_NOFLOWCTRL 0x0000 // no flow control + + // error bits returned by PC_Serial::Errors() + #define PCS_ERR_OVERRUN 0x0002 + #define PCS_ERR_PARITY 0x0004 + #define PCS_ERR_FRAMING 0x0008 + #define PCS_ERR_BREAK 0x0010 + #define PCS_ERR_ALLOC 0x0100 // failed at slot allocation + #define PCS_ERR_INIT 0x0200 // failed DPMI initialization + #define PCS_ERR_TXOVER 0x0400 // overran transmit buffer + #define PCS_ERR_RXOVER 0x0500 // overran receive buffer + + // bits returned by PC_Serial::ModemStatus() + + // (1st four bits not defined yet, but non-zero) + #define PCS_MS_CTS 0x0010 + #define PCS_MS_DSR 0x0020 + #define PCS_MS_RI 0x0040 + #define PCS_MS_DCD 0x0080 + + + class PCSerial; + + extern "C" void + PCSerialInit( + PCSerial *pc_serial, + Word data_rate, + Word data_format, + Word port, + Word irq_num + ); + + extern "C" int + PCSerialTerm( + PCSerial *pc_serial + ); + + extern "C" int + PCSerialReceive( + PCSerial *pc_serial, + char *destination, + int destination_length + ); + + extern "C" void + PCSerialSend( + PCSerial *pc_serial, + char *source, + int source_length + ); + + extern "C" int + PCSerialErrors( + PCSerial *pc_serial + ); + + extern "C" int + PCSerialActive( + PCSerial *pc_serial + ); + + extern "C" int + PCSerialTestInstance( + PCSerial *pc_serial + ); + + extern "C" int + PCSerialIsSignatureBad( + const volatile PCSerial *pc_serial + ); + + extern "C" int + PCSerialReceiveCount( + PCSerial *pc_serial + ); + + extern "C" int + PCSerialTransmitCount( + PCSerial *pc_serial + ); + + extern "C" void + PCSerialSetRate( + PCSerial *pc_serial, + Word rate + ); + + extern "C" void + PCSerialSetDataFormat( + PCSerial *pc_serial, + Word format + ); + + extern "C" void + PCSerialFlowControl( + PCSerial *pc_serial, + int enable + ); + + extern "C" int + PCSerialModemStatus( + PCSerial *pc_serial + ); + + class PCSerial + { + + public: + PCSerial(Word rate, Word format, Word port, Word int_num) + { PCSerialInit(this, rate, format, port, int_num); } + + ~PCSerial() + { + if (this == NULL) + { + cout << "~PCSerial has been passed a NULL pointer\n"; + } + else + { + PCSerialTerm(this); + } + } + + Logical + TestInstance() + { return PCSerialTestInstance(this); } + + int + ReceiveString(char *destPtr, int maxLen) // returns length + { return PCSerialReceive(this, destPtr, maxLen); } + + void + FlowControlEnable(Logical onOff) + { PCSerialFlowControl(this, (int) onOff); } + + void + SendString(char *srcPtr, int length) + { PCSerialSend(this, srcPtr, length); } + + // error bits returned by PCSerial::Errors() + enum ErrorBits { + overrunError=0x0002, + parityError=0x0004, + framingError=0x0008, + breakDetect=0x0010, + initError=0x0100 + }; + + int + ReceiveCharCount() + { return PCSerialReceiveCount(this); } + + int + TransmitCharCount() + { return PCSerialTransmitCount(this); } + + int + Errors() // returns error value, clears it + { return PCSerialErrors(this); } + + int + IsActive() + { return PCSerialActive(this); } + + int + ModemStatus() + { return PCSerialModemStatus(this); } + +# if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile PCSerial *ptr) + { return PCSerialIsSignatureBad(ptr); } +# endif + +// protected: + + Word portBase; + Word errorValue; + Byte enabled; + Byte txFlow; + Byte flowOverride; + LWord intDataPtr; + LWord hackCount; + + // This is for INTERNAL USE only (reflects structure in .ASM file) + struct PCSerBuf + { + Word head, tail, count; + Byte data[1024]; + } + txBuf, rxBuf; + + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4SPLR.HPP b/CODE/RP/MUNGA_L4/L4SPLR.HPP new file mode 100644 index 0000000..03f91f2 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4SPLR.HPP @@ -0,0 +1,234 @@ +//===========================================================================// +// File: rp4lbe4.hh // +// Project: MUNGA Brick: Red Planet LBE Application // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4SPLR_HPP) +# define L4SPLR_HPP + +# if !defined(L4NET_HPP) +# include +# endif + +# if !defined(L4APP_HPP) +# include +# endif + +# if !defined(SPOOLER_HPP) +# include +# endif + +# if !defined(INTEREST_HPP) +# include +# endif + +# if !defined(APPTASK_HPP) +# include +# endif + + //########################################################################## + //#################### SpoolingInterestManager ######################### + //########################################################################## + + class SpoolingInterestManager: + public InterestManager + { + public: + SpoolingInterestManager(); + ~SpoolingInterestManager(); + + void + LoadInterestArenas(Mission *mission); + void + LoadMission(Mission *mission); + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + void + Shutdown(); + }; + + //########################################################################## + //################### L4SpoolingNetworkManager ######################### + //########################################################################## + + class L4SpoolingNetworkManager: + public L4NetworkManager + { + public: + L4SpoolingNetworkManager(); + ~L4SpoolingNetworkManager(); + + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + void + StartConnecting(Mission *mission); + }; + + //########################################################################## + //################### L4PlaybackNetworkManager ######################### + //########################################################################## + + class L4PlaybackNetworkManager: + public NetworkManager + { + public: + L4PlaybackNetworkManager(); + ~L4PlaybackNetworkManager(); + + void + StartConnecting(Mission *mission); + + Logical + Shutdown(); + + Logical + CheckBuffers(NetworkPacket*); + }; + + //########################################################################## + //################### L4SpoolingApplication ########################## + //########################################################################## + + class L4SpoolingApplication: + public L4Application + { + public: + L4SpoolingApplication( + ResourceFile *resource, + ApplicationID application_ID + ); + ~L4SpoolingApplication(); + + SpoolingInterestManager* + GetInterestManager() + { + return + (SpoolingInterestManager*)Application::GetInterestManager(); + } + + L4SpoolingNetworkManager* + GetNetworkManager() + { + return + (L4SpoolingNetworkManager*)Application::GetNetworkManager(); + } + + MissionReviewApplicationManager* + GetApplicationManager() + { + return + (MissionReviewApplicationManager*) + Application::GetApplicationManager(); + } + + protected: + Registry* + MakeRegistry(); + InterestManager* + MakeInterestManager(); + NetworkManager* + MakeNetworkManager(); + + Mission* + MakeMission( + NotationFile *notation_file, + ResourceFile *resources + ); + + VideoRenderer* + MakeVideoRenderer(); + AudioRenderer* + MakeAudioRenderer(); + GaugeRenderer* + MakeGaugeRenderer(); + + Entity* + MakeViewpointEntity(Entity__MakeMessage *); + + void + Initialize(); + void + LoadBackgroundTasks(); + Logical + Shutdown(); + + + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + + Logical + ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ); + void + ExecuteBackgroundTask(); + + protected: + Logical + missionSpooled; + + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + void + LoadMissionMessageHandler(Message *message); + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + void + AbortMissionMessageHandler(AbortMissionMessage *message); + + Logical + TestInstance() const; + }; + + extern L4SpoolingApplication * &l4_spooling_application; + + //########################################################################## + //######################## SpoolerTask ############################### + //########################################################################## + + class SpoolerTask: + public ApplicationTask + { + public: + SpoolerTask(); + ~SpoolerTask(); + + void + Execute(); + + virtual void + DispatchPacket(NetworkPacket *packet); + virtual long + GetTimeBias(); + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4SVGA16.ASM b/CODE/RP/MUNGA_L4/L4SVGA16.ASM new file mode 100644 index 0000000..94fd017 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4SVGA16.ASM @@ -0,0 +1,654 @@ +;=========================================================================== +; File: L4SVGA16.asm +; Project: MUNGA +; Contents: SVGA 16-bit buffered graphics operations +;--------------------------------------------------------------------------- +; Date Who Modification +; -------- --- ----------------------------------------------------------- +; 03/08/95 CPB Initial coding (started from VGAbuf8.asm) +;--------------------------------------------------------------------------- +; Copyright (C) 1995, Virtual World Entertainment, Inc. +; All Rights reserved worldwide +; This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL +;=========================================================================== + + include l4asm.inc + include pcdpmi.inc +;=========================================================================== +; Equates +;=========================================================================== + +;-------------------------------------------------------------- +; VGA CRTC registers (in color mode: monochrome is different!) +; monochrome is 3B4/3B5 respectively +;-------------------------------------------------------------- +CRTC_INDEX equ 03D4h +CRTC_DATA equ 03D5h + +CRTC_INDEX_HTOTAL equ 00h +CRTC_INDEX_HDISPENEND equ 01h +CRTC_INDEX_HBSTART equ 02h +CRTC_INDEX_HBEND equ 03h +CRTC_INDEX_HRSTART equ 04h +CRTC_INDEX_HREND equ 05h +CRTC_INDEX_VTOTAL equ 06h +CRTC_INDEX_OVERFLOW equ 07h +CRTC_INDEX_PRSCAN equ 08h +CRTC_INDEX_MAXSCAN equ 09h +CRTC_INDEX_CUR_START equ 0Ah +CRTC_INDEX_CUR_END equ 0Bh +CRTC_INDEX_STARTHIGH equ 0Ch +CRTC_INDEX_STARTLOW equ 0Dh +CRTC_INDEX_CURSORHIGH equ 0Eh +CRTC_INDEX_CURSORLOW equ 0Fh +CRTC_INDEX_VRSTART equ 10h +CRTC_INDEX_VREND equ 11h ;;bit 7=1 to write-protect 0..7 +CRTC_INDEX_VDENABEND equ 12h +CRTC_INDEX_OFFSET equ 13h +CRTC_INDEX_UNDERLINE equ 14h +CRTC_INDEX_VBSTART equ 15h +CRTC_INDEX_VBEND equ 16h +CRTC_INDEX_MODECTL equ 17h +CRTC_INDEX_LINECMP equ 18h + +;-------------------------------------------------------------- +; VGA sequencer registers +;-------------------------------------------------------------- +SRX equ 03C4h +SRDATA equ 03C5h + +SR0 equ 000h ;reset +SR1 equ 001h ;clocking mode +SR2 equ 002h ;plane mask +SR3 equ 003h ;character map select +SR4 equ 004h ;memory mode +;-------------------------------------------------------------- +; VGA graphics controller registers +;-------------------------------------------------------------- +GRX equ 03CEh +GRDATA equ 03CFh + +GR0 equ 000h ;set/reset +GR1 equ 001h ;set/reset enable +GR2 equ 002h ;color compare +GR3 equ 003h ;data rotate +GR4 equ 004h ;read map select +GR5 equ 005h ;mode +GR6 equ 006h ;miscellaneous +GR7 equ 007h ;color don't care +GR8 equ 008h ;bit mask +;-------------------------------------------------------------- +; VGA attribute controller registers +;-------------------------------------------------------------- +ARX equ 03C0h ;???? +ARDATA equ 03C1h + +PEL_WRITE_ADDR equ 03C8h ;write begins "write" operation +PEL_READ_ADDR equ 03C7h ;write begins "read" operation +PEL_STATE equ 03C7h ;read returns DAC state +PEL_DATA equ 03C9h + +;-------------------------------------------------------------- +; VWE LBE4 video splitter board addresses +;-------------------------------------------------------------- +VWE_HC_ON equ 031Ah ;write to this port turns on high-color divider +VWE_HC_OFF equ 0319h ;write to this port turns off high-color divider + +;-------------------------------------------------------------- +; Video buffer base address +;-------------------------------------------------------------- +VIDEO_BUFFER EQU 0000h +VIDEO_SEGMENT EQU 0A000h +BIOS_SEGMENT EQU 0C000h + +;=========================================================================== +; Macros +;=========================================================================== + +;=========================================================================== +; Structures +;=========================================================================== + +PixelMap STRUC + pmX dd ? + pmY dd ? + pmPtr dd ? +PixelMap ENDS + +BitMap STRUC + bmX dd ? + bmY dd ? + bmWords dd ? + bmPtr dd ? +BitMap ENDS + +;=========================================================================== +; Data segment +;=========================================================================== +BEGIN_DATA + + regs DPMIrealModeRegs <> + video_descriptor dw ? + + pageFunction dd ? ;THE ORDER OF THESE TWO IS CRITICAL! + BIOS_descriptor dw ? ;(they constitute a far pointer in 32-bits) + + bitMapFcn dd ? ;used by Buf16DrawBitMap + + tempColor db 256*3 dup () + +;; testWord dw 0 + + + badVideoActive db 0 ;flag indicating deliberately bad video is on + crtc_htotal db ? ;horizontal total + + +END_DATA + +;=========================================================================== +; Code segment +;=========================================================================== +BEGIN_CODE + +;------------------------------------------------------------------------- +; SVGASetMode() +; Set requested VESA display mode +;------------------------------------------------------------------------- +; Enter: +; LWord mode = requested display mode +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGASetMode + ARG_DWORD sm_mode + ARG_CPTR sm_ptr + + BUILD_STACK_FRAME + + mov eax,sm_ptr + mov pageFunction,eax + + mov eax,sm_mode + cmp eax,0100h + jae short smUseVESA + + ;-------------------------------------------------------------- + ; Prepare for BIOS call + ;-------------------------------------------------------------- + ;ah=00 for mode set, al=mode + mov regs.realEAX,eax + jmp short smGo + +smUseVESA: + ;-------------------------------------------------------------- + ; Prepare for VESA call + ;-------------------------------------------------------------- + mov ax,04F02h ;ah=4F for VESA, al=02 for set mode + mov regs.realEAX,eax + + mov eax,sm_mode ;bx = mode + mov regs.realEBX,eax + ;-------------------------------------- + ; Simulate real interrupt through DPMI + ;-------------------------------------- +smGo: + mov bx,010h ;bh=0, bl=interrupt number + xor cx,cx ;copy zero words from stack + + mov ax,ds ;es:edi points to regs + mov es,ax ;es:edi points to regs + mov edi,OFFSET regs + + DPMI_SIMULATE_REAL_INT + + ;-------------------------------------------------------------- + ; Generate descriptor for video buffer at segment A000 + ;-------------------------------------------------------------- + mov bx,VIDEO_SEGMENT ;segment to map + DPMI_MAP_SEG_TO_DESC + mov video_descriptor,ax + +END_C_PROC + +;------------------------------------------------------------------------- +; SVGAFunkyVideo() +; Deliberately create bad video sync +;------------------------------------------------------------------------- +; Enter: +; LWord mode = on/off (MUNGA "Logical") +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGAFunkyVideo + ARG_DWORD fv_mode + + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Enable writing to lowest seven CRTC registers + ;-------------------------------------------------------------- + mov dx,CRTC_INDEX ;point to vrend register + mov al,CRTC_INDEX_VREND + out dx,al + + mov dx,CRTC_DATA ;get the current setting + in al,dx + mov cl,al ;save in cl + + and al,07Fh ;turn off MSB (turns off write-protect) + out dx,al ;write it out + ;-------------------------------------------------------------- + ; Point to CRTC htotal register + ;-------------------------------------------------------------- + mov dx,CRTC_INDEX ;point to htotal register + mov al,CRTC_INDEX_HTOTAL + out dx,al + + mov dx,CRTC_DATA ;point dx at data port + ;-------------------------------------------------------------- + ; Set or restore? + ;-------------------------------------------------------------- + mov eax,fv_mode + or eax,eax + je short bvOff + + mov al,badVideoActive ;already in bad video? + or al,al + jnz bvExit ;yes, bail out + + mov badVideoActive,1 ;flag as 'bad' + ;-------------------------------------------------------------- + ; Read CRTC value, save it + ;-------------------------------------------------------------- + in al,dx ;get the current setting + mov crtc_htotal,al + ;-------------------------------------------------------------- + ; Set screwed up CRTC value + ;-------------------------------------------------------------- + sub al,9 ;generate funky htotal + out dx,al ;write it out + jmp short bvExit + ;-------------------------------------------------------------- + ; Restore proper CRTC value + ;-------------------------------------------------------------- +bvOff: + mov al,crtc_htotal + out dx,al + + mov badVideoActive,0 ;flag as 'good' +bvExit: + ;-------------------------------------------------------------- + ; Restore VREND register + ;-------------------------------------------------------------- + mov dx,CRTC_INDEX ;point to vrend register + mov al,CRTC_INDEX_VREND + out dx,al + + mov dx,CRTC_DATA + mov al,cl ;get the old value + out dx,al ;write it out + +END_C_PROC + +;------------------------------------------------------------------------- +; SVGASetSplitterClock() +; Turn on/off special VWE splitter clock divider +;------------------------------------------------------------------------- +; Enter: +; LWord state = requested clock mode (True:on, False:off) +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGASetSplitterClock + + ARG_DWORD state + + BUILD_STACK_FRAME + + mov eax,state + or eax,eax + jz short ssc_off + ;-------------------------------------------------------------- + ; Turn on special splitter card clock divider + ;-------------------------------------------------------------- + mov dx,VWE_HC_ON + jmp short ssc_write + ;-------------------------------------------------------------- + ; Turn off special splitter card clock divider + ;-------------------------------------------------------------- +ssc_off: + mov dx,VWE_HC_OFF +ssc_write: + out dx,al ;any value will do + +END_C_PROC + +;------------------------------------------------------------------------- +; SVGASetPage() +; Set SVGA display page +;------------------------------------------------------------------------- +; Enter: +; int page = requested SVGA page +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGASetPage + + ARG_DWORD sp_page + + BUILD_STACK_FRAME + + mov edx,sp_page + and edx,00FFh ;remove upper bits + + mov bx,0000h ;bh=set bank, bl=window # + mov ax,4F05h ;int 10h function 4F subfcn 05 + +;; cmp pageFunction,0 ;does the direct call exist? +;; je setBankIrq ;no, use interrupt + +;; call cs:fword ptr [pageFunction] ;THIS DOES NOT WORK, +;; jmp setBankRest ;I suspect we must use a DPMI call. + +;;setBankIrq: + mov ax,04F05h ;ah=4F for VESA, al=05 for set bank + mov regs.realEAX,eax + + xor eax,eax ;bh = subfunction, bl=window + mov regs.realEBX,eax + + mov regs.realEDX,edx ;dx = addr in granularity units + + mov bx,010h ;bh=0, bl=interrupt number + xor cx,cx ;copy zero words from stack + + mov ax,ds ;es:edi points to regs + mov es,ax + mov edi,OFFSET regs + + DPMI_SIMULATE_REAL_INT +END_C_PROC + +;------------------------------------------------------------------------- +; SVGATransfer32() +; Copy modified portions of buffer to SVGA display buffer +;------------------------------------------------------------------------- +; Enter: +; LWord offset = offset into display buffer +; Word *ptr = pointer to source pixels +; LWord bits = bits indicating which pixels to write +;------------------------------------------------------------------------- +; Returns: +; int number of bits transferred +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGATransfer32 + + ARG_DWORD t_dest_offset + ARG_DPTR t_source_ptr + ARG_DWORD t_bits + + BUILD_STACK_FRAME + ;----------------------------- + ; Get source ptr in ds:si + ;----------------------------- + mov esi,t_source_ptr + ;----------------------------- + ; Get dest ptr in es:di + ;----------------------------- + mov ax,video_descriptor ;es:di points to destination + mov es,ax + mov edi,t_dest_offset + ;----------------------------- + ; Clear bit count + ;----------------------------- + xor edx,edx + ;----------------------------- + ; Check 32 pixels + ;----------------------------- + mov ebx,t_bits ;bx has bits + mov ecx,32 + cld ;make sure esi, edi are INCREMENTED +tx_loop: + lodsw ;get source word + shl ebx,1 ;is bit set? + jnc tx_nope ;no, don't copy + ;----------------------------- + ; Bit set, copy the pixel + ;----------------------------- +;; mov ax,testWord +;; inc ax +;; mov testWord,ax + + stosw ;yes, copy + inc edx ;increment bit count + loop tx_loop + jmp short tx_done + ;----------------------------- + ; Bit clear, skip the pixel + ;----------------------------- +tx_nope: + add edi,2 + loop tx_loop +tx_done: + ;----------------------------- + ; All done, exit + ;----------------------------- + mov eax,edx ;return count in eax +END_C_PROC + +;------------------------------------------------------------------------- +; SVGATransfer32x() +; Copy LOWER BYTE of modified portions of buffer to SVGA display buffer +;------------------------------------------------------------------------- +; Enter: +; LWord offset = offset into display buffer +; Word *ptr = pointer to source pixels +; LWord bits = bits indicating which pixels to write +;------------------------------------------------------------------------- +; Returns: +; int number of bits transferred +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGATransfer32x + + ARG_DWORD t_dest_offsetx + ARG_DPTR t_source_ptrx + ARG_DWORD t_bitsx + + BUILD_STACK_FRAME + ;----------------------------- + ; Get source ptr in ds:si + ;----------------------------- + mov esi,t_source_ptrx + ;----------------------------- + ; Get dest ptr in es:di + ;----------------------------- + mov ax,video_descriptor ;es:di points to destination + mov es,ax + mov edi,t_dest_offsetx + ;----------------------------- + ; Clear bit count + ;----------------------------- + xor edx,edx + ;----------------------------- + ; Check 32 pixels + ;----------------------------- + mov ebx,t_bitsx ;bx has bits + mov ecx,32 + cld ;make sure esi, edi are INCREMENTED +tx_loopx: + lodsw ;get source word + shl ebx,1 ;is bit set? + jnc tx_nopex ;no, don't copy + ;----------------------------- + ; Bit set, copy the pixel + ;----------------------------- + stosb ;yes, copy LOWER BYTE + inc edx ;increment bit count + loop tx_loopx + jmp short tx_donex + ;----------------------------- + ; Bit clear, skip the pixel + ;----------------------------- +tx_nopex: + inc edi ;; LOWER BYTE ONLY + loop tx_loopx +tx_donex: + ;----------------------------- + ; All done, exit + ;----------------------------- + mov eax,edx ;return count in eax +END_C_PROC + +;------------------------------------------------------------------------- +; SVGAZeroPalette(port) +; Clear entire 256-color palette in hardware +; ASSUMES that the port is correct. +;------------------------------------------------------------------------- +; Enter: +; Word port = base port address +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGAZeroPalette + ARG_WORD zp_port + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Signal CLUT that color data will be written + ;-------------------------------------------------------------- + mov dx,zp_port ;get port base address + + xor al,al ;start with color zero + add dx,2 ;move to "write address" register + out dx,al ;set the address + ;-------------------------------------------------------------- + ; Write the color data + ;-------------------------------------------------------------- + inc dx ;move to "data" register + mov ecx,256*3 ;clear entire palette +zpLoop: + out dx,al + loop zpLoop +END_C_PROC + +;------------------------------------------------------------------------- +; SVGAWriteFullPalette(palette_ptr, port) +; Write entire 256-color palette to hardware +; ASSUMES that the palette pointer is correct. +; ASSUMES that the port is correct. +;------------------------------------------------------------------------- +; Enter: +; Palette8 *wp_source = pointer to FIRST COLOR TRIPLET +; Word port = base port address +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGAWriteFullPalette + ARG_DPTR wfp_source + ARG_WORD wfp_port + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Convert color bytes to 6-bit VGA palette values + ;-------------------------------------------------------------- + mov esi,wfp_source ;get pointer to FIRST TRIPLET + mov edi,offset tempColor + mov ecx,256*3 ;transfer entire palette + cld ;make sure the pointers INCREMENT! +wfpLoop: + lodsb ;get the byte + shr al,2 ;change to six bits + stosb ;save the shifted data + loop wfpLoop ;do 'em all + ;-------------------------------------------------------------- + ; Signal CLUT that color data will be written + ;-------------------------------------------------------------- + mov dx,wfp_port ;get port base address + + xor al,al ;start with color zero + add dx,2 ;move to "write address" register + out dx,al ;set the address + ;-------------------------------------------------------------- + ; Write the color data + ;-------------------------------------------------------------- + inc dx ;move to "data" register + + mov esi,offset tempColor ;point to shifted data + mov ecx,256*3 ;transfer entire palette + rep outsb +END_C_PROC + +;------------------------------------------------------------------------- +; SVGAReadFullPalette(palette_ptr, port) +; Read entire 256-color palette from hardware +; ASSUMES that the palette pointer is correct. +; ASSUMES that the port is correct. +;------------------------------------------------------------------------- +; Enter: +; Palette8 *rp_dest = pointer to FIRST COLOR TRIPLET +; Word port = base port address +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGAReadFullPalette + ARG_DPTR rfp_dest + ARG_WORD rfp_port + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Signal CLUT that color data will be read + ;-------------------------------------------------------------- + mov dx,rfp_port ;get port base address + + xor al,al ;start with color zero + add dx,1 ;move to "read address" register + out dx,al ;set the address + ;-------------------------------------------------------------- + ; Read the color data + ;-------------------------------------------------------------- + add dx,2 ;move to "data" register + mov edi,rfp_dest ;point to destination + mov ecx,256*3 ;transfer entire palette +rfpLoop: + in al,dx ;get the color + shl al,2 ;convert to 8-bit data + stosb ;save it + loop rfpLoop +END_C_PROC + +;------------------------------------------------------------------------- +; SVGAWritePaletteMask(port, mask) +; Set hardware palette mask +; ASSUMES that the port is correct. +;------------------------------------------------------------------------- +; Enter: +; Word port = base port address +; Byte mask = new mask value +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC SVGAWritePaletteMask + ARG_WORD wpm_port + ARG_BYTE wpm_mask + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Write the mask + ;-------------------------------------------------------------- + mov dx,wpm_port ;get port base address + mov al,wpm_mask + out dx,al +END_C_PROC + +END_CODE + END + diff --git a/CODE/RP/MUNGA_L4/L4TIME.CPP b/CODE/RP/MUNGA_L4/L4TIME.CPP new file mode 100644 index 0000000..14acb51 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4TIME.CPP @@ -0,0 +1,153 @@ +#include +#pragma hdrstop + +#if !defined(L4TIME_HPP) +# include +#endif + +#include +#include + +//############################################################################# +//########################### System Clock ############################## +//############################################################################# + +SystemClock + SystemClock::timer; +Scalar + SystemClock::ticksPerSecond; + +volatile long fast_time=0L; +WORD timer_handler_handle=0xFFFF; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Timer_Handler() +{ + ++fast_time; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + SystemClock::GetRTC() +{ + if (timer_handler_handle == 0xFFFF) + { + // + //---------------------------------------------------------------------- + // Read the BIOS time. If it is less than the value it was last time we + // read it, then we have crossed midnight. All the clock values start + // over again, so we will subtract 24 hours worth of ticks from when we + // started the application, allowing the application to simply see the + // clock continue to get bigger, regardless of the boundary condition + //---------------------------------------------------------------------- + // + static long last_time=0L; + long new_time = biostime(0, 0L); + if (new_time < last_time) + { + fast_time -= 1573040L; + } + last_time = new_time; + return new_time - fast_time; + } + else + { + return fast_time; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SystemClock::SystemClock() +{ + // + //------------------------------- + // Initialize the timer variables + //------------------------------- + // + pauseStart = 0L; + pauseTime = 0L; + + // + //------------------------------ + // Initialize the platform timer + //------------------------------ + // + fast_time = 0L; + char *time_options = getenv(TIMER_ENV); + if (time_options && !strcmp(time_options,USE_SOS_TIMER)) + { + #if DEBUG_LEVEL>0 + WORD err = sosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL); + Verify(err == _ERR_NO_ERROR); + err = + sosTIMERRegisterEvent(28, Timer_Handler, &timer_handler_handle); + Verify(err == _ERR_NO_ERROR); + #else + sosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL); + sosTIMERRegisterEvent(28, Timer_Handler, &timer_handler_handle); + #endif + ticksPerSecond = 28.0f; + } + else + { + ticksPerSecond = 1193180.0f / 65536.0f; + fast_time = biostime(0, 0L); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SystemClock::Shutdown() +{ + if (timer_handler_handle != 0xFFFF) + { + #if DEBUG_LEVEL>0 + WORD err = sosTIMERRemoveEvent(timer_handler_handle); + Verify(err == _ERR_NO_ERROR); + err = sosTIMERUnInitSystem(0); + Verify(err == _ERR_NO_ERROR); + #else + sosTIMERRemoveEvent(timer_handler_handle); + sosTIMERUnInitSystem(0); + #endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define TIMER_CONTROL 0x43 +#define GET_TIMER0 0xC2 +#define TIMER0_PORT 0x40 +#define OUTPUT_BIT 0x80 + +#undef inportb +#undef outportb + +float + Get_Frame_Percent_Used() +{ + outportb(TIMER_CONTROL, GET_TIMER0); + int half = inportb(TIMER0_PORT) & OUTPUT_BIT; + int subtick = ((int)inportb(TIMER0_PORT)) >> 1; + subtick += (((int)inportb(TIMER0_PORT)) << 7); + + if (timer_handler_handle == 0xFFFF) + { + subtick += half << 8; + return (65535 - subtick) / 65536.0f; + } + else + { + if (half) + { + subtick += _wTIMERValue >> 1; + } + return (_wTIMERValue - 1 - subtick) / (float)_wTIMERValue; + } +} + diff --git a/CODE/RP/MUNGA_L4/L4TIME.HPP b/CODE/RP/MUNGA_L4/L4TIME.HPP new file mode 100644 index 0000000..f94c572 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4TIME.HPP @@ -0,0 +1,12 @@ + +#if !defined(L4TIME_HPP) +# define L4TIME_HPP + +# if !defined(TIME_HPP) +# include +# endif + +# define TIMER_ENV "L4TIMER" +# define USE_SOS_TIMER "FAST" + +#endif diff --git a/CODE/RP/MUNGA_L4/L4TOOL.HPP b/CODE/RP/MUNGA_L4/L4TOOL.HPP new file mode 100644 index 0000000..ad7113c --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4TOOL.HPP @@ -0,0 +1,89 @@ +//===========================================================================// +// File: txttores.hpp // +// Project: Art Tools // +// Author: Jerry Edsall // +// Purpose: Program to convert Notation files to MUNGA .res files. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(L4TOOL_HPP) +# define L4TOOL_HPP + +# if !defined(TOOL_HPP) +# include +# endif + +# if !defined(AUDTOOLS_HPP) +# include +# endif + + class L4Tool: + public PlatformTool + { + public: + ResourceDescription::ResourceID + CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelGaugeStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelGaugeImageStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelGaugeMissionReviewStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateStaticAudioStreamResource( + ResourceFile *resource_file + ); + + FindNameFunction + GetControlMappingFunction(); + }; + + //########################################################################## + //##################### AudioCreateSymbols ########################### + //########################################################################## + + class L4AudioCreateSymbols: + public AudioCreateSymbols + { + protected: + void + WriteEntryStream(ofstream &symbol_file); + }; + +#endif + diff --git a/CODE/RP/MUNGA_L4/L4TRACE.CPP b/CODE/RP/MUNGA_L4/L4TRACE.CPP new file mode 100644 index 0000000..312afc3 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4TRACE.CPP @@ -0,0 +1,133 @@ +#include +#pragma hdrstop + +#if !defined(STYLE_HPP) +# include +#endif + +void* + Get_Caller(int level) +{ + char *address = (char*)_EBP; + while (level--) + { + Check_Pointer(address); + address = *(char**)address; + } + Check_Pointer(address); + return *(char**)(address+4); +} + +#if defined(USE_ACTIVE_PROFILE) +# undef inportb +# undef outportb + +// +// table of data representing bits on the parallel port at 0x378 (usually LPT1) +// DO NOT ALTER THIS DATA - IT REQUIRES LOTS OF SCHEMATIC TRACING TO DUPLICATE +// + struct ParallelBit + { + unsigned int port; + Byte mask; + int sense; + }; + + ParallelBit + Bit_Table[12] = + { + {0x378, 0x80, 0x00}, + {0x378, 0x40, 0x00}, + {0x378, 0x20, 0x00}, + {0x378, 0x10, 0x00}, + {0x37a, 0x08, 0x01}, + {0x37a, 0x04, 0x00}, + {0x37a, 0x02, 0x01}, + {0x37a, 0x01, 0x01}, + {0x378, 0x08, 0x00}, + {0x378, 0x04, 0x00}, + {0x378, 0x02, 0x00}, + {0x378, 0x01, 0x00} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::SetLineImplementation(Byte line) + { + Verify(line < ELEMENTS(Bit_Table)); + + // + //------------------------------------------------------------------ + // read the current value of the appropriate port + //------------------------------------------------------------------ + // + Byte port_value = inportb(Bit_Table[line].port); + + // + //------------------------------------------------------------------ + // set the appropriate bit, taking into account the hardware sense + //------------------------------------------------------------------ + // + if (!Bit_Table[line].sense) + { + port_value |= Bit_Table[line].mask; + } + else + { + port_value &= (Byte)(~Bit_Table[line].mask); + } + + // + //------------------------------------------------------------------ + // put the modified value into the appropriate port + //------------------------------------------------------------------ + // + outportb(Bit_Table[line].port, port_value); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::ClearLineImplementation(Byte line) + { + Verify(line < ELEMENTS(Bit_Table)); + + // + //------------------------------------------------------------------ + // read the current value of the appropriate port + //------------------------------------------------------------------ + // + Byte port_value = inportb(Bit_Table[line].port); + + // + //------------------------------------------------------------------ + // clear the appropriate bit, taking into account the hardware sense + //------------------------------------------------------------------ + // + if (!Bit_Table[line].sense) + { + port_value &= (Byte)(~Bit_Table[line].mask); + } + else + { + port_value |= Bit_Table[line].mask; + } + + // + //------------------------------------------------------------------ + // put the modified value into the appropriate port + //------------------------------------------------------------------ + // + outportb(Bit_Table[line].port, port_value); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Logical + BitTrace::IsLineValidImplementation(Byte line) + { + return line +#pragma hdrstop + +#if !defined(STYLE_HPP) +# include +#endif + +char GlobalEggFileName[80]; + +int + main() +{ + #if defined(TEST_CLASS) + Start_Registering(); + + // + //------------------ + // Test time manager + //------------------ + // + #if 0 + Time::TestClass(); + #endif + + // + //------------------------------------------------- + // Test gauges and gauge manager + //------------------------------------------------- + // + #if 0 + { + L4Gauge::TestClass(); + + cout << "Gauge test...\n" << flush; + VGA320x200x8 *display; + display = new VGA320x200x8; + Check(display); + Register_Object(display); + + GraphicsPort *port; + port = new GraphicsPort(display); + Check(port); + Register_Object(port); + + Scalar + value(-1.0f); + + Scalar + direction(0.002f); + + BarGraphVerticalScalar *bar; + bar = new + BarGraphVerticalScalar( + NULL, + 0, + port, + 20,20,30,180, + 1, 2, + (Scalar) -1, + (Scalar) 1, + &value + ); + Check(bar); + Register_Object(bar); + + while (!kbhit()) + { + value += direction; + if (value >= 1.0f) + { + value = 1.0f; + direction = - direction; + } + else if (value <= -1.0f) + { + value = -1.0f; + direction = - direction; + } + bar->UpdateParameters(); + bar->Execute(); + display->Update(0); + } + getch(); + + Check(bar); + Unregister_Object(bar); + delete bar; + + Check(port); + Unregister_Object(port); + delete port; + + Check(display); + Unregister_Object(display); + delete display; + } + #endif + + // + //------------------------------------------------- + // Test Audio Hardware + //------------------------------------------------- + // + #if 0 + { + char *blaster1, *blaster2; + + blaster1 = getenv(FRONT_CARD_ENV_VAR); + blaster2 = getenv(REAR_CARD_ENV_VAR); + + //cout << "Audio test...\n" << flush; + + Check_Pointer(blaster1); + Check_Pointer(blaster2); + + AudioHardware::TestClass(); + // AudioHardware::ProfileClass(); + } + #endif + + // + //-------------------------------------------- + // Stop registering, and tell us about its use + //-------------------------------------------- + // + Stop_Registering(); + Tell("Exiting\n"); + #endif + + return 0; +} diff --git a/CODE/RP/MUNGA_L4/L4VB16.CPP b/CODE/RP/MUNGA_L4/L4VB16.CPP new file mode 100644 index 0000000..93d90ab --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VB16.CPP @@ -0,0 +1,5500 @@ +//===========================================================================// +// File: L4vb16.cpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for buffered 16-bit display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/08/95 CPB Initial coding. // +// 11/01/95 CPB Removed 128 color limitation on auxiliary displays // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4VB16_HPP) +# include +#endif + +#if defined(TRACE_SCREEN_COPY) + static BitTrace Screen_Copy("Screen Copy"); + #define SET_SCREEN_COPY() Screen_Copy.Set() + #define CLEAR_SCREEN_COPY() Screen_Copy.Clear() +#else + #define SET_SCREEN_COPY() + #define CLEAR_SCREEN_COPY() +#endif + +#define BLIT_STATISTICS + +#if defined(BLIT_STATISTICS) + static int + dirtyPixelCount, + transferPixelCount, + overflowPixelCount; +#endif + +//#define DEBUG + +#if defined(DEBUG) + static Logical + printFlag=True; +# define Diag_on printFlag=True +# define Diag_off printFlag=False +# define Diag_Tell(stuff) if(printFlag){cout << stuff;} +#else +# define Diag_on +# define Diag_off +# define Diag_Tell(n) +#endif + +extern "C" void + SVGASetMode( + int mode, + LWord pageFlipFcnpointer + ); + +extern "C" void + SVGASetPage( + int page + ); + +extern "C" int + SVGATransfer32( + int dest_offset, + Word *source_pointer, + LWord changed_bits + ); + +extern "C" int + SVGATransfer32x( + int dest_offset, + Word *source_pointer, + LWord changed_bits + ); + +extern "C" void + SVGASetSplitterClock( + Logical state + ); + +extern "C" void + SVGAZeroPalette( + Word DAC_port + ); + +extern "C" void + SVGAWriteFullPalette( + Byte *firstColorByte, + Word DAC_port + ); + +extern "C" void + SVGAReadFullPalette( + Byte *firstColorByte, + Word DAC_port + ); + +extern "C" void + SVGAWritePaletteMask( + Word DAC_port, + Byte new_mask + ); + +extern "C" void + SVGAFunkyVideo( + Logical on_off + ); + + + +//######################################################################## +//############################# BitWrangler ############################## +//######################################################################## +// +// A "bitwrangler" manages a group of bits by segregating them into two groups: +// "active", and "inactive". Active bits are those specified within a given +// bit mask as "ones", and inactive bits are those specified as "zeros". +// +// Once initialized, the bitwrangler may be requested to increment either +// the active bit field or the inactive bit field: the "carry" is propagated +// from the least significant bit through the most significant bit, and if +// an overflow is generated it is returned as "False". +// +// Why in the world would anyone want such a bizarre object? +// It's used here to generate palettes and translation tables according +// to bit allocations for a GraphicsPort. "Unused" colors are easily +// found and set to proper values. +// +class BitWrangler +{ +public: + BitWrangler(int bit_mask, int total_length); + ~BitWrangler() + {} + void ResetActive(); + void ResetInactive(); + Logical IncrementActive(); + Logical IncrementInactive(); + int NumberOfActiveBits(); + int NumberOfInactiveBits(); + + int Value; +protected: + int length; + int bitMask; +}; + +// +// Bitwrangler initialization +// +BitWrangler::BitWrangler(int bit_mask, int total_length) +{ + Verify(bit_mask != 0); + + bitMask = bit_mask; + length = total_length; + Value = 0; + Check_Fpu(); +} + +// +// Reset all "active" bits to zero +// +void + BitWrangler::ResetActive() +{ + Value &= ~ bitMask; + Check_Fpu(); +} + +// +// Reset all "inactive" bits to zero +// +void + BitWrangler::ResetInactive() +{ + Value &= bitMask; + Check_Fpu(); +} + +// +// Increment the "active" bit field, and return "false" if overflow +// +Logical + BitWrangler::IncrementActive() +{ + int single_bit; + int count(length); + + for(single_bit=1; count>0; --count, single_bit <<= 1) + { + // + // If it's an active bit, process it + // + if (bitMask & single_bit) + { + // + // Invert the bit + // + Value ^= single_bit; + // + // If the bit is now set, it was zero, so exit + // + if (Value & single_bit) + { + Check_Fpu(); + return True; + } + } + } + // + // All the active bits are set, so return false + // + Check_Fpu(); + return False; +} + +// +// Increment the "inactive" bit field, and return "false" if overflow +// +Logical + BitWrangler::IncrementInactive() +{ + int single_bit; + int count(length); + int inverse_mask(~bitMask); + + for(single_bit=1; count>0; --count, single_bit <<= 1) + { + // + // If it's an inactive bit, process it + // + if (inverse_mask & single_bit) + { + // + // Invert the bit + // + Value ^= single_bit; + // + // If the bit is now set, it was zero, so exit + // + if (Value & single_bit) + { + Check_Fpu(); + return True; + } + } + } + // + // All the inactive bits are set, so return false + // + Check_Fpu(); + return False; +} + +// +// Return the number of "active" bits +// +int + BitWrangler::NumberOfActiveBits() +{ + int count(0), temp(bitMask); + + while(temp != 0) + { + ++count; + + temp = temp & (temp-1); + } + + Check_Fpu(); + return count; +} + +// +// Return the number of "inactive" bits +// +int + BitWrangler::NumberOfInactiveBits() +{ + Check_Fpu(); + return length-NumberOfActiveBits(); +} + +//######################################################################## +//######################### Video16BitBuffered ########################### +//######################################################################## +// +//NOTE: the application assumes that the origin is in the lower left +// corner of the display, and all parameters passed to these routines +// use the application's coordinate system. +// +// All of the methods here convert these values to the SCREEN +// coordinate system, with the origin in the UPPER LEFT corner of +// the display. +// + +//=================================================================== +// Creator +//=================================================================== +Video16BitBuffered::Video16BitBuffered(int x, int y): + GraphicsDisplay(x, y), + pixelBuffer(x, y) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::Video16BitBuffered()\n" + ); +# endif + int + i, + changed_size; + + Verify(pixelBuffer.Data.MapPointer != NULL); + + height = y; + width = x; + changedBitWidth = (width >> 5); + changed_size = height * changedBitWidth; + + maximumY = height-1; + maximumX = width-1; + //--------------------------------------------------------- + // Create 'changedLine' and 'changedBit' arrays + //--------------------------------------------------------- + changedLine = new Byte[height]; + changedBit = new LWord[changed_size]; + + if (changedLine == NULL || changedBit == NULL) + { +# if defined(DEBUG) + Tell("INVALID!\n"); +# endif + valid = False; + return; + } + else + { + Register_Pointer(changedLine); + Register_Pointer(changedBit); + valid = True; + } + +# if defined(DEBUG) + Tell("changedLine=" << changedLine << "\n"); + Tell("changedBit=" << changedBit << "\n"); +# endif + + //--------------------------------------------------------- + // Clear the 'changedBit' array + //--------------------------------------------------------- + memset(changedLine, 0, height); + //--------------------------------------------------------- + // Clear the 'changedBit' array + //--------------------------------------------------------- + LWord + *bit_dest; + + for (i=changed_size,bit_dest=changedBit; i>0; --i,++bit_dest) + { + *bit_dest = (LWord) 0; + } + Check_Fpu(); +} + +//=================================================================== +// Destructor +//=================================================================== +Video16BitBuffered::~Video16BitBuffered() +{ + Check(this); + + if (changedLine != NULL) + { + Unregister_Pointer(changedLine); + delete changedLine; + changedLine = NULL; + } + + if (changedBit != NULL) + { + Unregister_Pointer(changedBit); + delete changedBit; + changedBit = NULL; + } + Check_Fpu(); +} + + +//=================================================================== +// TestInstance +//=================================================================== +Logical + Video16BitBuffered::TestInstance() const +{ + return True; +} + +//=================================================================== +// ShowInstance +//=================================================================== +void + Video16BitBuffered::ShowInstance( + char *indent + ) +{ + cout << indent << "Video16BitBuffered:\n"; + + Check(this); + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + cout << temp << "width =" << width << "\n"; + cout << temp << "height =" << height << "\n"; + cout << temp << "maximumX =" << maximumX << "\n"; + cout << temp << "maximumY =" << maximumY << "\n"; + cout << temp << "changedLine=" << changedLine << "\n"; + cout << temp << "changedBit =" << changedBit << "\n"; + + pixelBuffer.ShowInstance(temp); + GraphicsDisplay::ShowInstance(temp); + Check_Fpu(); +} + + +//=================================================================== +// buildDestPointer +//=================================================================== +void + Video16BitBuffered::buildDestPointer( + int screenX, + int screenY, + Word **pixel_pointer, + LWord **changed_bit_pointer, + LWord *changed_bit + ) +{ + Verify(valid); + + Verify(pixel_pointer != NULL); + Verify(changed_bit_pointer != NULL); + Verify(changed_bit != NULL); + + Verify(screenX >= 0); + Verify(screenX < width); + Verify(screenY >= 0); + Verify(screenY < height); + + *pixel_pointer = pixelBuffer.Data.MapPointer + + screenX + + (screenY * width); + Verify(*pixel_pointer >= pixelBuffer.Data.MapPointer); + Verify(*pixel_pointer < &pixelBuffer.Data.MapPointer[height*width]); + + *changed_bit_pointer = changedBit + + (screenX >> 5) + + (screenY * changedBitWidth); + Verify(*changed_bit_pointer >= changedBit); + Verify(*changed_bit_pointer < &changedBit[height*changedBitWidth]); + + *changed_bit = 1L << (0x1F - (screenX & 0x1F)); + Verify(*changed_bit != 0L); + + Diag_Tell( + "Video16BitBuffered::buildDestPointer(" << screenX << + ", " << screenY << hex << + ") = pix " << *pixel_pointer << + ", cbp " << *changed_bit_pointer << + ", cb " << *changed_bit << dec << + "\n" + ); + Diag_Tell("changedBitWidth=" << changedBitWidth << "\n"); + + Check_Fpu(); +} + +//=================================================================== +// MarkChangedLines +//=================================================================== +#if defined(BLIT_STATISTICS) +# define SET_CHANGED(pointer, bits) *pointer |= bits; ++dirtyPixelCount +#else +# define SET_CHANGED(pointer, bits) *pointer |= bits +#endif + +#define LEFT_CHANGED(pointer, bits) \ + bits <<= 1; \ + if (bits == 0) { --pointer; bits=0x00000001L; } + +#define RIGHT_CHANGED(pointer, bits) \ + bits >>= 1; \ + if (bits == 0) { ++pointer; bits=0x80000000L; } + +#define UP_CHANGED(pointer, bits) pointer -= changedBitWidth +#define DOWN_CHANGED(pointer, bits) pointer += changedBitWidth + + +#define LEFT_DEST(pointer) --pointer +#define RIGHT_DEST(pointer) ++pointer +#define UP_DEST(pointer) pointer -= width +#define DOWN_DEST(pointer) pointer += width + +#define LEFT_SOURCE(pointer,map) --pointer +#define RIGHT_SOURCE(pointer,map) ++pointer +#define UP_SOURCE(pointer,map) pointer -= map->Data.Size.x +#define DOWN_SOURCE(pointer,map) pointer += map->Data.Size.x + + + +#define LEFT_BITMAP(pointer,bits) \ + bits <<= 1; \ + if (bits == 0) { --pointer; bits=0x0001; } + +#define RIGHT_BITMAP(pointer, bits) \ + bits >>= 1; \ + if (bits == 0) { ++pointer; bits=0x8000; } + +#define UP_BITMAP(pointer,map) pointer -= map->Data.WidthInWords +#define DOWN_BITMAP(pointer,map) pointer += map->Data.WidthInWords + + +// +// Inputs are in DISPLAY COORDINATES, i.e., (0,0) in top left corner! +// +void + Video16BitBuffered::MarkChangedLines( + int start, + int stop + ) +{ + Check(this); + Diag_Tell( + "Video16BitBuffered::MarkChangedLines(" << start << + ", " << stop << + ")\n" + ); + + if (start > stop) + { +# if defined(DEBUG) + Tell("MarkChangedLines FLIPPING\n"); +# endif + int temp; + + temp = start; + start = stop; + stop = temp; + } + + Verify(start >= 0); + Verify(start <= maximumY); + Verify(stop >= 0); + Verify(stop <= maximumY); + + //------------------------------------------------ + // Set the flag for each changed line + //------------------------------------------------ + Verify(stop >= start); + memset(&changedLine[start], 1, stop-start+1); + + Check_Fpu(); +} + +//=================================================================== +// DrawPoint +//=================================================================== +void + Video16BitBuffered::DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ) +{ + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + Word + *dest_pointer; + LWord + *changed_pointer; + LWord + changed_bit; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); +# endif + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y, y); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Create pointers + //--------------------------------------------------------- + buildDestPointer( + x, y, + &dest_pointer, + &changed_pointer, + &changed_bit + ); + //--------------------------------------------------------- + // Write the point + //--------------------------------------------------------- + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + Check_Fpu(); +} + +//=================================================================== +// DrawLine +//=================================================================== +void + Video16BitBuffered::DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawLine(" << color << + ", " << bitmask << + ", " << operation << + ", " << x1 << "," << y1 << "," << x2 << "," << y2 << + ", " << include_last_pixel << + "\n" + ); +# endif + + Check(this); + + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + enum + { + negative_delta_x = 1, + negative_delta_y = 2, + delta_y_greater = 0, + delta_x_greater = 4 + }; + + long + length, + rate, + accumulator; + + int + octant, + delta_x, + delta_y; + + Word + *dest_pointer; + LWord + *changed_pointer; + LWord + changed_bit; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Route to DrawPoint if single pixel + //--------------------------------------------------------- + if (x1 == x2 && y1 == y2) + { + if (include_last_pixel) + { + DrawPoint(color, bitmask, operation, x1, y1); + } + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that endpoints are legitimate + //--------------------------------------------------------- + Verify(x1 >= 0); + Verify(x1 < width); + Verify(x2 >= 0); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 < height); + Verify(y2 >= 0); + Verify(y2 < height); + +# if defined(DEBUG) + Tell( + "Transformed coordinates=" << x1 << "," << y1 << + "," << x2 << "," << y2 << + "\n" + ); +# endif + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Determine which octant to use + //--------------------------------------------------------- + octant = 0; + + delta_x = x2 - x1; + if (delta_x < 0) + { +# if defined(DEBUG) + Tell("negative dx\n"); +# endif + octant |= negative_delta_x; + delta_x = - delta_x; + } + + delta_y = y2 - y1; + if (delta_y < 0) + { +# if defined(DEBUG) + Tell("negative dy\n"); +# endif + octant |= negative_delta_y; + delta_y = - delta_y; + } + + if (delta_x > delta_y) + { +# if defined(DEBUG) + Tell("dx > dy\n"); +# endif + octant |= delta_x_greater; + } +# if defined(DEBUG) + Tell( + "dx=" << delta_x << + ", dy=" << delta_y << + ", octant=" << octant << + ", color=" << color << + "\n" + ); +# endif + //--------------------------------------------------------- + // Prepare to draw line + //--------------------------------------------------------- + buildDestPointer( + x1, y1, + &dest_pointer, + &changed_pointer, + &changed_bit + ); + + accumulator = 1024L; // preset accumulator to 1/2 full + //--------------------------------------------------------- + // Draw the line! + //--------------------------------------------------------- + switch (octant) + { + case delta_y_greater: + //------------------------------------- + // delta y greater + // positive delta x + // positive delta y + // + // + + // \ & + // \ & + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + + Verify(delta_y > 0); + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_y_greater+negative_delta_x: + //------------------------------------- + // delta y greater + // negative delta x + // positive delta y + // + // + + // / + // / + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_y_greater+negative_delta_y: + //------------------------------------- + // delta y greater + // positive delta x + // negative delta y + // + // / + // / + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_y_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta y greater + // negative delta x + // negative delta y + // + // \ & + // \ & + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater: + //------------------------------------- + // delta x greater + // positive delta x + // positive delta y + // + // +---___ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater+negative_delta_x: + //------------------------------------- + // delta x greater + // negative delta x + // positive delta y + // + // ___---+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater+negative_delta_y: + //------------------------------------- + // delta x greater + // positive delta x + // negative delta y + // + // +___--- + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta x greater + // negative delta x + // negative delta y + // + // ---___+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawFilledRectangle +//=================================================================== +void + Video16BitBuffered::DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ +# if defined(DEBUG) + Tell("Video16BitBuffered::DrawFilledRectangle(" << + color << ", " << + hex << bitmask << ", " << dec << + operation << ", " << + x1 << ", " << + y1 << ", " << + x2 << ", " << + y2 << ", " << + ")\n"); +# endif + Check(this); + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + Word + *dest_pointer; + LWord + *init_changed_pointer, + *changed_pointer; + LWord + init_changed_bit, + changed_bit; + int + x, + dest_fixup, + rect_width, + rect_height; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that rectangle is properly specified + //--------------------------------------------------------- + if (x2 < x1) + { + int temp; + + temp = x1; + x1 = x2; + x2 = temp; + } + + if (y2 < y1) + { + int temp; + + temp = y1; + y1 = y2; + y2 = temp; + } + //--------------------------------------------------------- + // Verify that values are legitimate + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + Verify(x1 >= 0); + Verify(x1 <= x2); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 <= y2); + Verify(y2 < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to fill + //--------------------------------------------------------- +# if defined(DEBUG) + Tell( + "x1=" << x1 << ", " << "y1=" << y1 << "\n" << + "x2=" << x2 << ", " << "y2=" << y2 << "\n" << + flush + ); +# endif + buildDestPointer( + x1, y1, + &dest_pointer, + &init_changed_pointer, + &init_changed_bit + ); + + rect_height = y2 - y1 + 1; + rect_width = x2 - x1 + 1; + dest_fixup = width - rect_width; + +# if defined(DEBUG) + Tell( + "rect_height=" << rect_height << "\n" << + "rect_width=" << rect_width << "\n" << + "dest_fixup=" << dest_fixup << "\n" << + flush + ); +# endif + //--------------------------------------------------------- + // Fill the rectangle + //--------------------------------------------------------- + switch(operation) + { + case GraphicsDisplay::Replace: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + dest_pointer++; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::And: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer++ &= (Word) color; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Or: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer++ |= (Word) color; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Xor: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer++ ^= (Word) color; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + } + Check_Fpu(); +} + + +void + Video16BitBuffered::DrawText( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +# if defined(DEBUG) + Tell("Video16BitBuffered::DrawText()\n"); +# endif + Check(this); + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + Check_Fpu(); + if (!valid) + { + return; + } +} + +//=================================================================== +// DrawBitMap +//=================================================================== +void + Video16BitBuffered::DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawBitMap(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + switch (rotation) + { + default: + //-------------------------------------------- + // transparent bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "zero: xp=" << (x+map_width-1) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width-1 >= 0); + Verify(x+map_width-1 < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent bitmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n"); +# endif + + if (x-map_height < 0) + { + Tell("x-map_height = " << (x - map_height) << "\n"); + return; + } + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawBitMapOpaque +//=================================================================== +void + Video16BitBuffered::DrawBitMapOpaque( + int foreground, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + +Diag_on; + Diag_Tell( + "Video16BitBuffered::DrawBitMapOpaque(<" << x << + ", " << y << + ">,<" << sLeft << + ", " << sBottom << + ", " << sRight << + ", " << sTop << + ">)\n" + ); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + Word + color; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +Diag_off; + Diag_Tell("x=" << x << ", y=" << y << "\n"); + Diag_Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Diag_Tell( + "map_width=" << map_width << + ", map_height=" << map_height << + "\n" + ); +Diag_on; + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + //--------------------------------------------------------- + // The bitmap is always read left-to-right, bottom-to-top. + // We write it to the screen in different directions + // based on the rotation. + //--------------------------------------------------------- + switch (rotation) + { + default: + //-------------------------------------------- + // opaque bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width <= width); // HACK? <, or <=? + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // opaque bitmap, 90 degrees + // #--Y--. + // | | + // X | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // opaque bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // opaque bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "xp=" << (x-map_height+1) << + ", yp=" << (y-(map_width-1)) << + "\n" + ); +# endif + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + Diag_Tell( + "(y-(map_width-1))=" << (y-(map_width-1)) << + ", y=" << y << + "," + ); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + Diag_Tell( + "changed_pointer=" << changed_pointer << dec << + "\n" + ); + + break; + } + Check_Fpu(); +Diag_off; +} + +//=================================================================== +// DrawPixelMap8 +//=================================================================== +void + Video16BitBuffered::DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawPixelMap8(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + source_data, + *source_pointer_begin, + *source_pointer; + + Word + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + Word + color; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + if (opaque) + { + switch (rotation) + { + default: + //-------------------------------------------- + // Opaque pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Opaque pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << + "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Opaque pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << + "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Opaque pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Opaque 270: x=" << x << ", y=" << y << "\n"); + Tell( + "xp=" << (x-map_height) << + ", yp=" << (y-(map_width-1)) << + "\n" + ); +# endif + Verify(x-map_height-1 >= 0); + Verify(x-map_height-1 < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + } + else + { + switch (rotation) + { + default: + //-------------------------------------------- + // Transparent pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << + "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << + "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("transparent 270: x=" << x << ", y=" << y << "\n"); + Tell( + "xp=" << (x-map_height) << + ", yp=" << (y-(map_width-1)) << + "\n" + ); +# endif + Verify(x-(map_height-1) >= 0); + Verify(x-(map_height-1) < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//=================================================================== +// DrawPixelMap8SingleColor +//=================================================================== +void + Video16BitBuffered::DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawPixelMap8SingleColor(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + source_data, + *source_pointer_begin, + *source_pointer; + + Word + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + { + switch (rotation) + { + default: + //-------------------------------------------- + // Single-color pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Single-color pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << + "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Single-color pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << + "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Single-color pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Single-color 270: x=" << x << ", y=" << y << "\n"); + Tell( + "xp=" << (x-map_height) << + ", yp=" << (y-map_width) << + "\n" + ); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-map_width >= 0); + Verify(y-map_width < height); + + MarkChangedLines(y-map_width, y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//######################################################################## +//############################ SVGA640x480x16 ############################ +//######################################################################## +SVGA16::SVGA16( + int mode, + int init_width, + int init_height, + int mem_page_size, + int mem_granularity, + int bytes_per_line, + int page_function_pointer, + int special_interface +):Video16BitBuffered(init_width, init_height) +{ +# if defined(DEBUG) + Tell("SVGA16::SVGA16()\n"); +# endif + + pageSize = mem_page_size * 1024; + Verify(mem_granularity > 0); + pageDelta = mem_page_size/mem_granularity; + widthInBytes = bytes_per_line; + pageFcnPtr = page_function_pointer; + specialInterface = special_interface; // currently unused + + currentPageNumber = -1; + + // + // Set video mode + // + SVGASetMode(mode, pageFcnPtr); + // + // Set VWE video splitter clock divider + // + SVGASetSplitterClock(True); + + //------------------------------------------------------------------------ + // Initialize palettes + //------------------------------------------------------------------------ + FadeToWhite(0.0); + //------------------------------------------------------------------------ + // Initialize palette data + //------------------------------------------------------------------------ + // The +2 causes Adam's decoded Palette addresses to "match up" + // with the address definitions used by the standard VGA palette port. + // Adam's port decoder design uses: + // xx00 = write address port + // xx01 = data port + // xx10 = pixel mask port + // xx11 = read address port + // The standard VGA/SVGA ports are: + // 03C6 = ......0110 = xx10 = pixel mask port + // 03C7 = ......0111 = xx11 = read address port + // 03C8 = ......1000 = xx00 = write address port + // 03C9 = ......1001 = xx01 = data port + // Adam's ports are: + // 0300 = secondary palette + // 0308 = auxiliary palette 1 + // 0310 = auxiliary palette 2 + // By adding 2 to "Adam's" port assignments, they match with a VGA: + // 0302/030A/0312 = xx10 = pixel mask port + // 0303/030B/0313 = xx11 = read address port + // 0304/030C/0314 = xx00 = write address port + // 0305/030D/0315 = xx01 = data port + + // See L4VB16.hpp, class SVGA16 for an enumeration of palettes + // matching this table. + + static Word port_addr[PaletteCount] = { + 0x3C6, // NativePalette + 0x300+2, // SecondaryPalette + 0x308+2, // AuxiliaryPalette1 + 0x310+2 // AuxiliaryPalette2 + }; + + SVGA16Palette + *palette_pointer = &palette[0]; + for(int i=0; ihardwarePort = port_addr[i]; + palette_pointer->modified = False; + palette_pointer->flashAccumulator = 0.0; + palette_pointer->flashRate = 0.0; + palette_pointer->previousMaskState = -1; + + for(j=0; jmask[j] = 0xFF; + } + + if (port_addr[i] != 0x3C6) + { + SVGAZeroPalette(port_addr[i]); + } + } + //--------------------------------------------------------- + // Prepare update values + //--------------------------------------------------------- + currentPageNumber = -1; + + ResetUpdatePosition(); + +# if defined(BLIT_STATISTICS) + dirtyPixelCount = 0; + transferPixelCount = 0; + overflowPixelCount = 0; +# endif + //--------------------------------------------------------- + // Clear the display + //--------------------------------------------------------- +# if defined(DEBUG) + Tell("Valid, drawing rectangle-\n" << flush); +# endif + DrawFilledRectangle( + 0, + 0xFFFF, + GraphicsDisplay::Replace, + 0, 0, + maximumX, maximumY + ); +# if defined(DEBUG) + Tell("About to update-\n" << flush); +# endif + Update(False); + Check_Fpu(); +} + +SVGA16::~SVGA16() +{ +# if defined(DEBUG) + Tell("SVGA16::~SVGA16()\n"); +# endif + Check(this); + //--------------------------------------------------------- + // Eventually wait for fade (if any) to complete?? + //--------------------------------------------------------- + + //--------------------------------------------------------- + // Set video mode + //--------------------------------------------------------- + SVGASetMode(3, 0); +# if defined(BLIT_STATISTICS) + double + ratio; + + if (transferPixelCount == 0) + { + ratio = (double) 0; + } + else + { + ratio = ((double) dirtyPixelCount) / transferPixelCount; + } + + //------------------------------------------------------ + // Print statistics + //------------------------------------------------------ + DEBUG_STREAM << + "SVGA16::~SVGA16: pixel management statistics ------------" << + "\nNumber of dirty pixels =" << dirtyPixelCount << + "\nNumber of transferred pixels=" << transferPixelCount << + "\nTimes overflowed =" << overflowPixelCount << + "\nRatio =" << ratio << + "\n-------------------------------------------------------\n"; +# endif + //--------------------------------------------------------- + // Set VWE video splitter clock divider + //--------------------------------------------------------- + SVGASetSplitterClock(False); + Check_Fpu(); +} + +Logical + SVGA16::TestInstance() const +{ + return Video16BitBuffered::TestInstance(); +} + +void + SVGA16::ShowInstance(char *indent) +{ + cout << indent << "SVGA16:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + cout << temp << "SVGA16:\n"; + Video16BitBuffered::ShowInstance(temp); + Check_Fpu(); +} + +Logical + SVGA16::Update(Logical forceAll) +{ + SET_SCREEN_COPY(); + Diag_Tell("SVGA16::Update(" << forceAll << ")\n"); + Check(this); + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + CLEAR_SCREEN_COPY(); + return False; // Do no more! + } + //--------------------------------------------------------- + // Mark all lines as changed if commanded + //--------------------------------------------------------- + if (forceAll) + { + memset(changedLine, 1, height); + } + + int + previous_line_number = lineNumber; + + long + dest_size, + dest_line_size; + + //--------------------------------------------------------- + // Calculate sizes based on specialInterface + //--------------------------------------------------------- + if (specialInterface) + { + dest_size = 32L; // BYTE offset! + dest_line_size = width; + } + else + { + dest_size = 32L << 1; // WORD offset! + dest_line_size = width << 1; + } + //--------------------------------------------------------- + // Process lines for as long as we can + //--------------------------------------------------------- +#if 0 // Let's process just a few lines for background loop processing... + while (Get_Frame_Percent_Used() < .65f) +#endif + { + //--------------------------------------------------------- + // Do a couple of lines before checking time again + //--------------------------------------------------------- + for(int line_limit=15; line_limit > 0; ) + { + //--------------------------------------------------------- + // Check for changed line, clear the flag + //--------------------------------------------------------- + Verify(changedLinePointer < &changedLine[height]); + + int + changed_line = *changedLinePointer; + *changedLinePointer++ = 0; + + if (changed_line) + { + Diag_Tell(height << ":"); + //--------------------------------------------------------- + // Pixels on this line have been changed + //--------------------------------------------------------- + --line_limit; + //--------------------------------------------------------- + // Check 'dirty' LWords: if set, scan for changed pixels + //--------------------------------------------------------- + for(int x=0; x= pageSize) + { + destOffset -= pageSize; + nextPageNumber += pageDelta; + } + } + Diag_Tell("\n"); + } + else + { + //--------------------------------------------------------- + // Line has not changed, skip over it + //--------------------------------------------------------- +#if defined(CHECK_FOR_DIRT) + Logical + dirty_flag = False; + + for(int x=0; x= pageSize) + { + destOffset -= pageSize; + nextPageNumber += pageDelta; + } + } + if (dirty_flag) + { + Tell( + "SVGA16::Update: Unexpected dirty bits in line " << + lineNumber << + "\n!" + ); + } +#else + changedBitPointer += changedBitWidth; + sourcePointer += width; + destOffset += dest_line_size; + + if (destOffset >= pageSize) + { + destOffset -= pageSize; + nextPageNumber += pageDelta; + } +#endif + } + +# if defined(BLIT_STATISTICS) + //--------------------------------- + // Keep values within a sane range + //--------------------------------- + if ( + (transferPixelCount > 0x10000000) + || + (dirtyPixelCount > 0x10000000) + ) + { + transferPixelCount >>= 1; + dirtyPixelCount >>= 1; + ++overflowPixelCount; + } +# endif + //--------------------------------------------------------- + // Check for wrap + //--------------------------------------------------------- + if (++lineNumber >= height) + { + ResetUpdatePosition(); + } + //--------------------------------------------------------- + // If back to beginning, exit loop + //--------------------------------------------------------- + if (lineNumber == previous_line_number) + { + Check_Fpu(); + CLEAR_SCREEN_COPY(); + return False; // All done + } + } + } + Check_Fpu(); + CLEAR_SCREEN_COPY(); + return True; // True == 'more to do' +} + +void + SVGA16::ResetUpdatePosition() +{ + lineNumber = 0; + + sourcePointer = pixelBuffer.Data.MapPointer; + + changedLinePointer = changedLine; + changedBitPointer = changedBit; + + nextPageNumber = 0; + destOffset = 0L; +} + +void + SVGA16::FadeToPalettes(Scalar fade_time) +{ + Check(this); + + previousFadeTime = Now(); + paletteFadeState = fadeToColor; + + if(Small_Enough(fade_time)) + { + fadeUnitsPerSecond = 0.0; + fadeAlpha = 1.0; + } + else + { + fadeUnitsPerSecond = (1.0/fade_time); + } + Check_Fpu(); +} + +void + SVGA16::FadeToWhite(Scalar fade_time) +{ + Check(this); + + previousFadeTime = Now(); + paletteFadeState = fadeToWhite; + + if(Small_Enough(fade_time)) + { + fadeUnitsPerSecond = 0.0; + fadeAlpha = 0.0; + } + else + { + fadeUnitsPerSecond = (1.0/fade_time); + } + Check_Fpu(); +} + +void + generateFade( + SVGA16Palette *source, + Scalar alpha + ) +{ + Check_Pointer(source); + + if (alpha < 0.0) + { + alpha = 0.0; + } + else if (alpha > 1.0) + { + alpha = 1.0; + } + + Palette8 + temp; +// Scalar +// inverse_alpha = (1.0 - alpha) * 255.0; + int + i; + + for(i=0; i<256; ++i) + { + temp.Color[i].Red = (Byte) +// (inverse_alpha + (source->paletteData.Color[i].Red * alpha)); + ((source->paletteData.Color[i].Red * alpha)); + temp.Color[i].Green = (Byte) +// (inverse_alpha + (source->paletteData.Color[i].Green * alpha)); + ((source->paletteData.Color[i].Green * alpha)); + temp.Color[i].Blue = (Byte) +// (inverse_alpha + (source->paletteData.Color[i].Blue * alpha)); + ((source->paletteData.Color[i].Blue * alpha)); + } + + SVGAWriteFullPalette( // in L4SVGA16.ASM + &temp.Color[0].Red, + source->hardwarePort + ); + Check_Fpu(); +} + +void + SVGA16::FlashPalette( + int palette_number, + Scalar rate, + unsigned char *stateList + ) +{ + Check(this); + Verify(palette_number >= 0); + Verify(palette_number < PaletteCount); + + SVGA16Palette + *palette_pointer = &palette[palette_number]; + + //------------------------------------------------- + // Adjust rate so value becomes "cycles per second" + //------------------------------------------------- + palette_pointer->flashRate = rate * (Scalar) SVGA16Palette::maskStates; + //------------------------------------------------- + // Copy the mask values + //------------------------------------------------- + for (int i=0; imask[i] = *stateList++; + } + Check_Fpu(); +} + +void + SVGA16::UnflashPalette( + int palette_number + ) +{ + Check(this); + Verify(palette_number >= 0); + Verify(palette_number < PaletteCount); + + SVGA16Palette + *palette_pointer = &palette[palette_number]; + + palette_pointer->flashRate = 0.0; + palette_pointer->flashAccumulator = 0.0; + palette_pointer->previousMaskState = -1; + SVGAWritePaletteMask(palette_pointer->hardwarePort, 0xFF); + + Check_Fpu(); +} + +void + SVGA16::UpdatePalette() +{ + Check(this); + + int + i, + mask_state; + SVGA16Palette + *palette_pointer; + + //-------------------------------------------------------- + // Update time values + //-------------------------------------------------------- + Time + right_now = Now(); + Scalar + delta_t = (Scalar) (right_now - previousFadeTime); + + previousFadeTime = right_now; + if (delta_t <= 0.0) + { + return; + } + //-------------------------------------------------------- + // Set palette masks + //-------------------------------------------------------- + palette_pointer = &palette[0]; + for(i=0; iflashRate != 0.0) + { + palette_pointer->flashAccumulator += + palette_pointer->flashRate * delta_t; + + while (palette_pointer->flashAccumulator >= + (Scalar) SVGA16Palette::maskStates) + { + palette_pointer->flashAccumulator -= + (Scalar) SVGA16Palette::maskStates; + } + + mask_state = (int) palette_pointer->flashAccumulator; + + if (mask_state != palette_pointer->previousMaskState) + { + palette_pointer->previousMaskState = mask_state; + + SVGAWritePaletteMask( + palette_pointer->hardwarePort, + palette_pointer->mask[mask_state] + ); + } + } + } + //-------------------------------------------------------- + // Fade palettes + //-------------------------------------------------------- + palette_pointer = &palette[0]; + for(i=0; imodified) + { + palette_pointer->modified = False; + + SVGAWriteFullPalette( + &palette_pointer->paletteData.Color[0].Red, + palette_pointer->hardwarePort + ); + } + } + else + { + //-------------------------------------------------------- + // Discard 'modified' flag (we use the local values for + // fade in/out, and in the 'white' state we don't care, + // because we'll have to fade back in anyway) + //-------------------------------------------------------- + palette_pointer->modified = False; + //-------------------------------------------------------- + // Perform fade (or stay white) + //-------------------------------------------------------- + switch(paletteFadeState) + { + case fadeToWhite: + fadeAlpha -= (delta_t * fadeUnitsPerSecond); + generateFade(palette_pointer, fadeAlpha); + + if (fadeAlpha <= 0.0) + { + fadeAlpha = 0.0; + paletteFadeState = whitePalette; + } + break; + + case whitePalette: + break; + + case fadeToColor: + fadeAlpha += (delta_t * fadeUnitsPerSecond); + generateFade(palette_pointer, fadeAlpha); + + if (fadeAlpha >= 1.0) + { + fadeAlpha = 1.0; + paletteFadeState = staticPalette; + } + break; + } + } + } + Check_Fpu(); +} + +void + SVGA16::FunkyVideo(Logical on_off) +{ + Check(this); + SVGAFunkyVideo(on_off); + Check_Fpu(); +} + +//######################################################################## +//########################### L4GraphicsPort ############################# +//######################################################################## + +L4GraphicsPort::L4GraphicsPort( + Video16BitBuffered *graphics_display, + const char *name, + int rotation, + int bit_mask, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID channel_enable +):GraphicsPort(graphics_display, name) +{ + int + bit_test; + // + // Save the base rotation value + // + baseRotation = rotation; + // + // Save the paletteID and channel enable + // + paletteID = palette_ID; + channelEnable = channel_enable; + // + // Save the bitMask + // + bitMask = bit_mask; + Verify (bitMask != 0); + // + // Count the number of active bits in the bitMask + // + for(bit_test=0x8000,numberOfBits=0; bit_test!=0; bit_test>>=1) + { + if (bit_test & bitMask) + { + ++numberOfBits; + } + } + // + // Initialize conversion constants + // + maximumX = bounds.topRight.x - bounds.bottomLeft.x; + maximumY = bounds.topRight.y - bounds.bottomLeft.y; + // + // Overwrite the GraphicsPort::bounds data with rotated values + // for GraphView's benefit + // + switch(baseRotation) + { + default: + // do nothing + break; + + case 90: + case 270: + if (graphics_display != NULL) + { + Check(graphics_display); + bounds.bottomLeft.x = graphics_display->bounds.bottomLeft.y; + bounds.bottomLeft.y = graphics_display->bounds.bottomLeft.x; + bounds.topRight.x = graphics_display->bounds.topRight.y; + bounds.topRight.y = graphics_display->bounds.topRight.x; + } + break; + } + + for(int j=0; j<256; ++j) + { + myColor[j] = NULL; + } + + Check_Fpu(); +} + +L4GraphicsPort::~L4GraphicsPort() +{ + Check(this); + Check_Fpu(); +} + +Logical + L4GraphicsPort::TestInstance() const +{ + return True; +} + +void + L4GraphicsPort::ShowInstance(char *indent) +{ + Check(this); + + cout << indent << "L4GraphicsPort:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + cout << temp << "bitMask =" << bitMask << "\n"; + cout << temp << "baseRotation =" << baseRotation << "\n"; + cout << temp << "maximumX =" << maximumX << "\n"; + cout << temp << "maximumY =" << maximumY << "\n"; + cout << temp << "bounds =" << bounds << "\n"; + cout << flush; + GraphicsPort::ShowInstance(temp); + Check_Fpu(); +} + +void + L4GraphicsPort::SetColor( + PaletteTriplet *source_triplet, + int color_index + ) +{ + Check(this); + Check_Pointer(source_triplet); + Verify(color_index >= 0); + Verify(color_index < 256); + + switch(channelEnable) + { + case L4GraphicsPort::DirectColor: + case L4GraphicsPort::BlankColor: + break; + default: + BuildSecondaryColor(source_triplet, color_index); + break; + } + Check_Fpu(); +} + +void + L4GraphicsPort::SetSecondaryPalette( + Palette8 *source_palette + ) +{ + Check(this); + Check(source_palette); + + if (graphicsDisplay == NULL) + { + return; + } + + switch(channelEnable) + { + case L4GraphicsPort::DirectColor: + BuildDirectTranslation(source_palette); + break; + case L4GraphicsPort::BlankColor: + BlankPalette(); + BuildSecondaryTranslation(); + break; + default: + BuildSecondaryPalette(source_palette); + BuildSecondaryTranslation(); + break; + } + Check_Fpu(); +} + + +void + L4GraphicsPort::SetAuxiliaryPalette() +{ + Check(this); + + if (graphicsDisplay == NULL) + { + return; + } + + switch(channelEnable) + { + case L4GraphicsPort::DirectColor: + //--------------------------------------------------------------- + // Set translation table for direct color mode + //--------------------------------------------------------------- + { + Palette8 + monochrome_palette; + + PaletteTriplet + black, + white; + + black.Red = 0; + black.Green = 0; + black.Blue = 0; + + white.Red = 255; + white.Green = 255; + white.Blue = 255; + + monochrome_palette.BuildColorRange(0,255,black, white); + + BuildDirectTranslation(&monochrome_palette); + } + break; + + case L4GraphicsPort::BlankColor: + BlankPalette(); + BuildAuxiliaryTranslation(); + break; + + default: + BuildAuxiliaryPalette(); + BuildAuxiliaryTranslation(); + break; + } + Check_Fpu(); +} + + +void + L4GraphicsPort::DrawPoint( + int color, + Enumeration operation, + int x, int y + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + graphicsDisplay-> + DrawPoint( + translationTable[color], + bitMask, + operation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawLine( + translationTable[color], + bitMask, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y, + include_last_pixel + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawFilledRectangle( + translationTable[color], + bitMask, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawText( + int /*color*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +} + +void + L4GraphicsPort::DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMap( + translationTable[color], + bitMask, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMapOpaque( + translationTable[color], + translationTable[background], + bitMask, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); +} + +void + L4GraphicsPort::DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8( + translationTable, + bitMask, + operation, + opaque, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8SingleColor( + translationTable[color], + bitMask, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4GraphicsPort::convertPortPair( + int *xp, + int *yp, + int x, + int y + ) +{ + switch(baseRotation) + { + default: + *xp = x; + *yp = y; + break; + + case 90: + *xp = y; + *yp = maximumY - x; + break; + + case 180: + *xp = maximumX - x; + *yp = maximumY - y; + break; + + case 270: + *xp = maximumX - y; + *yp = x; + break; + } + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method generates a translation table specifically for writing +// to a "direct" color mode display, in which colors are represented +// as 5 red bits, 6 green bits, and 5 blue bits in a display word. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildDirectTranslation( + Palette8 *source_palette + ) +{ + PaletteTriplet + *source_data(source_palette->Color); + + int + *dest(translationTable); + + int + red_bits, + green_bits, + blue_bits, + i; + + // + // Force to all bits (just to be sure) + // + bitMask = 0xFFFF; + + for(i=256; i>0; --i,++source_data) + { + red_bits = source_data->Red >> 3; + green_bits = source_data->Green >> 2; + blue_bits = source_data->Blue >> 3; + + *dest++ = (red_bits << 11)|(green_bits << 5) | blue_bits; + } + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method combines palettes from multiple L4GraphicsPorts. +// If several ports have palettes mapped onto the same RGB display, then +// the most recently built palette has precedence over the previous one(s). +// +// Palettes are assumed to always have 256 colors. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildSecondaryPalette( + Palette8 *source_palette + ) +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + Check(source_palette); + + + int + byte_mask(bitMask & 0xFF); + Verify (byte_mask != 0); + + BitWrangler + wrangler(byte_mask, 8); + + PaletteTriplet + *source_triplet, + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + source_triplet = &source_palette->Color[0]; + + //------------------------------------------- + // Clear the 'owned color' flags + //------------------------------------------- + for(int j=0; j<256; ++j) + { + myColor[wrangler.Value] = 0; + } + + // + // If any of the ...TransparentZero modes are used, + // leave color zero undefined for this bit group by + // skipping over it + // + if (channelEnable & 0x80) + { + ++source_triplet; + wrangler.IncrementActive(); + } + + // + // Fill in the color table for this palette set + // + do + { + //------------------------------------------- + // Write all destination colors + //------------------------------------------- + do + { + //------------------------------------------- + // Set the 'owned color' flag + //------------------------------------------- + myColor[wrangler.Value] = 1; + //------------------------------------------- + // Get destination pointer + //------------------------------------------- + destination_triplet = + &svga_palette->paletteData.Color[wrangler.Value]; + //------------------------------------------- + // Copy color data + //------------------------------------------- + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = source_triplet->Red; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = source_triplet->Green; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = source_triplet->Blue; + break; + + case AllChannels: + case AllChannelsTransparentZero: + *destination_triplet = *source_triplet; + break; + } + } + while (wrangler.IncrementInactive()); + //------------------------------------------- + // Bump the source pointer + //------------------------------------------- + ++source_triplet; + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method combines palettes from multiple L4GraphicsPorts. +// If several ports have palettes mapped onto the same RGB display, then +// the most recently built palette has precedence over the previous one(s). +// +// Palettes are assumed to always have 256 colors. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildSecondaryColor( + PaletteTriplet *source_triplet, + int dest_color_number + ) +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + Check_Pointer(source_triplet); + + int + byte_mask(bitMask & 0xFF); + Verify (byte_mask != 0); + + BitWrangler + wrangler(byte_mask, 8); + + int + destination_color = 0; + + PaletteTriplet + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + //------------------------------------------- + // If any of the ...TransparentZero modes are used, + // leave color zero undefined for this bit group by + // skipping over it + //------------------------------------------- + if (channelEnable & 0x80) + { + ++destination_color; + wrangler.IncrementActive(); + } + + //------------------------------------------- + // Set the color value + //------------------------------------------- + do + { + //------------------------------------------- + // Write all destination colors + //------------------------------------------- + if (destination_color == dest_color_number) + { + //------------------------------------------- + // Write all destination colors + //------------------------------------------- + do + { + //------------------------------------------- + // Do we own this color? Skip if unowned + //------------------------------------------- + if (myColor[wrangler.Value]) + { + //------------------------------------------- + // Copy color data + //------------------------------------------- + destination_triplet = + &svga_palette->paletteData.Color[wrangler.Value]; + + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = source_triplet->Red; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = source_triplet->Green; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = source_triplet->Blue; + break; + + case AllChannels: + case AllChannelsTransparentZero: + *destination_triplet = *source_triplet; + break; + } + } + } + while (wrangler.IncrementInactive()); + //------------------------------------------- + // Only doing one color, so exit the loop + //------------------------------------------- + break; + } + //------------------------------------------- + // Bump the color counter + //------------------------------------------- + ++destination_color; + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method combines palettes from multiple L4GraphicsPorts. +// If several ports have palettes mapped on top of another, then +// the most recently built palette has precedence over the previous one(s). +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildAuxiliaryPalette() +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + + + int + byte_mask((bitMask >> 8) & 0xFF); + + Verify (byte_mask != 0); + BitWrangler + wrangler(byte_mask, 8); + + int + rate, + accumulator; + + Byte + color_value; + + PaletteTriplet + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + Verify(((1< 0); + rate = (255<<5)/((1<> 5); + accumulator += rate; + + do + { + destination_triplet = &svga_palette->paletteData. + Color[wrangler.Value]; + + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = color_value; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = color_value; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = color_value; + break; + + case AllChannels: + case AllChannelsTransparentZero: + destination_triplet->Red = color_value; + destination_triplet->Green = color_value; + destination_triplet->Blue = color_value; + break; + } + } + while (wrangler.IncrementInactive()); + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + +# if defined(TESTPALETTE) + cout << "L4GraphicsPort::BuildAuxiliaryPalette for port " << + hex << svga_palette->hardwarePort << "\n"; + for(int i=0; i<256; ++i) + { + if ((i & 0x03) == 0) + { + cout << dec << "\n" << i << ":" << hex; + } + cout << svga_palette->paletteData.Color[i] << " "; + } + cout << "\n"; + { + Palette8 + temp; + + SVGAReadFullPalette( + &temp.Color[0].Red, + svga_palette->hardwarePort + ); + + cout << "L4GraphicsPort::BuildAuxiliaryPalette, read back\n"; + for(int i=0; i<256; ++i) + { + if ((i & 0x03) == 0) + { + cout << dec << "\n" << i << ":" << hex; + } + cout << temp.Color[i] << " "; + } + cout << "\n"; + } +# endif + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This sets 'owned' color values in a palette to zero. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BlankPalette() +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + + int + byte_mask((bitMask >> 8) & 0xFF); + + Verify (byte_mask != 0); + BitWrangler + wrangler(byte_mask, 8); + + Byte + color_value; + + PaletteTriplet + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + Verify(((1< 0); + + color_value = 0; + do + { + do + { + destination_triplet = &svga_palette->paletteData. + Color[wrangler.Value]; + + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = color_value; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = color_value; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = color_value; + break; + + case AllChannels: + case AllChannelsTransparentZero: + destination_triplet->Red = color_value; + destination_triplet->Green = color_value; + destination_triplet->Blue = color_value; + break; + } + } + while (wrangler.IncrementInactive()); + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method generates a translation table for the secondary display, +// using a previously set palette and channel. +// +// Palettes are assumed to always have 256 colors. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildSecondaryTranslation() +{ + Verify((bitMask & 0xFF) != 0); + + BitWrangler + wrangler(bitMask & 0xFF, 8); + + int + *destination(translationTable); + + do + { + *destination++ = wrangler.Value; + } + while (wrangler.IncrementActive()); + Check_Fpu(); +} + + +// +//--------------------------------------------------------------------------- +// This method generates a translation table for the auxiliary displays. +// +// Palettes are assumed to always have 256 colors (0=black, 255=white). +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildAuxiliaryTranslation() +{ + Verify(numberOfBits != 0); + Verify(numberOfBits <= 8); + + int + byte_mask((bitMask >> 8) & 0xFF); + Verify(byte_mask != 0); + + BitWrangler + wrangler(byte_mask, 8); + int + *destination(translationTable); + int + currentValue; + + // + // Generate lookup table + // + do + { + currentValue = wrangler.Value << 8; + + do + { + *destination++ = currentValue; + } + while (wrangler.IncrementInactive()); + } + while (wrangler.IncrementActive()); + +# if defined(TESTPALETTE) + cout << "L4GraphicsPort::BuildAuxiliaryTranslation\n"; + for(int i=0; i<256; ++i) + { + if ((i & 0x07) == 0) + { + cout << "\n" << dec << i << ":" << hex; + } + cout << translationTable[i] << " "; + } + cout << "\n"; +# endif + Check_Fpu(); +} + + + + + + + + + + diff --git a/CODE/RP/MUNGA_L4/L4VB16.HPP b/CODE/RP/MUNGA_L4/L4VB16.HPP new file mode 100644 index 0000000..c2cef6e --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VB16.HPP @@ -0,0 +1,505 @@ +//===========================================================================// +// File: L4V16.hpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for 16-bit video display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/08/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4VB16_HPP) +# define L4VB16_HPP + +# if !defined(GRAPH2D_HPP) +# include +# endif + +# if !defined(TIME_HPP) +# include +# endif + + class L4graphicsPort; + + //######################################################################## + //######################### Video16BitBuffered ########################### + //######################################################################## + // + // X/Y values passed to these routines are assumed to be in + // the VIDEO DISPLAY COORDINATE SYSTEM, with (0,0) at the top left. + // + class Video16BitBuffered : + public GraphicsDisplay + { + public: + Video16BitBuffered(int x, int y); + + ~Video16BitBuffered(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + protected: + void + MarkChangedLines(int screenTop, int screenBottom); + + void + buildDestPointer( + int x, int y, + Word **pixelPointer, + LWord **changed_bit_pointer, + LWord *changed_bit + ); + + Logical + valid; + int + width, + changedBitWidth, + height, + maximumX, + maximumY; + + PixelMap16 + pixelBuffer; + Byte + *changedLine; + LWord + *changedBit; + }; + + + //######################################################################## + //################################ SVGA16 ################################ + //######################################################################## + struct SVGA16Palette + { + Word + hardwarePort; + Logical + modified; + Palette8 + paletteData; + Scalar + flashAccumulator, + flashRate; + + enum PaletteID + { + maskStates=4 + }; + unsigned char + mask[maskStates]; + int + previousMaskState; + }; + + + class SVGA16 : + public Video16BitBuffered + { + friend class L4GraphicsPort; // for palette access + + public: + + enum PaletteID { + NativePalette=0, + SecondaryPalette, + AuxiliaryPalette1, + AuxiliaryPalette2, + PaletteCount + }; + + SVGA16( + int mode, + int width, + int height, + int page_size, + int mem_granularity, + int bytes_per_line, + int page_function_pointer, + int special_interface + ); + + ~SVGA16(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + Logical + Update(Logical forceall); + void + UpdatePalette(); + + void + FadeToPalettes(Scalar fade_time); + void + FadeToWhite(Scalar fade_time); + void + FlashPalette( + int palette_number, + Scalar rate, + unsigned char *stateList + ); + void + UnflashPalette(int palette_number); + + void + FunkyVideo(Logical on_off); + + protected: + void + ResetUpdatePosition(); + + int + pageSize, + pageDelta, + widthInBytes, + pageFcnPtr, + specialInterface; + + int + currentPageNumber, + nextPageNumber, + lineNumber; + long + destOffset; + Byte + *changedLinePointer; + Word + *sourcePointer; + LWord + *changedBitPointer; + + enum PaletteFadeState + { + staticPalette, + fadeToWhite, + whitePalette, + fadeToColor + }; + + PaletteFadeState + paletteFadeState; + Scalar + fadeAlpha, + fadeUnitsPerSecond; + Time + previousFadeTime; + + // This array is closely linked to the PaletteID enumeration, above + SVGA16Palette + palette[PaletteCount]; + }; + + //######################################################################## + //########################## L4GraphicsPort ############################## + //######################################################################## + // + // X/Y values passed to these routines are assumed to be in + // the GRAPHICS COORDINATE SYSTEM, with (0,0) at the bottom left. + // + class L4GraphicsPort : + public GraphicsPort + { + public: + enum ChannelEnableID { + RedChannel, + GreenChannel, + BlueChannel, + AllChannels, + + DirectColor, + BlankColor, + + RedChannelTransparentZero=0x80, + GreenChannelTransparentZero, + BlueChannelTransparentZero, + AllChannelsTransparentZero + }; + + L4GraphicsPort( + Video16BitBuffered *graphics_display, + const char *name, + int rotation, + int bit_mask, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID channel_enable + ); + + ~L4GraphicsPort(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + SetSecondaryPalette( + Palette8 *source_palette + ); + + void + SetAuxiliaryPalette(); + + void + SetColor( + PaletteTriplet *source_color, + int color_index + ); + + void + DrawPoint( + int color, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + SetPaletteID(SVGA16::PaletteID palette_ID) + { + Check(this); + paletteID = palette_ID; + } + + void + SetEnableID(L4GraphicsPort::ChannelEnableID channel_enable) + { + Check(this); + channelEnable = channel_enable; + } + + int + GetBitMask() + { + Check(this); + return bitMask; + } + + protected: + void + convertPortPair( + int *xp, + int *yp, + int x, + int y + ); + + void + BuildDirectTranslation( + Palette8 *source_palette + ); + + void + BuildSecondaryPalette( + Palette8 *source_palette + ); + + void + BuildAuxiliaryPalette(); + + void + BuildSecondaryTranslation(); + + void + BuildAuxiliaryTranslation(); + + void + BlankPalette(); + + void + BuildSecondaryColor( + PaletteTriplet *source_triplet, + int color_number + ); + //------------------------------------------------------------ + // Protected data + //------------------------------------------------------------ + int + translationTable[256]; + unsigned char + myColor[256]; + + int + baseRotation, + bitMask, + numberOfBits, + maximumX, + maximumY; + + SVGA16::PaletteID + paletteID; + + L4GraphicsPort::ChannelEnableID + channelEnable; + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4VB8.CPP b/CODE/RP/MUNGA_L4/L4VB8.CPP new file mode 100644 index 0000000..d94b0b1 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VB8.CPP @@ -0,0 +1,3035 @@ +//===========================================================================// +// File: L4vb16.cpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for buffered 16-bit display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/08/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4VB8_HPP) +# include +#endif + +//######################################################################## +//######################### Video8BitBuffered ########################### +//######################################################################## +// +//NOTE: the application assumes that the origin is in the lower left +// corner of the display, and all parameters passed to these routines +// use the application's coordinate system. +// +// All of the methods here convert these values to the SCREEN +// coordinate system, with the origin in the UPPER LEFT corner of +// the display. +// + +//=================================================================== +// Creator +//=================================================================== +Video8BitBuffered::Video8BitBuffered(int x, int y): + GraphicsDisplay(x, y) + { +# if defined(DEBUG) + Tell( + "Video8BitBuffered::Video8BitBuffered()\n" + ); +# endif + int + i; + Word + *line_dest; + + pixelBuffer = new PixelMap8(x, y); + Check(pixelBuffer); + Verify(pixelBuffer->Data.MapPointer != NULL); + Register_Object(pixelBuffer); + createdPixelmap = True; + + height = y; + width = x; + + maximumY = height-1; + maximumX = width-1; + //--------------------------------------------------------- + // Create 'changedLine' array + //--------------------------------------------------------- + changedLine = new Word[height]; + Register_Pointer(changedLine); + valid = True; + + //--------------------------------------------------------- + // Clear the 'changedLine' array + //--------------------------------------------------------- + for (i=height,line_dest=changedLine; i>0; --i,++line_dest) + { + *line_dest = 0; + } + Check_Fpu(); +} + +Video8BitBuffered::Video8BitBuffered(PixelMap8 *pixel_buffer): + GraphicsDisplay(pixel_buffer->Data.Size.x, pixel_buffer->Data.Size.y) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::Video8BitBuffered()\n" + ); +# endif + int + i; + Word + *line_dest; + + pixelBuffer = pixel_buffer; + Verify(pixelBuffer->Data.MapPointer != NULL); + createdPixelmap = False; + + height = pixelBuffer->Data.Size.y; + width = pixelBuffer->Data.Size.x; + + maximumY = height-1; + maximumX = width-1; + //--------------------------------------------------------- + // Create 'changedLine' array + //--------------------------------------------------------- + changedLine = new Word[height]; + Register_Pointer(changedLine); + +# if defined(DEBUG) + Tell("changedLine=" << changedLine << "\n"); +# endif + + if (changedLine == NULL) + { +# if defined(DEBUG) + Tell("INVALID!\n"); +# endif + valid = False; + return; + } + else + { + Register_Pointer(changedLine); + valid = True; + } + //--------------------------------------------------------- + // Clear the 'changedLine' array + //--------------------------------------------------------- + for (i=height,line_dest=changedLine; i>0; --i,++line_dest) + { + *line_dest = 0; + } + Check_Fpu(); +} + +//=================================================================== +// Destructor +//=================================================================== +Video8BitBuffered::~Video8BitBuffered() +{ + Check(this); + + if (changedLine != NULL) + { + Unregister_Pointer(changedLine); + delete changedLine; + changedLine = NULL; + } + + if (createdPixelmap) + { + if (pixelBuffer != NULL) + { + Check(pixelBuffer); + Unregister_Object(pixelBuffer); + delete pixelBuffer; + pixelBuffer = NULL; + } + createdPixelmap = False; + } + + Check_Fpu(); +} + + +//=================================================================== +// TestInstance +//=================================================================== +Logical + Video8BitBuffered::TestInstance() const +{ + return True; +} + +//=================================================================== +// ShowInstance +//=================================================================== +void + Video8BitBuffered::ShowInstance( + char *indent + ) +{ + cout << indent << "Video8BitBuffered:\n"; + + Check(this); + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + cout << temp << "width =" << width << "\n"; + cout << temp << "height =" << height << "\n"; + cout << temp << "maximumX =" << maximumX << "\n"; + cout << temp << "maximumY =" << maximumY << "\n"; + cout << temp << "changedLine=" << changedLine << "\n"; + + pixelBuffer->ShowInstance(temp); + GraphicsDisplay::ShowInstance(temp); + Check_Fpu(); +} + + +//=================================================================== +// buildDestPointer +//=================================================================== +void + Video8BitBuffered::buildDestPointer( + int screenX, + int screenY, + Byte **pixel_pointer + ) +{ + Verify(valid); + + Verify(pixel_pointer != NULL); + + Verify(screenX >= 0); + Verify(screenX < width); + Verify(screenY >= 0); + Verify(screenY < height); + + *pixel_pointer = pixelBuffer->Data.MapPointer + + screenX + + (screenY * width); + Verify(*pixel_pointer >= pixelBuffer->Data.MapPointer); + Verify(*pixel_pointer < &pixelBuffer->Data.MapPointer[height*width]); + + Check_Fpu(); +} +#define LEFT_DEST(pointer) --pointer +#define RIGHT_DEST(pointer) ++pointer +#define UP_DEST(pointer) pointer -= width +#define DOWN_DEST(pointer) pointer += width + +#define LEFT_SOURCE(pointer,map) --pointer +#define RIGHT_SOURCE(pointer,map) ++pointer +#define UP_SOURCE(pointer,map) pointer -= map->Data.Size.x +#define DOWN_SOURCE(pointer,map) pointer += map->Data.Size.x + +#define LEFT_BITMAP(pointer,bits) \ + bits <<= 1; \ + if (bits == 0) { --pointer; bits=0x0001; } + +#define RIGHT_BITMAP(pointer, bits) \ + bits >>= 1; \ + if (bits == 0) { ++pointer; bits=0x8000; } + +#define UP_BITMAP(pointer,map) pointer -= map->Data.WidthInWords +#define DOWN_BITMAP(pointer,map) pointer += map->Data.WidthInWords + +#define WRITEPIXEL(dest_pointer, operation, color) \ + switch (operation) \ + {\ + case GraphicsDisplay::Replace:\ + *dest_pointer = (Byte)color;\ + break;\ + case GraphicsDisplay::And:\ + *dest_pointer &= (Byte) color;\ + break;\ + case GraphicsDisplay::Or:\ + *dest_pointer |= (Byte) color;\ + break;\ + case GraphicsDisplay::Xor:\ + *dest_pointer ^= (Byte) color;\ + break;\ + } + +//=================================================================== +// MarkChangedLines +//=================================================================== +// +// Inputs are in DISPLAY COORDINATES, i.e., (0,0) in top left corner! +// +void + Video8BitBuffered::MarkChangedLines( + int start, + int stop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::MarkChangedLines(" << start << ", " << stop << + ")\n" + ); +# endif + Check(this); + + if (start > stop) + { +# if defined(DEBUG) + Tell("MarkChangedLines FLIPPING\n"); +# endif + int temp; + + temp = start; + start = stop; + stop = temp; + } + + Verify(start >= 0); + Verify(start <= maximumY); + Verify(stop >= 0); + Verify(stop <= maximumY); + + ++changedLine[start]; + + // + // Always include at least one line + // + if (stop < maximumY) + { + --changedLine[stop+1]; + } + + Check_Fpu(); +} + +//=================================================================== +// DrawPoint +//=================================================================== +void + Video8BitBuffered::DrawPoint( + int color, + int /*bitmask*/, + Enumeration operation, + int x, int y + ) +{ + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + Byte + *dest_pointer; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); +# endif + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y, y); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Create pointers + //--------------------------------------------------------- + buildDestPointer( + x, y, + &dest_pointer + ); + //--------------------------------------------------------- + // Write the point + //--------------------------------------------------------- + WRITEPIXEL(dest_pointer, operation, color) + Check_Fpu(); +} + +//=================================================================== +// DrawLine +//=================================================================== +void + Video8BitBuffered::DrawLine( + int color, + int /*bitmask*/, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawLine(" << color << + ", " << bitmask << + ", " << operation << + ", " << x1 << "," << y1 << "," << x2 << "," << y2 << + ", " << include_last_pixel << + "\n" + ); +# endif + + Check(this); + + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + enum + { + negative_delta_x = 1, + negative_delta_y = 2, + delta_y_greater = 0, + delta_x_greater = 4 + }; + + long + length, + rate, + accumulator; + + int + octant, + delta_x, + delta_y; + + Byte + *dest_pointer; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Route to DrawPoint if single pixel + //--------------------------------------------------------- + if (x1 == x2 && y1 == y2) + { + if (include_last_pixel) + { + DrawPoint(color, 0 /*bitmask*/, operation, x1, y1); + } + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that endpoints are legitimate + //--------------------------------------------------------- + Verify(x1 >= 0); + Verify(x1 < width); + Verify(x2 >= 0); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 < height); + Verify(y2 >= 0); + Verify(y2 < height); + +# if defined(DEBUG) + Tell( + "Transformed coordinates=" << x1 << "," << y1 << + "," << x2 << "," << y2 << + "\n" + ); +# endif + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Determine which octant to use + //--------------------------------------------------------- + octant = 0; + + delta_x = x2 - x1; + if (delta_x < 0) + { +# if defined(DEBUG) + Tell("negative dx\n"); +# endif + octant |= negative_delta_x; + delta_x = - delta_x; + } + + delta_y = y2 - y1; + if (delta_y < 0) + { +# if defined(DEBUG) + Tell("negative dy\n"); +# endif + octant |= negative_delta_y; + delta_y = - delta_y; + } + + if (delta_x > delta_y) + { +# if defined(DEBUG) + Tell("dx > dy\n"); +# endif + octant |= delta_x_greater; + } +# if defined(DEBUG) + Tell( + "dx=" << delta_x << + ", dy=" << delta_y << + ", octant=" << octant << + ", color=" << color << + "\n" + ); +# endif + //--------------------------------------------------------- + // Prepare to draw line + //--------------------------------------------------------- + buildDestPointer( + x1, y1, + &dest_pointer + ); + + accumulator = 1024L; // preset accumulator to 1/2 full + //--------------------------------------------------------- + // Draw the line! + //--------------------------------------------------------- + switch (octant) + { + case delta_y_greater: + //------------------------------------- + // delta y greater + // positive delta x + // positive delta y + // + // + + // \ & + // \ & + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + + Verify(delta_y > 0); + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + DOWN_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + } + } + break; + + case delta_y_greater+negative_delta_x: + //------------------------------------- + // delta y greater + // negative delta x + // positive delta y + // + // + + // / + // / + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + DOWN_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + } + } + break; + + case delta_y_greater+negative_delta_y: + //------------------------------------- + // delta y greater + // positive delta x + // negative delta y + // + // / + // / + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + UP_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + } + } + break; + + case delta_y_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta y greater + // negative delta x + // negative delta y + // + // \ & + // \ & + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + UP_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + } + } + break; + + case delta_x_greater: + //------------------------------------- + // delta x greater + // positive delta x + // positive delta y + // + // +---___ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + RIGHT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + } + } + break; + + case delta_x_greater+negative_delta_x: + //------------------------------------- + // delta x greater + // negative delta x + // positive delta y + // + // ___---+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + LEFT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + } + } + break; + + case delta_x_greater+negative_delta_y: + //------------------------------------- + // delta x greater + // positive delta x + // negative delta y + // + // +___--- + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + RIGHT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + } + } + break; + + case delta_x_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta x greater + // negative delta x + // negative delta y + // + // ---___+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + LEFT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawFilledRectangle +//=================================================================== +void + Video8BitBuffered::DrawFilledRectangle( + int color, + int /*bitmask*/, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ +# if defined(DEBUG) + Tell("Video8BitBuffered::DrawFilledRectangle(" << + color << ", " << + hex << bitmask << ", " << dec << + operation << ", " << + x1 << ", " << + y1 << ", " << + x2 << ", " << + y2 << ", " << + ")\n"); +# endif + Check(this); + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + Byte + *dest_pointer; + int + x, + dest_fixup, + rect_width, + rect_height; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that rectangle is properly specified + //--------------------------------------------------------- + if (x2 < x1) + { + int temp; + + temp = x1; + x1 = x2; + x2 = temp; + } + + if (y2 < y1) + { + int temp; + + temp = y1; + y1 = y2; + y2 = temp; + } + //--------------------------------------------------------- + // Verify that values are legitimate + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + Verify(x1 >= 0); + Verify(x1 <= x2); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 <= y2); + Verify(y2 < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to fill + //--------------------------------------------------------- +# if defined(DEBUG) + Tell( + "x1=" << x1 << ", " << "y1=" << y1 << "\n" << + "x2=" << x2 << ", " << "y2=" << y2 << "\n" << + flush + ); +# endif + buildDestPointer(x1, y1, &dest_pointer); + + rect_height = y2 - y1 + 1; + rect_width = x2 - x1 + 1; + dest_fixup = width - rect_width; + +# if defined(DEBUG) + Tell( + "rect_height=" << rect_height << "\n" << + "rect_width=" << rect_width << "\n" << + "dest_fixup=" << dest_fixup << "\n" << + flush + ); +# endif + //--------------------------------------------------------- + // Fill the rectangle + //--------------------------------------------------------- + switch(operation) + { + case GraphicsDisplay::Replace: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer = (Byte) color; + dest_pointer++; + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::And: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer++ &= (Byte) color; + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Or: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer++ |= (Byte) color; + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Xor: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer++ ^= (Byte) color; + } + dest_pointer += dest_fixup; + } + break; + } + Check_Fpu(); +} + + +void + Video8BitBuffered::DrawText( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +# if defined(DEBUG) + Tell("Video8BitBuffered::DrawText()\n"); +# endif + Check(this); + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + Check_Fpu(); + if (!valid) + { + return; + } +} + +//=================================================================== +// DrawBitMap +//=================================================================== +void + Video8BitBuffered::DrawBitMap( + int color, + int /*bitmask*/, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawBitMap(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer; + Byte + *dest_pointer_begin, + *dest_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + switch (rotation) + { + default: + //-------------------------------------------- + // transparent bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("zero: xp=" << (x+map_width-1) << ", yp=" << (y-map_height+1) << "\n"); +# endif + Verify(x+map_width-1 >= 0); + Verify(x+map_width-1 < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent bitmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n"); +# endif + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawBitMapOpaque +//=================================================================== +void + Video8BitBuffered::DrawBitMapOpaque( + int foreground, + int background, + int /*bitmask*/, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawBitMapOpaque(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer; + Byte + *dest_pointer_begin, + *dest_pointer; + Byte + color; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + switch (rotation) + { + default: + //-------------------------------------------- + // opaque bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("zero: xp=" << (x+map_width) << ", yp=" << (y-map_height+1) << "\n"); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width <= width); // HACK? <, or <=? + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // opaque bitmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // opaque bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // opaque bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_height+1) << ", yp=" << (y-(map_width-1)) << "\n"); +# endif + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawPixelMap8 +//=================================================================== +void + Video8BitBuffered::DrawPixelMap8( + int */*translation_table*/, + int /*bitmask*/, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawPixelMap8(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + color, + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + if (opaque) + { + switch (rotation) + { + default: + //-------------------------------------------- + // Opaque pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Opaque pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Opaque pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Opaque pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Opaque 270: x=" << x << ", y=" << y << "\n"); + Tell("xp=" << x-map_height << ", yp=" << y-(map_width-1) << "\n"); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + UP_DEST(dest_pointer); + } + } + break; + } + } + else + { + switch (rotation) + { + default: + //-------------------------------------------- + // Transparent pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("transparent 270: x=" << x << ", y=" << y << "\n"); + Tell("xp=" << x-map_height << ", yp=" << y-(map_width-1) << "\n"); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//=================================================================== +// DrawPixelMap8SingleColor +//=================================================================== +void + Video8BitBuffered::DrawPixelMap8SingleColor( + int color, + int /*bitmask*/, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawPixelMap8SingleColor(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + source_data, + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + { + switch (rotation) + { + default: + //-------------------------------------------- + // Single-color pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Single-color pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Single-color pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Single-color pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Single-color 270: x=" << x << ", y=" << y << "\n"); + Tell("xp=" << x-map_height << ", yp=" << y-map_width << "\n"); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-map_width >= 0); + Verify(y-map_width < height); + + MarkChangedLines(y-map_width, y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//######################################################################## +//########################### L4BytePort ############################# +//######################################################################## + +L4BytePort::L4BytePort( + Video8BitBuffered *graphics_display, + const char *name, + int rotation +):GraphicsPort(graphics_display, name) +{ + // + // Save the base rotation value + // + baseRotation = rotation; + // + // Initialize conversion constants + // + maximumX = bounds.topRight.x - bounds.bottomLeft.x; + maximumY = bounds.topRight.y - bounds.bottomLeft.y; + // + // Overwrite the GraphicsPort::bounds data with rotated values + // for GraphView's benefit + // + switch(baseRotation) + { + default: + // do nothing + break; + + case 90: + case 270: + if (graphics_display != NULL) + { + Check(graphics_display); + bounds.bottomLeft.x = graphics_display->bounds.bottomLeft.y; + bounds.bottomLeft.y = graphics_display->bounds.bottomLeft.x; + bounds.topRight.x = graphics_display->bounds.topRight.y; + bounds.topRight.y = graphics_display->bounds.topRight.x; + } + break; + } + Check_Fpu(); +} + +L4BytePort::~L4BytePort() +{ + Check(this); + Check_Fpu(); +} + +Logical + L4BytePort::TestInstance() const +{ + return True; +} + +void + L4BytePort::ShowInstance(char *indent) +{ + Check(this); + + cout << indent << "L4BytePort:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + cout << temp << "baseRotation =" << baseRotation << "\n"; + cout << temp << "maximumX =" << maximumX << "\n"; + cout << temp << "maximumY =" << maximumY << "\n"; + cout << temp << "bounds =" << bounds << "\n"; + cout << flush; + GraphicsPort::ShowInstance(temp); + Check_Fpu(); +} + +void + L4BytePort::DrawPoint( + int color, + Enumeration operation, + int x, int y + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + graphicsDisplay-> + DrawPoint( + color, + 0, + operation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4BytePort::DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawLine( + color, + 0, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y, + include_last_pixel + ); + Check_Fpu(); +} + +void + L4BytePort::DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawFilledRectangle( + color, + 0, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4BytePort::DrawText( + int /*color*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +} + +void + L4BytePort::DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMap( + color, + 0, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4BytePort::DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMapOpaque( + color, + background, + 0, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); +} + +void + L4BytePort::DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8( + NULL, + 0, + operation, + opaque, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4BytePort::DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8SingleColor( + color, + 0, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4BytePort::convertPortPair( + int *xp, + int *yp, + int x, + int y + ) +{ + switch(baseRotation) + { + default: + *xp = x; + *yp = y; + break; + + case 90: + *xp = y; + *yp = maximumY - x; + break; + + case 180: + *xp = maximumX - x; + *yp = maximumY - y; + break; + + case 270: + *xp = maximumX - y; + *yp = x; + break; + } + Check_Fpu(); +} + + + + + + + + + + diff --git a/CODE/RP/MUNGA_L4/L4VB8.HPP b/CODE/RP/MUNGA_L4/L4VB8.HPP new file mode 100644 index 0000000..9d95b25 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VB8.HPP @@ -0,0 +1,278 @@ +//===========================================================================// +// File: L4V16.hpp // +// Project: MUNGA Brick: Applications-specific controls module // +// Contents: Interface specification for 16-bit video display // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 02/08/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4VB8_HPP) +# define L4VB8_HPP + +# if !defined(GRAPH2D_HPP) +# include +# endif + + //######################################################################## + //######################### Video8BitBuffered ########################### + //######################################################################## + // + // X/Y values passed to these routines are assumed to be in + // the VIDEO DISPLAY COORDINATE SYSTEM, with (0,0) at the top left. + // + class Video8BitBuffered : + public GraphicsDisplay + { + public: + Video8BitBuffered(int x, int y); + Video8BitBuffered(PixelMap8 *pixel_map); + + ~Video8BitBuffered(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + protected: + void + MarkChangedLines(int screenTop, int screenBottom); + + void + buildDestPointer( + int x, int y, + Byte **pixelPointer + ); + + Logical + valid, + createdPixelmap; + int + width, + height, + maximumX, + maximumY; + + public: + PixelMap8 + *pixelBuffer; + protected: + Word + *changedLine; + }; + + + //######################################################################## + //########################## L4BytePort ############################## + //######################################################################## + // + // X/Y values passed to these routines are assumed to be in + // the GRAPHICS COORDINATE SYSTEM, with (0,0) at the bottom left. + // + class L4BytePort : + public GraphicsPort + { + public: + L4BytePort( + Video8BitBuffered *graphics_display, + const char *name, + int rotation + ); + + ~L4BytePort(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + DrawPoint( + int color, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + protected: + void + convertPortPair( + int *xp, + int *yp, + int x, + int y + ); + + //------------------------------------------------------------ + // Protected data + //------------------------------------------------------------ + int + baseRotation, + maximumX, + maximumY; + }; + +#endif diff --git a/CODE/RP/MUNGA_L4/L4VIDEO.CPP b/CODE/RP/MUNGA_L4/L4VIDEO.CPP new file mode 100644 index 0000000..959aaa2 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VIDEO.CPP @@ -0,0 +1,6708 @@ +//===========================================================================// +// File: l4video.cpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +// 07/11/95 KEO Modify video resource format. // +// 02/08/96 KEO Add rubble entry to video resource. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995-1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(DOOR_HPP) +# include +#endif + +#if !defined(DOORFRAM_HPP) +# include +#endif + +#if !defined(EYECANDY_HPP) +# include +#endif + +#if !defined(L4VIDRND_HPP) +# include +#endif + +#if !defined(L4VIDEO_HPP) +# include +#endif + +#if !defined(MATRIX_HPP) +# include +#endif + +#if !defined(MOVER_HPP) +# include +#endif + +#if !defined(JMOVER_HPP) +# include +#endif + +#if !defined(PLAYER_HPP) +# include +#endif + +#if !defined(CAMSHIP_HPP) +# include +#endif + +#if !defined(DIRECTOR_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(CULTURAL_HPP) +# include +#endif + +#if !defined(NTTMGR_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#include + +// +// Includes for the DPL libraries +// +#include +#include +#include +#include +#include +// +// You can enable or disable these traces here for quicker rebuilding during +// profile testing, but for production they should be all turned off! +// +//#define TRACE_VIDEO_CULL_SETUP +//#define TRACE_VIDEO_VEHICLE_RENDERABLES +// #define TRACE_VIDEO_ALL_RENDERABLES +// +// These are other traces you can use to extract data +// +#if defined(TRACE_VIDEO_LOAD_OBJECT) + static BitTrace Video_Load_Object("Video Load Object"); + #define SET_VIDEO_LOAD_OBJECT() Video_Load_Object.Set() + #define CLEAR_VIDEO_LOAD_OBJECT() Video_Load_Object.Clear() +#else + #define SET_VIDEO_LOAD_OBJECT() + #define CLEAR_VIDEO_LOAD_OBJECT() +#endif + +#if defined(TRACE_VIDEO_CONSTRUCT_ROOT) + static BitTrace Video_Construct_Root("Video Construct Root"); + #define SET_VIDEO_CONSTRUCT_ROOT() Video_Construct_Root.Set() + #define CLEAR_VIDEO_CONSTRUCT_ROOT() Video_Construct_Root.Clear() +#else + #define SET_VIDEO_CONSTRUCT_ROOT() + #define CLEAR_VIDEO_CONSTRUCT_ROOT() +#endif +// +// This is the time spent fetching and processing the pickpoint information +// from the DPL renderer. +// +#if defined(TRACE_VIDEO_PICKPOINT) + static BitTrace Video_Pickpoint("Video Pickpoint"); + #define SET_VIDEO_PICKPOINT() Video_Pickpoint.Set() + #define CLEAR_VIDEO_PICKPOINT() Video_Pickpoint.Clear() +#else + #define SET_VIDEO_PICKPOINT() + #define CLEAR_VIDEO_PICKPOINT() +#endif +// +// Traces the time spent setting up the video culling parameters +// +#if defined(TRACE_VIDEO_CULL_SETUP) + static BitTrace Video_Cull_Setup("Video Cull Setup"); +# define SET_VIDEO_CULL_SETUP() Video_Cull_Setup.Set() +# define CLEAR_VIDEO_CULL_SETUP() Video_Cull_Setup.Clear() +#else +# define SET_VIDEO_CULL_SETUP() +# define CLEAR_VIDEO_CULL_SETUP() +#endif +// +// This trace covers the entire time spent executing renderables as one +// transition. It goes up when the execute implimentation starts running +// over the all iterator and goes down when it's done. +// +#if defined(TRACE_VIDEO_RENDERABLES) + static BitTrace Video_Renderables("Video Renderables"); + #define SET_VIDEO_RENDERABLES() Video_Renderables.Set() + #define CLEAR_VIDEO_RENDERABLES() Video_Renderables.Clear() +#else + #define SET_VIDEO_RENDERABLES() + #define CLEAR_VIDEO_RENDERABLES() +#endif +// +// Traces time spent executing renderables that belong to a vehicle entity +// (currently Mech, VTV or BTPlayer) +// +#if defined(TRACE_VIDEO_VEHICLE_RENDERABLES) + static BitTrace Video_Vehicle_Renderables("Video Vehicle Renderables"); +# define SET_VIDEO_VEHICLE_RENDERABLES() Video_Vehicle_Renderables.Set() +# define CLEAR_VIDEO_VEHICLE_RENDERABLES() Video_Vehicle_Renderables.Clear() +#else +# define SET_VIDEO_VEHICLE_RENDERABLES() +# define CLEAR_VIDEO_VEHICLE_RENDERABLES() +#endif +// +// This trace will transition as each individual renderable is executed. +// It will buzz and cause serious impact to the accuracy of the trace but is +// good for identifying time-eating individual renderables +// +#if defined(TRACE_VIDEO_ALL_RENDERABLES) + static BitTrace Video_All_Renderables("Video All Renderables"); +# define SET_VIDEO_ALL_RENDERABLES() Video_All_Renderables.Set() +# define CLEAR_VIDEO_ALL_RENDERABLES() Video_All_Renderables.Clear() +#else +# define SET_VIDEO_ALL_RENDERABLES() +# define CLEAR_VIDEO_ALL_RENDERABLES() +#endif +// +// This is the routine that does a DPL_FlushArticulations on the batch of +// DCS's that we've been holding during rendering, flushing them all to +// the card in a big batch +// +#if defined(TRACE_VIDEO_BATCH_FLUSH) + static BitTrace Video_Batch_Flush("Video Batch Flush"); +# define SET_VIDEO_BATCH_FLUSH() Video_Batch_Flush.Set() +# define CLEAR_VIDEO_BATCH_FLUSH() Video_Batch_Flush.Clear() +#else +# define SET_VIDEO_BATCH_FLUSH() +# define CLEAR_VIDEO_BATCH_FLUSH() +#endif +// +// This trace shows the time spent doing the "frame done" processing where the +// renderer waits for the DPL card to become ready and then issues a command +// to start the scene drawing. An additional batch flush can happen here. +// If USE_ONE_VIDEO_TRACE is turned on, data from this trace will show up as +// part of the Video_Renderer trace. +// +#if defined(TRACE_VIDEO_RENDERER_FRAME_DONE) +# if defined(USE_ONE_VIDEO_TRACE) +# define SET_VIDEO_RENDERER_FRAME_DONE() Video_Renderer.Set() +# define CLEAR_VIDEO_RENDERER_FRAME_DONE() Video_Renderer.Clear() +# else + static BitTrace Video_Renderer_Frame_Done("Video Renderer Frame Done"); +# define SET_VIDEO_RENDERER_FRAME_DONE() Video_Renderer_Frame_Done.Set() +# define CLEAR_VIDEO_RENDERER_FRAME_DONE() Video_Renderer_Frame_Done.Clear() +# endif +#else +# define SET_VIDEO_RENDERER_FRAME_DONE() +# define CLEAR_VIDEO_RENDERER_FRAME_DONE() +#endif +// +// The following traces are specifically designed for profileing the low level +// DPL routines in Division's libraries. You need to link to a special "profile" +// version of the division libraries for these to work. If you enable them +// with a production libdpl you will get NO traces. If you disable them and +// try to link to a profile version of libdpl you will get link errors. Sorry +// but this is the most efficient way of connecting the c++ trace routines to +// the C code of division's libraries. +// +// There are switches in the DPL libraries that handle turning these functions +// on and off in the profile version. +// +//#define TRACE_DPL_LOAD_OBJECT +//#define TRACE_DPL_TRANSPUTER_LINK // will buzz +//#define TRACE_DPL_DO_OUTSW // will buzz +//#define TRACE_DPL_OUTINT32 // will buzz + +#if defined(TRACE_DPL_LOAD_OBJECT) + static BitTrace DPL_Load_Object("DPL Load Object"); + + extern "C" + { + void Set_DPL_Load_Object(); + void Clear_DPL_Load_Object(); + } + + void + Set_DPL_Load_Object() + { + DPL_Load_Object.Set(); + } + + void + Clear_DPL_Load_Object() + { + DPL_Load_Object.Clear(); + } +#endif + +#if defined(TRACE_DPL_TRANSPUTER_LINK) + static BitTrace DPL_Transputer_Link("DPL Transputer Link"); + + extern "C" + { + void Set_DPL_Transputer_Link(); + void Clear_DPL_Transputer_Link(); + } + + void + Set_DPL_Transputer_Link() + { + DPL_Transputer_Link.Set(); + } + + void + Clear_DPL_Transputer_Link() + { + DPL_Transputer_Link.Clear(); + } +#endif + +#if defined(TRACE_DPL_DO_OUTSW) + static BitTrace DPL_do_outsw("DPL do_outsw"); + + extern "C" + { + void Set_DPL_do_outsw(); + void Clear_DPL_do_outsw(); + } + + void + Set_DPL_do_outsw() + { + DPL_do_outsw.Set(); + } + + void + Clear_DPL_do_outsw() + { + DPL_do_outsw.Clear(); + } +#endif + +#if defined(TRACE_DPL_OUTINT32) + static BitTrace DPL_outint32("DPL outint32"); + + extern "C" + { + void Set_DPL_outint32(); + void Clear_DPL_outint32(); + } + + void + Set_DPL_outint32() + { + DPL_outint32.Set(); + } + + void + Clear_DPL_outint32() + { + DPL_outint32.Clear(); + } +#endif + +// +// The following trace will probably be obsolete soon +// + +#if 0 +#if defined(TRACE_VIDEO_FIRST_FRAME_DONE) + static BitTrace Video_First_Frame_Done("Video First Frame Done"); +# define SET_VIDEO_FIRST_FRAME_DONE() Video_First_Frame_Done.Set() +# define CLEAR_VIDEO_FIRST_FRAME_DONE() Video_First_Frame_Done.Clear() +#else +# define SET_VIDEO_FIRST_FRAME_DONE() +# define CLEAR_VIDEO_FIRST_FRAME_DONE() +#endif +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Definitions of various debugging switches +// +#define DEBUG_SPECIAL_CALLBACK 0 // 0 = none, 1 = print special, 2 = real noisy +#define DEBUG_CREATE_CALLBACK 0 // 0 = none, +#define PRINT_THE_PFX False // Set to true and the pfx definition will print when it is read in. +#define RAPID_SECT_PIXEL True // True if you want to use the rapidsectpixel call for intersections +#define PARTICLE_TEST False // True to issue a stream of particles at the detected intersect point +#define PRINT_PICKPOINT_TEST False // True to print data whenever the intersect changes +#define NOISY_RENDERER False // True enables a lot of printouts as the renderer makes/kills object +#define USE_TRACKER_STRUCTURE False // True to enable the full tracker structure that holds damage zone names & such +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Definitions of system constants used only in this file +// +#define MAX_SPECIAL_ARGUMENTS 25 // Maximum number of arguments a "special" callback can handle +#define MAX_SPECIAL_SIZE 512 // Maximum size (characters) of a "special" +#define dpl_arg_sep '~' // seperator used when parsing dpl argument string +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity + *Entity_Being_Created = 0; // !!! temp, till callback handlers become a class +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// These extern "c" routines and constants are from startdpl or from dpl +// itself and need to be here. +// +extern "C" { + extern const int + x_size, // x size of the screen (from startdpl) + y_size; // y size of the screen (startdpl) + void + dpl_TexmapTexels2D ( // A routine from DPL we normally couldn't access + dpl_TEXMAP *tm, + uint32 *texels, + int32 u_size, + int32 v_size, + int32 bytes_per_texel); + int + screen_resolution( // Sets up the screen resolution (startdpl) + char *dpl_argv ), + explode_args( // Parses DPLARG system environmental (startdpl) + char **argv, + char *dpl_args, + char sep ); + char + *dpl_TypeToString( // Converts a DPL type code into a string (libdpl) + dpl_TYPE t); + int32 + dpl_DrawSceneComplete(void); // missing definition (libdpl) +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// see DPLReportPerfStats() +extern "C" const int32 __sect_time; +extern "C" const int32 __last_cull_time; +extern "C" const int32 __last_draw_time; +extern "C" const int32 __last_frame_time; +extern "C" const int32 __last_pxpl_time; +extern "C" const int32 __last_frame_prims; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// dump_frame_buffer() declaration +void dump_frame_buffer( + dpl_VIEW *eye, + int32 x_size, + int32 y_size, + Logical antialias); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following are definitions of DPL callback functions. These are called +// by the dpl file loader as it is loading graphics files so we can do material +// substitution and set special attributes on geometry & such. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The "special" callback is called whenever a "special" field is processed in +// incomming geometry. +// dPL special callback function type. +// typedef void (dpl_SPECIAL_CALLBACK)(dpl_TYPE type, void *handle, +// char8 *special, uint32 special_len); + +static void + TestSpecialCallBack( + dpl_TYPE type, + void *handle, + char8 *special, + uint32 special_len) +{ + char + *args[MAX_SPECIAL_ARGUMENTS], + **argptr, + *argstring; + int + argcount; + float + u0, + v0, + du, + dv; + int32 + immunity; + char +// NameBuff[80], + TempBuff[MAX_SPECIAL_SIZE + 1]; + #if USE_TRACKER_STRUCTURE + dpl_tracker + *this_tracker; + #endif + + if(special_len > MAX_SPECIAL_SIZE) + { + DEBUG_STREAM<<"SPECIAL was bigger than "< MAX_SPECIAL_SIZE); + } + strncpy(TempBuff, special,special_len); + TempBuff[special_len] = 0; + if(TempBuff[special_len-1] != 0) + { + DEBUG_STREAM<<"Caution, the following SPECIAL was not null terminated\n"; + printf("SPECIAL->%08x: %s, %s\n", handle, dpl_TypeToString(type), TempBuff); + } + #if DEBUG_SPECIAL_CALLBACK >= 1 + printf("SPECIAL->%08x: %s, %s\n", handle, dpl_TypeToString(type), TempBuff); + #endif +// +// Scan all the argument start points into an array for easier processing. +// also avoids non-reentrand problem with strtok +// + argstring = TempBuff; + for(argcount = 0; argcount= 2 + Tell("Calling SetObjectAdditiveLODs on an object\n"); + #endif + // REMOVE dpl_SetObjectAdditiveLODs to run with older renderers + dpl_SetObjectAdditiveLODs ( (dpl_OBJECT *)handle); + } + } + break; + case dpl_type_lod: + break; + case dpl_type_geogroup: + #if USE_TRACKER_STRUCTURE + this_tracker = (dpl_tracker *)dpl_GetAppSpecific(handle); + #endif + for(argptr = args; + *argptr; + argptr++) + { + if (strncmp(*argptr, "dz_", 3) == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL GEOGROUP Damage zone "); + #endif + + #if USE_TRACKER_STRUCTURE + if (this_tracker) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("marked\n"); + #endif + strncpy(this_tracker->dz_name, *argptr, MAX_DZ_NAME_LENGTH); + this_tracker->dz_name[MAX_DZ_NAME_LENGTH - 1] = 0; + #endif + //--------------------------------------------- + // lookup damage zone index in global namelist + //--------------------------------------------- + if (Entity_Being_Created->damageZones) + { + Check_Pointer(Entity_Being_Created->damageZones); + + int + damage_zone_index; + + damage_zone_index = + Entity_Being_Created->GetDamageZoneIndex(*argptr); + + if (damage_zone_index != -1) + { + #if USE_TRACKER_STRUCTURE + this_tracker->Damage_Zone_Number = damage_zone_index; + #else + if(dpl_GetAppSpecific(handle)) + Fail("AppSpecific already set\n"); + dpl_PutAppSpecific(handle, (void *)(damage_zone_index+1)); + #endif + } + else + { + DEBUG_STREAM << endl << "Damage zone '" << + *argptr << "' not in table." << endl; + } + } + #if USE_TRACKER_STRUCTURE + } + else + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("NOT marked\n"); + #endif + } + #endif + } + else if(strcmp(*argptr,"PUNCH") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL GEOGROUP Punchize\n"); + #endif + dpl_Punchize((dpl_GEOGROUP *)handle); + } + else if(strcmp(*argptr,"DAMAGE") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL GEOGROUP damagize\n"); + #endif + if(*(++argptr)) + { + int + status; + dpl_MATERIAL *damagize_material = dpl_LookupMaterial ( *argptr, dpl_lookup_normal, &status ); + if(damagize_material) + { + dpl_Damagize((dpl_GEOGROUP *)handle, damagize_material); + } + else + { + DEBUG_STREAM<<"SPECIAL GEOGROUP DAMAGE couldn't find material "<<*argptr<<"\n"; + Verify(damagize_material); + } + } + else + { + DEBUG_STREAM<<"SPECIAL GEOGROUP DAMAGE no material name \n"; + Verify(*argptr); + } + } + else if(strcmp(*argptr,"WIREFRAME") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL GEOGROUP WIREFRAME\n"); + #endif + dpl_SetGeogroupWireframe((dpl_GEOGROUP *)handle, True); + } + else if(strcmp(*argptr,"GEOMETRIZE") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL GEOGROUP geometrize\n"); + #endif + if(*(++argptr)) + { + dpl_GEOMETRY + *geometry_ptr; + long + geometrize_code; + int + geometry_id = 0; + sscanf( + *argptr, + "%lx", + &geometrize_code); + do + { + geometry_ptr = dpl_GetGeogroupGeometry((dpl_GEOGROUP *)handle,geometry_id); + if(geometry_ptr) + { + dpl_Geometrize(geometry_ptr,geometrize_code); + } + geometry_id++; + } while(geometry_ptr); + } + else + { + DEBUG_STREAM<<"SPECIAL GEOGROUP GEOMETRIZE has no geometrize code\n"; + Verify(*argptr); + } + } + else if(strcmp(*argptr,"DRAWLAST") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL GEOGROUP DRAWLAST\n"); + #endif + dpl_SetGeogroupDrawLast((dpl_GEOGROUP *)handle, True); + dpl_FlushGeogroup((dpl_GEOGROUP *)handle); + } + else if(strcmp(*argptr,"BLINK") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("SPECIAL GEOGROUP BLINK is not supported\n"); + #endif + } + else + { + DEBUG_STREAM<<"SPECIAL GEOGROUP "<<*argptr<<" is not a geogroup modifier\n"; + } + } + break; + case dpl_type_geometry: + break; + case dpl_type_material: + for(argptr = args; + *argptr; + argptr++) + { + if(strcmp(*argptr,"IMMUNE") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL MATERIAL IMMUNE\n"); + #endif + if(*(++argptr)) + { + immunity = atol(*argptr); + dpl_SetMaterialFogImmunity ( (dpl_MATERIAL *)handle, immunity ); + dpl_FlushMaterial((dpl_MATERIAL *)handle); + } + else + { + DEBUG_STREAM<<"SPECIAL MATERIAL IMMUNE has no immune code\n"; + Verify(*argptr); + } + } + else + { + DEBUG_STREAM<<"SPECIAL MATERIAL "<<*argptr<<" is not a material modifier\n"; + } + } + break; + case dpl_type_texture: + for(argptr = args; + *argptr; + argptr++) + { + if(strcmp(*argptr,"SCROLL") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SCROLL\n"); + #endif + u0 = v0 = du = dv = 0.0; + if(*(++argptr)) + u0 = atof(*argptr); + else + { + DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing u0\n"; + Verify(*argptr); + } + if(*(++argptr)) + v0 = atof(*argptr); + else + { + DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing v0\n"; + Verify(*argptr); + } + if(*(++argptr)) + du = atof(*argptr); + else + { + DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing du\n"; + Verify(*argptr); + } + if(*(++argptr)) + dv = atof(*argptr); + else + { + DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing dv\n"; + Verify(*argptr); + } + dpl_SetTextureScroll ( + (dpl_TEXTURE *)handle, + u0, + v0, + du, + dv); + dpl_FlushTexture((dpl_TEXTURE *)handle); + } + else if(strcmp(*argptr,"FAKESIZE") == 0) + { + #if DEBUG_SPECIAL_CALLBACK >= 2 + Tell("Doing SPECIAL TEXURE FAKESIZE\n"); + #endif + int + size, offset; + if(*(++argptr)) + size = atoi(*argptr); + else + { + DEBUG_STREAM<<"SPECIAL TEXTURE FAKESIZE missing size\n"; + Verify(*argptr); + } + if(*(++argptr)) + offset = atoi(*argptr); + else + { + DEBUG_STREAM<<"SPECIAL TEXTURE FAKESIZE missing offset\n"; + Verify(*argptr); + } + dpl_FakeTextureSize((dpl_TEXTURE *)handle,size,offset); + dpl_FlushTexture((dpl_TEXTURE *)handle); + } + else + { + DEBUG_STREAM<<"SPECIAL TEXTURE "<<*argptr<<" is not a texture modifier\n"; + } + } + break; + case dpl_type_texmap: + break; + case dpl_type_ramp: + break; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The TestCreateCallBack callback is called whenever a dpl node of the indicated +// type is created while loading a DPL graphics file. +/* dPL create/delete callback function type. */ +//typedef void (dpl_CREATE_DELETE_CALLBACK)(dpl_TYPE type, void *handle); + +static void + TestCreateCallBack( + dpl_TYPE type, + #if DEBUG_CREATE_CALLBACK>=1 + void *handle + #else + void * + #endif + ) +{ + // + // get a pointer to the node structure (first part of most dpl types) + // + #if DEBUG_CREATE_CALLBACK >=1 + printf("CREATE->%08x: %s\n", handle, dpl_TypeToString(type)); + #endif + switch(type) + { + case dpl_type_error: + break; + case dpl_type_scene: + break; + case dpl_type_zones: + break; + case dpl_type_view: + break; + case dpl_type_instance: + break; + case dpl_type_dcs: + break; + case dpl_type_light: + break; + case dpl_type_object: + break; + case dpl_type_lod: + break; + case dpl_type_geogroup: + #if USE_TRACKER_STRUCTURE + { + dpl_tracker *this_tracker = new dpl_tracker; + this_tracker->This_Entity = Entity_Being_Created; + this_tracker->dz_name[0] = 0; + this_tracker->Damage_Zone_Number = -1; // no damage zone (default) + if(dpl_GetAppSpecific(handle)) + DEBUG_STREAM<<"app_specific hook already set!\n"; + dpl_PutAppSpecific(handle, this_tracker); + + break; + } + #endif + case dpl_type_geometry: + break; + case dpl_type_material: + break; + case dpl_type_texture: + break; + case dpl_type_texmap: + break; + case dpl_type_ramp: + break; + } +} + +//############################################################################# +// Code to setup and handle material substitutions. +//############################################################################# +// +NameList + *materialSubstitutionList = NULL; + +/* dPL material name callback function type. */ +//typedef char8 *(dpl_MATERIAL_NAME_CALLBACK)(char8 *mat_name); +char8* + substituteMaterial( + char8 *source + ) +{ + static char + buffer[MATERIAL_NAME_BUFFER_LENGTH]; + NameList::Entry + *entry; + const char + *search, + *replace, + *pc; + int + len; + //---------------------------------------------- + // perform text substitution + // first match in the sub list gets substituted + // materialSubstitutionList is a pre-prepared global namelist. + //---------------------------------------------- + entry = materialSubstitutionList->GetFirstEntry(); + while (entry) + { + search = entry->GetName(); + if (search && *search && (pc = strstr(source, search)) != NULL) + { + replace = entry->GetChar(); + *buffer = '\0'; + + len = pc - source; + while (*replace == '<') + { + ++replace; + --len; + } + if (len > 0) + { + strncat(buffer, source, len); + } + + pc += strlen(search); + len = strlen(replace); + while (len && *(replace+len-1) == '>') + { + --len; + if (*pc) { ++pc; } + } + if (len > 0) + { + strncat(buffer, replace, len); + } + + Str_Cat(buffer, pc, MATERIAL_NAME_BUFFER_LENGTH); + Str_Copy(source, buffer, MATERIAL_NAME_BUFFER_LENGTH); + break; + } + entry = entry->GetNextEntry(); + } + return source; +} +//----------------------------------------------------------------------------- +//--------------------------DPL video resource object-------------------------- +//----------------------------------------------------------------------------- +//############################################################################# +//############################ L4VideoObject ############################ +//############################################################################# + +L4VideoObject::L4VideoObject( + const char *filename, + ResourceType resource_type, + Enumeration renderer_modes, // RendererModes + float blink_period, + float percent_time_on +) +{ + Check_Pointer(filename); + + Str_Copy(objectFilename, filename, sizeof(objectFilename)); + //--------------------------------------------------------------- + // pad objectFilename with nulls so all .res files are identical + //--------------------------------------------------------------- + char + *p = objectFilename + strlen(filename) + 1, + *c = objectFilename + sizeof(objectFilename); + + for (; p < c; ++p) + { *p = '\0'; } + + resourceType = resource_type; + rendererModes = renderer_modes; + blinkPeriod = blink_period; + percentTimeOn = percent_time_on; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4VideoObject::~L4VideoObject() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4VideoObject::TestInstance() const +{ + Verify( strlen(objectFilename) < sizeof(objectFilename) ); + return True; +} + +//############################################################################# +//######################## L4VideoObjectWrapper ######################### +//############################################################################# + +L4VideoObjectWrapper::L4VideoObjectWrapper( + L4VideoObject *video_object, + Logical delete_object +) +{ + Check_Pointer(video_object); // do not use Check() + + videoObject = video_object; + deleteObject = delete_object; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4VideoObjectWrapper::~L4VideoObjectWrapper() +{ + if (deleteObject) + { + Unregister_Pointer(videoObject); + delete videoObject; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4VideoObjectWrapper::TestInstance() const +{ + if (videoObject) + { + Check_Pointer(videoObject); // do not use Check() + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// static +int + L4VideoObjectWrapper::BuildVideoObjectChainFromResource( + ChainOf *video_chain, + ResourceDescription *video_resource + ) +{ + //do not Check(this) - static + Check(video_chain); + Check(video_resource); + + const char + *video_pointer; + int + object_count, + index; + long + object_size; + L4VideoObject + *video_object; + L4VideoObjectWrapper + *video_wrapper; + + //---------------------------------------------------- + // convert video resource into chain of video objects + //---------------------------------------------------- + video_pointer = (char *)video_resource->resourceAddress; + Check_Pointer(video_pointer); + + object_count = *((int *)video_pointer); + video_pointer += sizeof(int); + + object_size = sizeof(L4VideoObject); + Verify( video_resource->resourceSize == sizeof(int) + object_count * object_size ); + + //Tell("video chain: ("<GetObjectFilename()<<"' 0x"<GetRendererModes()); + + video_wrapper = new L4VideoObjectWrapper(video_object, False); + Register_Object(video_wrapper); + + video_chain->Add(video_wrapper); + } + + //Tell(dec<<"\n"); + + return object_count; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// static +void + L4VideoObjectWrapper::DeleteVideoObjectChain( + ChainOf *video_chain + ) +{ + //do not Check(this) - static + Check(video_chain); + + ChainIteratorOf + video_iterator(video_chain); + L4VideoObjectWrapper + *video_wrapper; + + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + Check(video_wrapper); + + Unregister_Object(video_wrapper); + delete video_wrapper; + } + return; +} + +//----------------------------------------------------------------------------- +//-------------------Actual DPL video renderer starts below-------------------- +//----------------------------------------------------------------------------- + +UserHeap* DPLRenderer::DPLHeap = NULL; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLRenderer +// +DPLRenderer::DPLRenderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration +): + VideoRenderer( + calibration_rate, + calibration_complexity, + calibration_priority, + interest_type, + depth_calibration + ), + projectile_list(NULL), + dplObjectCacheSocket(NULL, False), + dplJointToDCSTranslatorSocket(NULL,False), + dplRenderableSocket(NULL) +{ + char + Eye_Type[50], + *Eye_Arg, // Controls generation of the eye point + *DPL_Arg; // Points to DPLARG environment pointer once we get it + int + psfx_number; +// int +// i; // Temporary loop counter + float + eye_x, + eye_y, + eye_z, + eye_x_rot, + eye_y_rot, + eye_z_rot; +// +// Initialize a bunch of the variables to their starting values +// + eyeRelative = False; + completeCycleNeeded = False; + lastAppState = 0; + fogUpdating = True; + fogRed = 0.0f; + fogBlue = 0.0f; + fogGreen = 0.0f; + fogNear = 0.0f; + fogFar = 0.0f; + searchLightFogRed = 0.0f; + searchLightFogGreen = 0.0f; + searchLightFogBlue = 0.0f; + searchLightFogNear = 0.0f; + searchLightFogFar = 0.0f; + noSearchLightFogRed = 0.0f; + noSearchLightFogGreen = 0.0f; + noSearchLightFogBlue = 0.0f; + noSearchLightFogNear = 0.0f; + noSearchLightFogFar = 0.0f; + clipNear = 0.0f; + clipFar = 0.0f; + backgroundRed = 0.0f; + backgroundGreen = 0.0f; + backgroundBlue = 0.0f; + viewAngle = 30.0f; + dplMainView = NULL; + dplDeathZone = NULL; + dplMainZone = NULL; + vehicleReticle = NULL; + dplHitInstance = NULL; + dplHitDCS = NULL; + dplHitGeoGroup = NULL; + dplHitGeometry = NULL; + delayedDCSCount = 0; + myUniqueID = 0; + ambientLight = NULL; + sceneLightDCS = NULL; + sceneLight = NULL; + sceneLightCount = 0; + + worldToEyeMatrix = LinearMatrix::Identity; // the current world to eye transform for our linked entity + currentFrameTime = Now(); // the time at the start of renderable execution + + Verify(!DPLHeap); + DPLHeap = new UserHeap("DPL Heap", 2000000); + Register_Object(DPLHeap); + + // + // Clear the myPSFXDescriptons array to all zeros so we can detect attempts + // to use uninitialized items. + // + for( psfx_number = 0; psfx_number < MAX_PSFX_COUNT; psfx_number++) + { + myPSFXDescriptons[psfx_number] = NULL; + } +// +// These guys will come out of a world environment variable eventually +// + eye_x = 0.0f; + eye_y = 10.0f; + eye_z = 0.0f; + eye_x_rot = 0.0f; + eye_y_rot = 0.0f; + eye_z_rot = 0.0f; +// +// Get pointers to environmentals containing DPL startup arguments and +// eye positioning information. If L4EYES is present set the renderer +// variable that controls the hooking up of the eye position. +// + Eye_Type[0] = 0; + DPL_Arg = getenv("DPLARG"); + Eye_Arg = getenv("L4EYES"); + if(Eye_Arg) + { + sscanf( + Eye_Arg, + "%f %f %f %f %f %f %s", + &eye_x, + &eye_y, + &eye_z, + &eye_x_rot, + &eye_y_rot, + &eye_z_rot, + Eye_Type); + + printf("%f, %f, %f %f, %f, %f\n", + eye_x, + eye_y, + eye_z, + eye_x_rot, + eye_y_rot, + eye_z_rot); + + Disconnected_Eye = True; // tells vidrend:: to request outside view of linked entity + if(*Eye_Type == 'r') + { + DEBUG_STREAM<<"DPLRenderer::DPLRenderer Eye will be offset relative to vehicle\n"; + eyeRelative = True; + } + } +// +// If the argument was empty, we can't render !!! should exit sensiblly +// + if(!DPL_Arg) + { + DEBUG_STREAM << "DPLARG must be set for the Division card to come up\n"; + Verify(DPL_Arg); + } +// +// If we're still here, try to interpret and setup the screen resolution +// requested by DPLARG. The screen_resolution function is Phil's routine +// in startdpl. +// + if (screen_resolution ( DPL_Arg ) == 0) + { + DEBUG_STREAM << "DPLARG is bad, I couldn't understand video format\n"; + Verify(DPL_Arg); + } +// +// Breakdown the DPLARGS string using expload_args from startdpl, then feed +// the results to the dpl_Init routine to get DPL up and running. +// + char *argv[32]; + int argc = explode_args ( argv, DPL_Arg, dpl_arg_sep ); + dpl_Init ( argc, argv ); + // + // Setup the file paths for geometry and texture loading + // +// dpl_SetObjectFilePath ( ".\\video", "\\video", "..\\video" ); +// dpl_SetTexmapFilePath ( ".\\video", "\\video", "..\\video" ); +// dpl_SetMaterialFilePath ( ".\\video", "\\video", "..\\video" ); +// dpl_SetObjectFilePath ( ".\\video", "", "" ); +// cout<tex = dpl_LookupTexture ( cp, dpl_lookup_normal, &status ); + #if PRINT_THE_PFX + printf ( "texture => %s\n", cp ); + #endif + // + // The remander of these statements get the rest of the PFX data + // + cp = fgets ( line, 255, fp ); + status = sscanf ( cp, + "%x %d %f %f\n", + &psfx_info->identifier, &psfx_info->maximum_issue, &psfx_info->release_period, &psfx_info->rate ); + if(status < 4) + { + cout<<"pfx file "<px, &psfx_info->py, &psfx_info->pz, &psfx_info->pv ); + if(status < 4) + { + cout<<"pfx file "<velx, &psfx_info->vely, &psfx_info->velz, + &psfx_info->velxv, &psfx_info->velyv, &psfx_info->velzv ); + if(status < 6) + { + cout<<"pfx file "<rad, &psfx_info->radv, &psfx_info->exp, &psfx_info->expv, &psfx_info->dexp, &psfx_info->dexpv ); + if(status < 6) + { + cout<<"pfx file "<accelx, &psfx_info->accely, &psfx_info->accelz, + &psfx_info->accelxv, &psfx_info->accelyv, &psfx_info->accelzv ); + if(status < 6) + { + cout<<"pfx file "<atten, &psfx_info->attenv ); + if(status < 2) + { + cout<<"pfx file "<sRi,&psfx_info->sGi,&psfx_info->sBi,&psfx_info->sAi,&psfx_info->sRiv,&psfx_info->sGiv,&psfx_info->sBiv,&psfx_info->sAiv ); + if(status < 8) + { + cout<<"pfx file "<sRo,&psfx_info->sGo,&psfx_info->sBo,&psfx_info->sAo,&psfx_info->sRov,&psfx_info->sGov,&psfx_info->sBov,&psfx_info->sAov ); + if(status < 8) + { + cout<<"pfx file "<eRi,&psfx_info->eGi,&psfx_info->eBi,&psfx_info->eAi,&psfx_info->eRiv,&psfx_info->eGiv,&psfx_info->eBiv,&psfx_info->eAiv ); + if(status < 8) + { + cout<<"pfx file "<eRo,&psfx_info->eGo,&psfx_info->eBo,&psfx_info->eAo,&psfx_info->eRov,&psfx_info->eGov,&psfx_info->eBov,&psfx_info->eAov ); + if(status < 8) + { + cout<<"pfx file "<colour_warp, &psfx_info->alpha_warp ); + if(status < 2) + { + cout<<"pfx file "<dur, &psfx_info->durv ); + if(status < 2) + { + cout<<"pfx file "<\n" ); + /*{{{ trace the psfx*/ + printf ( "psfx_info->tex = 0x%x\n", + psfx_info->tex ); + printf ( "identifier = 0x%x ", + psfx_info->identifier ); + printf ( "maximum_issue = %d ", + psfx_info->maximum_issue ); + printf ( "release_period = %f\n", + psfx_info->release_period ); + printf ( "rate = %f ", + psfx_info->rate ); + printf ( "px = %f ", + psfx_info->px ); + printf ( "py = %f ", + psfx_info->py ); + printf ( "pz = %f ", + psfx_info->pz ); + printf ( "pv = %f\n", + psfx_info->pv ); + printf ( "velx = %f ", + psfx_info->velx ); + printf ( "vely = %f ", + psfx_info->vely ); + printf ( "velz = %f\n", + psfx_info->velz ); + printf ( "velxv = %f ", + psfx_info->velxv ); + printf ( "velyv = %f ", + psfx_info->velyv ); + printf ( "velzv = %f\n", + psfx_info->velzv ); + printf ( "rad = %f ", + psfx_info->rad ); + printf ( "radv = %f\n", + psfx_info->radv ); + printf ( "exp = %f ", + psfx_info->exp ); + printf ( "expv = %f ", + psfx_info->expv ); + printf ( "dexp = %f ", + psfx_info->dexp ); + printf ( "dexpv = %f\n", + psfx_info->dexpv ); + printf ( "accelx = %f ", + psfx_info->accelx ); + printf ( "accely = %f ", + psfx_info->accely ); + printf ( "accelz = %f ", + psfx_info->accelz ); + printf ( "accelxv = %f ", + psfx_info->accelxv ); + printf ( "accelyv = %f ", + psfx_info->accelyv ); + printf ( "accelzv = %f\n", + psfx_info->accelzv ); + printf ( "atten = %f ", + psfx_info->atten ); + printf ( "attenv = %f\n", + psfx_info->attenv ); + printf ( "sRi = %f ", + psfx_info->sRi ); + printf ( "sGi = %f ", + psfx_info->sGi ); + printf ( "sBi = %f ", + psfx_info->sBi ); + printf ( "sAi = %f\n", + psfx_info->sAi ); + printf ( "sRiv = %f ", + psfx_info->sRiv ); + printf ( "sGiv = %f ", + psfx_info->sGiv ); + printf ( "sBiv = %f ", + psfx_info->sBiv ); + printf ( "sAiv = %f\n", + psfx_info->sAiv ); + printf ( "sRo = %f ", + psfx_info->sRo ); + printf ( "sGo = %f ", + psfx_info->sGo ); + printf ( "sBo = %f ", + psfx_info->sBo ); + printf ( "sAo = %f\n", + psfx_info->sAo ); + printf ( "sRov = %f ", + psfx_info->sRov ); + printf ( "sGov = %f ", + psfx_info->sGov ); + printf ( "sBov = %f ", + psfx_info->sBov ); + printf ( "sAov = %f\n", + psfx_info->sAov ); + printf ( "eRi = %f ", + psfx_info->eRi ); + printf ( "eGi = %f ", + psfx_info->eGi ); + printf ( "eBi = %f ", + psfx_info->eBi ); + printf ( "eAi = %f\n", + psfx_info->eAi ); + printf ( "eRiv = %f ", + psfx_info->eRiv ); + printf ( "eGiv = %f ", + psfx_info->eGiv ); + printf ( "eBiv = %f ", + psfx_info->eBiv ); + printf ( "eAiv = %f\n", + psfx_info->eAiv ); + printf ( "eRo = %f ", + psfx_info->eRo ); + printf ( "eGo = %f ", + psfx_info->eGo ); + printf ( "eBo = %f ", + psfx_info->eBo ); + printf ( "eAo = %f\n", + psfx_info->eAo ); + printf ( "eRov = %f ", + psfx_info->eRov ); + printf ( "eGov = %f ", + psfx_info->eGov ); + printf ( "eBov = %f ", + psfx_info->eBov ); + printf ( "eAov = %f\n", + psfx_info->eAov ); + printf ( "colour_warp = %f ", + psfx_info->colour_warp ); + printf ( "alpha_warp = %f ", + psfx_info->alpha_warp ); + printf ( "dur = %f ", + psfx_info->dur ); + printf ( "durv = %f\n", + psfx_info->durv ); + #endif + return(psfx_info); +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// New INI file handler +// routine to read in an environment from a notation file and setup lights, +// spfx and such... +// +void + DPLRenderer::DPLReadINIPage( + NotationFile *master_notation_file, + const char *starting_page_name, + Mission *mission, + Logical debug_printing) +{ + float + red, + green, + blue, + x_rotate, + y_rotate, + z_rotate; + NameList + *cache_namelist, + *light_namelist, + *psfx_namelist, + *specialfx_namelist, + *include_pages, + *path_pages; + NameList::Entry + *entry; + const char + *next_include_page_name, + *TempStringPtr, + *compare_source; + + if (debug_printing) + cout<<"DPLReadINIPage processing "<MakeEntryList(starting_page_name, "objectpath")) != NULL) + { + Register_Object(path_pages); + // + // Recursively process all the include pages + // + for( entry = path_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + dpl_AddToObjectFilePath((char *)entry->dataReference, dpl_path_user); + if (debug_printing) + { + DEBUG_STREAM << "objectpath '" << dpl_GetObjectFilePath() << "'" << endl; + } + } + Unregister_Object(path_pages); + delete path_pages; + } + if ((path_pages = master_notation_file->MakeEntryList(starting_page_name, "texmappath")) != NULL) + { + Register_Object(path_pages); + // + // Recursively process all the include pages + // + for( entry = path_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + dpl_AddToTexmapFilePath((char *)entry->dataReference, dpl_path_user); + if (debug_printing) + { + DEBUG_STREAM << "texmappath '" << dpl_GetTexmapFilePath() << "'" << endl; + } + } + Unregister_Object(path_pages); + delete path_pages; + } + if ((path_pages = master_notation_file->MakeEntryList(starting_page_name, "materialpath")) != NULL) + { + Register_Object(path_pages); + // + // Recursively process all the include pages + // + for( entry = path_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + dpl_AddToMaterialFilePath((char *)entry->dataReference, dpl_path_user); + if (debug_printing) + { + DEBUG_STREAM << "materialpath '" << dpl_GetMaterialFilePath() << "'" << endl; + } + } + Unregister_Object(path_pages); + delete path_pages; + } + + if (master_notation_file->GetEntry(starting_page_name, "priorityobjectpath", &TempStringPtr)) + { + dpl_AddToObjectFilePath((char *)TempStringPtr, dpl_path_system); + if (debug_printing) + { DEBUG_STREAM << "priorityobjectpath '" << TempStringPtr << "'" << endl; } + } + if (master_notation_file->GetEntry(starting_page_name, "prioritytexmappath", &TempStringPtr)) + { + dpl_AddToTexmapFilePath((char *)TempStringPtr, dpl_path_system); + if (debug_printing) + { DEBUG_STREAM << "prioritytexmappath '" << TempStringPtr << "'" << endl; } + } + if (master_notation_file->GetEntry(starting_page_name, "prioritymaterialpath", &TempStringPtr)) + { + dpl_AddToMaterialFilePath((char *)TempStringPtr, dpl_path_system); + if (debug_printing) + { DEBUG_STREAM << "prioritymaterialpath '" << TempStringPtr << "'" << endl; } + } + // + // Get a the list of dpl objects that should be loaded into cache and load them + // + if ((cache_namelist = master_notation_file->MakeEntryList(starting_page_name, "cache")) != NULL) + { + dpl_OBJECT + *dpl_a_object; + Register_Object(cache_namelist); + for( entry = cache_namelist->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + dpl_a_object = dpl_LoadObject((char *)entry->dataReference, dpl_load_normal); + if(!dpl_a_object) + DEBUG_STREAM<<"Unable to cache "<<(char *)entry->dataReference<<"\n"; + else + { + if(debug_printing) + cout<<"Caching "<<(char *)entry->dataReference<<"\n"; + } + } + Unregister_Object(cache_namelist); + delete cache_namelist; + } + // + // Setup the clip range + // + if(master_notation_file->GetEntry(starting_page_name, "clip" ,&TempStringPtr)) + { + sscanf( + TempStringPtr, + "%f %f", + &clipNear, + &clipFar); + dpl_SetViewClipPlanes ( dplMainView, clipNear, clipFar ); + if(debug_printing) + cout<<"Clip Range "<GetEntry(starting_page_name, "backgnd" ,&TempStringPtr)) + { + sscanf( + TempStringPtr, + "%f %f %f", + &backgroundRed, + &backgroundGreen, + &backgroundBlue); + dpl_SetViewBackGround ( dplMainView, backgroundRed, backgroundGreen, backgroundBlue); + if(debug_printing) + cout<<"Background Color "<GetEntry(starting_page_name, "viewangle" ,&TempStringPtr)) + { + sscanf( + TempStringPtr, + "%f", + &viewAngle); + dpl_SetPipeWindow (0, 0, 0, x_size, y_size); + SetViewAngle(viewAngle); + dpl_SetViewPipe ( dplMainView, 0); + if(debug_printing) + cout<<"View Angle "<GetEntry(starting_page_name, "fog" ,&TempStringPtr)) + { + sscanf( + TempStringPtr, + "%f %f %f %f %f", + &fogNear, + &fogFar, + &fogRed, + &fogGreen, + &fogBlue); + searchLightFogRed = fogRed; + searchLightFogGreen = fogGreen; + searchLightFogBlue = fogBlue; + searchLightFogNear = fogNear; + searchLightFogFar = fogFar; + noSearchLightFogRed = fogRed; + noSearchLightFogGreen = fogGreen; + noSearchLightFogBlue = fogBlue; + noSearchLightFogNear = fogNear; + noSearchLightFogFar = fogFar; + // Force a 0-0 black fog on startup + dpl_SetViewFog (dplMainView, dpl_fog_type_pixel_lin, 0.0, 0.0, 0.0, 0.01, 0.05 ); + if(debug_printing) + cout<<"Fog "<GetEntry(starting_page_name, "nosearchlightfog" ,&TempStringPtr)) + { + sscanf( + TempStringPtr, + "%f %f %f %f %f", + &noSearchLightFogNear, + &noSearchLightFogFar, + &noSearchLightFogRed, + &noSearchLightFogGreen, + &noSearchLightFogBlue); + if(debug_printing) + cout<<"nosearchlightfog "<GetEntry(starting_page_name, "ambient" ,&TempStringPtr)) + { + sscanf( + TempStringPtr, + "%f %f %f ", + &red, + &green, + &blue); + ambientLight = dpl_NewLight(); + Register_Pointer(ambientLight); + + dpl_SetLightType ( ambientLight, dpl_light_type_ambient ); + dpl_SetLightColor ( ambientLight, red, green, blue ); + dpl_FlushLight ( ambientLight ); + if(debug_printing) + cout<<"Ambient Light "<MakeEntryList(starting_page_name, "light")) != NULL) + { + Register_Object(light_namelist); + // + // HACK !!! All the lights must (temporarily) be defined on a single page. + // The lights and their DCS's should really be stored in a light object on + // a chain, or as an actual entity in the simulation. This line will throw + // an exception if this rule is violated + // + if(light_namelist->EntryCount() != 0) + { + if(sceneLightCount != 0) + { + Fail("All lights must be defined on a single INI file page!\n"); + } + // + // Create storage space for the dpl_LIGHT and dpl_DCS structures + // + sceneLightCount = light_namelist->EntryCount(); + if (sceneLightCount) + { + sceneLightDCS = new (dpl_DCS (*[sceneLightCount])); + Register_Pointer(sceneLightDCS); + sceneLight = new (dpl_LIGHT (*[sceneLightCount])); + Register_Pointer(sceneLight); + } + int current_entry(0); + for( entry = light_namelist->GetFirstEntry(); + entry; + entry = entry->GetNextEntry(), ++current_entry) + { + // + // Read the parameters for the light + // + sscanf( + (char *)entry->dataReference, + "%f %f %f %f %f %f", + &red, + &green, + &blue, + &x_rotate, + &y_rotate, + &z_rotate); + if(debug_printing) + cout<<"Light "<<(char *)entry->dataReference<<"\n"; + // + // Create and rotate a dcs to hold the light, and the light itself + // + Verify(current_entry <= sceneLightCount); + sceneLight[current_entry] = dpl_NewLight(); + Register_Pointer(sceneLight[current_entry]); + sceneLightDCS[current_entry] = dpl_NewDCS(); + Register_Pointer(sceneLightDCS[current_entry]); + + dpl_AddDCSToScene ( sceneLightDCS[current_entry] ); + dpl_SetLightType ( sceneLight[current_entry], dpl_light_type_directional ); + dpl_SetLightColor ( sceneLight[current_entry], red, green, blue); + dpl_SetLightDCS ( sceneLight[current_entry], sceneLightDCS[current_entry] ); + dpl_RotateDCS ( sceneLightDCS[current_entry], z_rotate, dpl_Z ); + dpl_RotateDCS ( sceneLightDCS[current_entry], x_rotate, dpl_X ); + dpl_RotateDCS ( sceneLightDCS[current_entry], y_rotate, dpl_Y ); + dpl_FlushLight ( sceneLight[current_entry] ); + dpl_FlushDCS ( sceneLightDCS[current_entry] ); + } + } + // + // Get rid of the light entry list + // + Unregister_Object(light_namelist); + delete light_namelist; + } + // + // Get a the list of PSFX effects we should load into RAM + // + if ((psfx_namelist = master_notation_file->MakeEntryList(starting_page_name, "psfx")) != NULL) + { + const char + *psfx_file_name; + int + psfx_number; + Register_Object(psfx_namelist); + // + // create all the PSFX on the current page + // + for( entry = psfx_namelist->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + psfx_number = atoi(entry->GetName()+4); + psfx_file_name = entry->GetChar(); + if(debug_printing) + cout<<"psfx"< MAX_PSFX_COUNT-1) + { + Fail("PSFX id number was not in the allowed range"); + } + // + // See if we are overwriting an existing psfx + // + if(myPSFXDescriptons[psfx_number]) + { + cout<<"psfx#"<MakeEntryList(starting_page_name, "specialfx")) != NULL) + { + char + *texture_name; + const char + *effect_page_name; + int + status, + spfx_number, + spfx_type, + spfx_count, + spfx_repeats; + float + spfx_size, + spfx_velocity, + spfx_bias, + spfx_y_off, + spfx_cook_r, + spfx_cook_g, + spfx_cook_b, + spfx_varience, + spfx_gravity, + spfx_cool, + spfx_ocool; + dpl_TEXTURE + *effect_texture; + + Register_Object(specialfx_namelist); + // + // create all the effects on the current page + // + for( entry = specialfx_namelist->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + spfx_number = atoi(entry->GetName()+9); + // + // Get the page with this effect on it + // + effect_page_name = entry->GetChar(); + if(debug_printing) + cout<<"specialfx"<GetEntry(effect_page_name, "type", &spfx_type); + master_notation_file->GetEntry(effect_page_name, "size", &spfx_size); + master_notation_file->GetEntry(effect_page_name, "velocity", &spfx_velocity); + master_notation_file->GetEntry(effect_page_name, "v_bias", &spfx_bias); + master_notation_file->GetEntry(effect_page_name, "y_off", &spfx_y_off); + master_notation_file->GetEntry(effect_page_name, "variance", &spfx_varience); + master_notation_file->GetEntry(effect_page_name, "gravity", &spfx_gravity); + master_notation_file->GetEntry(effect_page_name, "count", &spfx_count); + master_notation_file->GetEntry(effect_page_name, "repeats", &spfx_repeats); + master_notation_file->GetEntry(effect_page_name, "cook", &TempStringPtr); + sscanf( + TempStringPtr, + "%f %f %f", + &spfx_cook_r, + &spfx_cook_g, + &spfx_cook_b); + master_notation_file->GetEntry(effect_page_name, "cool", &TempStringPtr); + sscanf( + TempStringPtr, + "%f %f", + &spfx_cool, + &spfx_ocool); + // + // install the effect + // + master_notation_file->GetEntry(effect_page_name, "texture" ,&TempStringPtr); + texture_name = SKIPPY_CAST(char*, TempStringPtr); + effect_texture = dpl_LookupTexture ( texture_name, dpl_lookup_normal, &status ); + + if (effect_texture == NULL) + DEBUG_STREAM<<"couldn't find texture "<MakeEntryList(starting_page_name, "include")) != NULL) + { + Register_Object(include_pages); + // + // Recursively process all the include pages + // + for( entry = include_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + // Get the name of the next include page + next_include_page_name = (char *)entry->dataReference; + // Process the next page recursively through this routine + DPLReadINIPage( + master_notation_file, + next_include_page_name, + mission, + debug_printing); + if(debug_printing) + cout<<"DPLReadINIPage returned to "<GetEntry(starting_page_name, "compare" ,&compare_source)) + { + Logical + match; + NameList + *branch_pages; + CString + compare_strings[10], + wild_card("*"), + token_string, + target_string, + master_compare_string(compare_source); + int + token_count; + ResourceFile + *this_resource_file; + // + // Get a pointer to our resource file so we can find the name of the map + // resource later in this process. + // + Check(application); + this_resource_file = application->GetResourceFile(); + Check(this_resource_file); + // + // Print the compare string + // + if(debug_printing) + cout<<"compare = "<FindResourceDescription(mission->GetMapID()))->resourceName; +// cout<GetMissionTime(); +// cout<GetMissionWeather(); +// cout<GetScenarioName(); +// cout<MakeEntryList(starting_page_name,"branch"); + Register_Object(branch_pages); + for( entry = branch_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + CString + branch_command, + match_string; + int + compare_token; + // + // Get the text of the branch command and print it + // + branch_command = (char *)entry->dataReference; + if(debug_printing) + cout<<"branch = "<GetFileName() << + "' NO MATCH FOUND!!" << endl; + } + } +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Read environment +// routine to read in an environment from a notation file and setup lights, +// spfx and such... +// +void + DPLRenderer::DPLReadEnvironment(Mission *mission) +{ + char + *L4DPLcfg; +// const char +// *cc; + + NotationFile + *renderer_environment; + + Logical + debug_printing; + // + // Get the name of the notation file from an environmental + // + L4DPLcfg = getenv("L4DPLCFG"); + if (!L4DPLcfg) + { + DEBUG_STREAM<<"L4DPLCFG not defined, using dpldflt.ini!\n"; + L4DPLcfg = "dpldflt.ini"; + } + // + // Read the environment out of a notation file + // + renderer_environment = new NotationFile(L4DPLcfg); + Register_Object(renderer_environment); + if (renderer_environment->PageCount() == 0) + { + DEBUG_STREAM<<"Renderer config notation file "<PageCount() == 0); + } + // + // Register the notation file and check it + // + Check(renderer_environment); + if (renderer_environment->PageExists("main")) + { + if (!(renderer_environment->GetLogicalEntry("main", "debug", &debug_printing))) + { + debug_printing=False; + } + DPLReadINIPage( + renderer_environment, + "main", + mission, + debug_printing); +#if 0 + if ((cc = dpl_GetObjectFilePath()) == NULL || *cc == NULL) + { + dpl_SetObjectFilePath ( ".\\video", NULL, NULL ); + } + if ((cc = dpl_GetTexmapFilePath()) == NULL || *cc == NULL) + { + dpl_SetTexmapFilePath ( ".\\video", NULL, NULL ); + } + if ((cc = dpl_GetMaterialFilePath()) == NULL || *cc == NULL) + { + dpl_SetMaterialFilePath ( ".\\video", NULL, NULL ); + } +#endif + } + else + { + if (!(renderer_environment->GetLogicalEntry("dpl_config", "debug", &debug_printing))) + { + debug_printing=False; + } + cout<<"READING OLD FORMAT INI FILE '"<< + renderer_environment->GetFileName()<< + "'---hope this works\n"; + dpl_SetObjectFilePath ( ".\\video", NULL, NULL ); + dpl_SetTexmapFilePath ( ".\\video", NULL, NULL ); + dpl_SetMaterialFilePath ( ".\\video", NULL, NULL ); + DPLReadINIPage( + renderer_environment, + "dpl_config", + mission, + debug_printing); + } + if (debug_printing) + { + DEBUG_STREAM << "ObjectFilePath '" << dpl_GetObjectFilePath() << "'" << endl; + DEBUG_STREAM << "TexmapFilePath '" << dpl_GetTexmapFilePath() << "'" << endl; + DEBUG_STREAM << "MaterialFilePath '" << dpl_GetMaterialFilePath() << "'" << endl; + } + // + // Close the notation file + // + Verify( !renderer_environment->IsDirty() ); + Unregister_Object(renderer_environment); + delete renderer_environment; + // + // Flush all the things we've set/changed here + // + dpl_FlushView ( dplMainView); + return; +} +// +//############################################################################# +// Destructor for the video renderer +//############################################################################# +// +DPLRenderer::~DPLRenderer() +{ + int + psfx_number; + //------------------------------------------------------ + // release allocated memory used by dump_frame_buffer() + //------------------------------------------------------ + dump_frame_buffer(NULL, NULL, NULL, NULL); + // + // Delete any memory allocated to hold psfx effect descriptions + // + for( psfx_number = 0; psfx_number < MAX_PSFX_COUNT; psfx_number++) + { + if(myPSFXDescriptons[psfx_number]) + { + delete myPSFXDescriptons[psfx_number]; + Unregister_Pointer(myPSFXDescriptons[psfx_number]); + myPSFXDescriptons[psfx_number] = NULL; + } + } + // + //~~~~~~~~~~~~~~~~~~ + // Delete all Lights + //~~~~~~~~~~~~~~~~~~ + // + if (ambientLight) + { + Check_Pointer(ambientLight); + Unregister_Pointer(ambientLight); + dpl_DeleteLight(ambientLight); + } + if (sceneLightDCS && sceneLight) + { + Check_Pointer(sceneLightDCS); + for(int ii=0;ii= 1); + Verify(load_position <=12); + Check(bitmap_to_load); + Check_Pointer(local_storage); + // + // Figure out the position to start copying the data at + // + word_pointer = bitmap_to_load->Data.MapPointer; + if(load_position & 0x1) + { + pixel_pointer = local_storage + 4096; + } + else + { + pixel_pointer = local_storage; + } + // + // Find the bit position to merge the data into + // + switch(load_position) + { + case 1: + case 2: + turn_on = 0x0000f000; + turn_off = 0xffff0fff; + break; + case 3: + case 4: + turn_on = 0x00000f00; + turn_off = 0xfffff0ff; + break; + case 5: + case 6: + turn_on = 0x00f00000; + turn_off = 0xff0fffff; + break; + case 7: + case 8: + turn_on = 0x000f0000; + turn_off = 0xfff0ffff; + break; + case 9: + case 10: + turn_on = 0xf0000000; + turn_off = 0x0fffffff; + break; + case 11: + case 12: + turn_on = 0x0f000000; + turn_off = 0xf0ffffff; + break; + } + // + // Actually process the texels + // + bit_number = 15; + for(y = 0; y < 32; y++) + { + for(x = 0; x < 128; x++) + { + if((*word_pointer & (1< + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL); // intersection mask for the object + Register_Object(this_root); + // + // Select which script to construct + // + switch(script_select) + { + case 0: // Shock wave + { + // + // Load object(s) we will be using for the explosions + // + object_1 = dpl_LoadObject("shock.bgf", dpl_load_normal); + // + // Setup control variables and transforms we need + // + Vector3D scaling_velocity_1(3.5, 3.5, 3.5); + Vector3D velocity_accel_1(0.0, 0.0, 0.0); + LinearMatrix explosion_1_offset(True); + // + // Create the scaling explosion renderables + // + ScalingExplosionRenderable *explosion_1 = + new ScalingExplosionRenderable( + entity, // Entity to attach the renderable to + ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable + object_1, // This will be the scaling explosion object + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS(), // the parent DCS we will be offsetting from + &explosion_1_offset, // offset matrix to be applied prior to joint DCS + &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity + &velocity_accel_1, + 0.0f, + NULL); // -.25 gravity is normal + Register_Object(explosion_1); + // + // Create a sweep renderable to drive the material morph + // + SweepRenderable *sweep_1 = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 0.5f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + NULL); + Register_Object(sweep_1); + // + // Lookup a texture that we can use for the morphing materials + // + int + status; + dpl_TEXTURE *effect_texture = + dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); + if (effect_texture == NULL) + DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n"; + // + // Setup a morph material renderable for each explosion shape + // + MorphMaterialRenderable *morph_material_1 = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 1.0f,1.0f,1.0f, // Material's ambient component + 1.0f,1.0f,1.0f, // Material's emissive component + 1.0f,1.0f,1.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 4.0f,0.2f,-0.05f, // Material's opacity + effect_texture, // Material's texture pointer + 0.0f, // Material's Z dither value + 0, // Material's Fog Imunity value + 0.5f,0.5f,0.5f, // Material's ambient component + 0.5f,0.5f,0.5f, // Material's emissive component + 0.5f,0.5f,0.5f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 0.25f,0.25f,-0.05f, // Material's opacity + 0.1f,0.1f,-0.05f, // Material's opacity + 0.0f, // Material's Z dither value + sweep_1->GetSweepAttribute()); + Register_Object(morph_material_1); + dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); + if(!explosion_1_instance) + Fail("explosion_1_instance came back null\n"); + dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); + dpl_FlushInstance(explosion_1_instance); + break; + } + case 1: // Big explosion + { + // + // Load object(s) we will be using for the explosions + // + object_1 = dpl_LoadObject("exp.bgf", dpl_load_normal); + // + // Setup control variables and transforms we need + // + Vector3D scaling_velocity_1(0.15, 0.15, 0.15); + Vector3D scaling_velocity_2(0.18, 0.22, 0.18); + Vector3D velocity_accel_1(0.0, 0.0, 0.0); + Vector3D velocity_accel_2(0.0, 0.0, 0.0); + LinearMatrix explosion_1_offset(True); + LinearMatrix explosion_2_offset(True); + Point3D explosion_2_translate(0.0f, 0.0f, 0.0f); + EulerAngles explosion_2_rotate(0.0f, 1.0f, 0.0f); + explosion_2_offset = explosion_2_rotate; + explosion_2_offset = explosion_2_translate; + // + // Create the scaling explosion renderables + // + ScalingExplosionRenderable *explosion_1 = + new ScalingExplosionRenderable( + entity, // Entity to attach the renderable to + ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable + object_1, // This will be the scaling explosion object + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS(), // the parent DCS we will be offsetting from + &explosion_1_offset, // offset matrix to be applied prior to joint DCS + &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity + &velocity_accel_1, + 0.0f, + NULL); // -.25 gravity is normal + Register_Object(explosion_1); + ScalingExplosionRenderable *explosion_2 = + new ScalingExplosionRenderable( + entity, // Entity to attach the renderable to + ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable + object_1, // This will be the scaling explosion object + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS(), // the parent DCS we will be offsetting from + &explosion_2_offset, // offset matrix to be applied prior to joint DCS + &scaling_velocity_2, // Effect control vector, Y is acceleration, X, Z are velocity + &velocity_accel_2, + 0.0f, + NULL); + Register_Object(explosion_2); + // + // Create a sweep renderable to drive the material morph + // + SweepRenderable *sweep_1 = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 3.0f, + 1, // number of times to cycle before stopping + NULL); // How long to take to sweep from 0 to 1 + Register_Object(sweep_1); + SweepRenderable *sweep_2 = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 2.0f, + 1, // number of times to cycle before stopping + NULL); // How long to take to sweep from 0 to 1 + Register_Object(sweep_2); + // + // Lookup a texture that we can use for the morphing materials + // + int + status; + dpl_TEXTURE *effect_texture = + dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); + if (effect_texture == NULL) + DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n"; + // + // Setup a morph material renderable for each explosion shape + // + #if 0 + 0.9f,0.0f,0.0f, // Material's ambient component + 1.0f,1.0f,0.0f, // Material's emissive component + 1.0f,0.7f,0.2f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 8.0f,0.2f,-0.05f, // Material's opacity + #endif + MorphMaterialRenderable *morph_material_1 = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 0.9f,0.0f,0.0f, // Material's ambient component + 1.0f,0.2f,0.0f, // Material's emissive component + 1.0f,0.2f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 10.0f,0.6f,-0.05f, // Material's opacity + effect_texture, // Material's texture pointer + 0.0f, // Material's Z dither value + 0, // Material's Fog Imunity value + 0.3f,0.0f,0.0f, // Material's ambient component + 0.5f,0.0f,0.0f, // Material's emissive component + 0.2f,0.0f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 0.25f,0.25f,-0.05f, // Material's opacity + 15.0f, // Material's Z dither value + sweep_1->GetSweepAttribute()); + Register_Object(morph_material_1); + MorphMaterialRenderable *morph_material_2 = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 0.9f,0.0f,0.0f, // Material's ambient component + 1.0f,0.6f,0.3f, // Material's emissive component + 1.0f,0.4f,0.2f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 8.0f,0.2f,-0.05f, // Material's opacity + effect_texture, // Material's texture pointer + 0.0f, // Material's Z dither value + 0, // Material's Fog Imunity value + 0.1f,0.0f,0.0f, // Material's ambient component + 0.0f,0.0f,0.0f, // Material's emissive component + 0.1f,0.0f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 0.25f,0.25f,-0.05f, // Material's opacity + 15.0f, // Material's Z dither value + sweep_2->GetSweepAttribute()); + Register_Object(morph_material_2); + // + // Override the materials in the two explosion shapes using these morph materials + // + dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); + dpl_INSTANCE *explosion_2_instance = dpl_GetDCSInstance(explosion_2->GetDCS(), 1); + + if(!explosion_1_instance) + Fail("explosion_1_instance came back null\n"); + if(!explosion_2_instance) + Fail("explosion_2_instance came back null\n"); + + dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); + dpl_SetInstanceFrontMaterial(explosion_2_instance, morph_material_2->GetMaterial()); + + dpl_FlushInstance(explosion_1_instance); + dpl_FlushInstance(explosion_2_instance); + break; + } + case 2: // Big explosion + { + // + // Load object(s) we will be using for the explosions + // + object_1 = dpl_LoadObject("exp.bgf", dpl_load_normal); + // + // Setup control variables and transforms we need + // + Vector3D scaling_velocity_1(1.0, 0.2, 1.0); + Vector3D scaling_velocity_2(0.75, 0.75, 0.75); + Vector3D velocity_accel_1(-0.00725, -0.004, -0.00725); +// Vector3D velocity_accel_1(-0.00925, -0.00925, -0.00925); + Vector3D velocity_accel_2(-0.01388, -0.01388, -0.01388); + LinearMatrix explosion_1_offset(True); + LinearMatrix explosion_2_offset(True); + Point3D explosion_2_translate(0.0f, 0.0f, 0.0f); + EulerAngles explosion_2_rotate(0.0f, 1.0f, 0.0f); + explosion_2_offset = explosion_2_rotate; + explosion_2_offset = explosion_2_translate; + // + // Create the scaling explosion renderables + // + ScalingExplosionRenderable *explosion_1 = + new ScalingExplosionRenderable( + entity, // Entity to attach the renderable to + ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable + object_1, // This will be the scaling explosion object + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS(), // the parent DCS we will be offsetting from + &explosion_1_offset, // offset matrix to be applied prior to joint DCS + &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity + &velocity_accel_1, + 0.0f, + NULL); // -.25 gravity is normal + Register_Object(explosion_1); + ScalingExplosionRenderable *explosion_2 = + new ScalingExplosionRenderable( + entity, // Entity to attach the renderable to + ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable + object_1, // This will be the scaling explosion object + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS(), // the parent DCS we will be offsetting from + &explosion_2_offset, // offset matrix to be applied prior to joint DCS + &scaling_velocity_2, // Effect control vector, Y is acceleration, X, Z are velocity + &velocity_accel_2, + 0.0f, + NULL); + Register_Object(explosion_2); + // + // Create a sweep renderable to drive the material morph + // + SweepRenderable *sweep_1 = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 3.0f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + NULL); + Register_Object(sweep_1); + SweepRenderable *sweep_2 = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 2.0f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + NULL); + Register_Object(sweep_2); + // + // Lookup a texture that we can use for the morphing materials + // + int + status; + dpl_TEXTURE *effect_texture = + dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); + if (effect_texture == NULL) + DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n"; + // + // Setup a morph material renderable for each explosion shape + // + #if 0 + 0.9f,0.0f,0.0f, // Material's ambient component + 1.0f,1.0f,0.0f, // Material's emissive component + 1.0f,0.7f,0.2f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 8.0f,0.2f,-0.05f, // Material's opacity + #endif + MorphMaterialRenderable *morph_material_1 = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 0.9f,0.0f,0.0f, // Material's ambient component + 1.0f,0.2f,0.0f, // Material's emissive component + 1.0f,0.2f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 8.0f,0.2f,-0.05f, // Material's opacity + effect_texture, // Material's texture pointer + 0.0f, // Material's Z dither value + 0, // Material's Fog Imunity value + 0.3f,0.0f,0.0f, // Material's ambient component + 0.5f,0.0f,0.0f, // Material's emissive component + 0.2f,0.0f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 0.25f,0.25f,-0.05f, // Material's opacity + 15.0f, // Material's Z dither value + sweep_1->GetSweepAttribute()); + Register_Object(morph_material_1); + MorphMaterialRenderable *morph_material_2 = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 0.9f,0.0f,0.0f, // Material's ambient component + 1.0f,0.6f,0.4f, // Material's emissive component + 1.0f,0.3f,0.2f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 8.0f,0.2f,-0.05f, // Material's opacity + effect_texture, // Material's texture pointer + 0.0f, // Material's Z dither value + 0, // Material's Fog Imunity value + 0.1f,0.0f,0.0f, // Material's ambient component + 0.0f,0.0f,0.0f, // Material's emissive component + 0.0f,0.0f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 0.25f,0.25f,-0.05f, // Material's opacity + 15.0f, // Material's Z dither value + sweep_2->GetSweepAttribute()); + Register_Object(morph_material_2); + // + // Override the materials in the two explosion shapes using these morph materials + // + dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); + dpl_INSTANCE *explosion_2_instance = dpl_GetDCSInstance(explosion_2->GetDCS(), 1); + + if(!explosion_1_instance) + Fail("explosion_1_instance came back null\n"); + if(!explosion_2_instance) + Fail("explosion_2_instance came back null\n"); + + dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); + dpl_SetInstanceFrontMaterial(explosion_2_instance, morph_material_2->GetMaterial()); + + dpl_FlushInstance(explosion_1_instance); + dpl_FlushInstance(explosion_2_instance); + break; + } + case 3: // Sparks + { + // + // Load object(s) we will be using for the explosions + // + object_1 = dpl_LoadObject("spk1.bgf", dpl_load_normal); + // + // Setup control variables and transforms we need + // + Vector3D scaling_velocity_1(0.1, 0.1, 0.1); + Vector3D velocity_accel_1(0.0, 0.0, 0.0); + LinearMatrix explosion_1_offset(True); + // + // Create the scaling explosion renderables + // + ScalingExplosionRenderable *explosion_1 = + new ScalingExplosionRenderable( + entity, // Entity to attach the renderable to + ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable + object_1, // This will be the scaling explosion object + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS(), // the parent DCS we will be offsetting from + &explosion_1_offset, // offset matrix to be applied prior to joint DCS + &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity + &velocity_accel_1, + -0.15f, + NULL); // -.25 gravity is normal + Register_Object(explosion_1); + // + // Create a sweep renderable to drive the material morph + // + SweepRenderable *sweep_1 = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 0.5f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + NULL); + Register_Object(sweep_1); + // + // Lookup a texture that we can use for the morphing materials + // + int + status; + dpl_TEXTURE *effect_texture = + dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); + if (effect_texture == NULL) + DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n"; + // + // Setup a morph material renderable for each explosion shape + // + MorphMaterialRenderable *morph_material_1 = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 1.0f,1.0f,0.0f, // Material's ambient component + 1.0f,1.0f,0.0f, // Material's emissive component + 1.0f,1.0f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 1.0f,1.0f,1.0f, // Material's opacity + effect_texture, // Material's texture pointer + 0.0f, // Material's Z dither value + 2, // Material's Fog Imunity value + 0.9f,0.0f,0.0f, // Material's ambient component + 0.9f,0.0f,0.0f, // Material's emissive component + 0.9f,0.0f,0.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0, // Material's specular component + 1.0f,1.0f,1.0f, // Material's opacity + 0.0f, // Material's Z dither value + sweep_1->GetSweepAttribute()); + Register_Object(morph_material_1); + dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); + if(!explosion_1_instance) + Fail("explosion_1_instance came back null\n"); + dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); + dpl_FlushInstance(explosion_1_instance); + break; + } + case 4: // A huge mech explodes (yawn) + { + Point3D null_offset(0.0f, 0.0f, 0.0f); + LinearMatrix null_offset_matrix(True); + Point3D local_height(0.0f, 6.2f, 0.0f); // height of Thor + LinearMatrix local_offset(True); + local_offset = local_height; + DPLStaticChildRenderable *local_root = + new DPLStaticChildRenderable( + entity, + dplMainZone, + NULL, + dpl_isect_mode_obj, + NULL, + local_offset, + this_root->GetDCS()); + Register_Object(local_root); + // + // Load morph sources we need for the effect + // + dpl_OBJECT *thor_debris_object = dpl_LoadObject("thrdbr.bgf", dpl_load_normal); + dpl_OBJECT *large_debris_object = dpl_LoadObject("ldbr.bgf", dpl_load_normal); + dpl_OBJECT *small_flames_object = dpl_LoadObject("flamesml.bgf", dpl_load_normal); + // + // Load morph targets we need for the effect + // + //------------------------------------------------ + // Renderables to handle the chunks and fireballs + //------------------------------------------------ +#if 0 + OneShotDelayRenderable *fireball_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.25f); // How long to wait before raising the trigger + Register_Object(fireball_delay); + Point3D my_offset(0.0, 4.0, 0.0); + #if DEBUG_LEVEL > 0 + DPLPSFXRenderable* initial_boom = + #endif + new DPLPSFXRenderable( + entity, // Entity to attach the renderable to + DPLPSFXRenderable::Dynamic, // How/when to execute the renderable + fireball_delay->GetTriggerAttribute(), // address containing the trigger + myPSFXDescriptons[7], // pointer to the PFX description + this_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &my_offset); // Offset (or world coordinants if DCS is NULL) + Register_Object(initial_boom); + #if DEBUG_LEVEL > 0 + DPLEffectRenderable *chunks_effect = + #endif + new DPLEffectRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + fireball_delay->GetTriggerAttribute(), // address containing the trigger + 3, // Chunks // DPL effect number to trigger + local_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &null_offset); // Offset (or world coordinants if DCS is NULL) + Register_Object(chunks_effect); + Point3D fireball_offset(1.0f, 5.0f, 1.0f); + #if DEBUG_LEVEL > 0 + DPLEffectRenderable *fireball_effect = + #endif + new DPLEffectRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + fireball_delay->GetTriggerAttribute(), // address containing the trigger + 15, // Fireball // DPL effect number to trigger + local_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &fireball_offset); // Offset (or world coordinants if DCS is NULL) + Register_Object(fireball_effect); +#endif + OneShotDelayRenderable *fireball_delay_2 = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.55f); // How long to wait before raising the trigger + Register_Object(fireball_delay_2); + Point3D fireball_offset_2(-1.0f, 5.0f, -1.0f); + #if DEBUG_LEVEL > 0 + DPLEffectRenderable *fireball_effect_2 = + #endif + new DPLEffectRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + fireball_delay_2->GetTriggerAttribute(), // address containing the trigger + 15, // Fireball // DPL effect number to trigger + local_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &fireball_offset_2); // Offset (or world coordinants if DCS is NULL) + Register_Object(fireball_effect_2); + //----------------------------------------------- + // Renderables to handle static debris + //----------------------------------------------- + OneShotDelayRenderable *static_debris_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.25f); // How long to wait before raising the trigger + Register_Object(static_debris_delay); + DPLStaticChildRenderable *mech_debris = + new DPLStaticChildRenderable( + entity, + dplMainZone, + thor_debris_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + this_root->GetDCS()); + Register_Object(mech_debris); + #if DEBUG_LEVEL > 0 + MakeDCSFall *mech_debris_fall = + #endif + new MakeDCSFall( + entity, // Entity to attach the renderable to + MakeDCSFall::Dynamic, // How/when to execute the renderable + mech_debris->GetDCS(), // the DCS to control + -0.025f, // Gravity in meters/sec squared + static_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off + Register_Object(mech_debris_fall); + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *mech_debris_instance = dpl_GetDCSInstance(mech_debris->GetDCS(), 1); + #if DEBUG_LEVEL > 0 + InstanceSwitchRenderable *mech_debris_instance_switch = + #endif + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + mech_debris_instance, // the instance to control + True, // Instance is on when trigger is... + static_debris_delay->GetTriggerAttribute()); + Register_Object(mech_debris_instance_switch); + + DPLStaticChildRenderable *large_debris = + new DPLStaticChildRenderable( + entity, + dplMainZone, + large_debris_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + mech_debris->GetDCS()); + Register_Object(large_debris); + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *large_debris_instance = dpl_GetDCSInstance(large_debris->GetDCS(), 1); + #if DEBUG_LEVEL > 0 + InstanceSwitchRenderable *large_debris_instance_switch = + #endif + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + large_debris_instance, // the instance to control + True, // Instance is on when trigger is... + static_debris_delay->GetTriggerAttribute()); + Register_Object(large_debris_instance_switch); + //----------------------------------------------- + // Renderables to handle fires + //----------------------------------------------- + OneShotDelayRenderable *fires_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.25f); // How long to wait before raising the trigger + Register_Object(fires_delay); + DPLStaticChildRenderable *fires = + new DPLStaticChildRenderable( + entity, + dplMainZone, + NULL, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + this_root->GetDCS()); + Register_Object(fires); + #if DEBUG_LEVEL > 0 + MakeDCSFall *fires_fall = + #endif + new MakeDCSFall( + entity, // Entity to attach the renderable to + MakeDCSFall::Dynamic, // How/when to execute the renderable + fires->GetDCS(), // the DCS to control + -0.01f, // Gravity in meters/sec squared + fires_delay->GetTriggerAttribute()); // true if the instance is on, false if off + Register_Object(fires_fall); + DPLStaticChildRenderable *small_flames = + new DPLStaticChildRenderable( + entity, + dplMainZone, + small_flames_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + fires->GetDCS()); + Register_Object(small_flames); + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *small_flames_instance = dpl_GetDCSInstance(small_flames->GetDCS(), 1); + #if DEBUG_LEVEL > 0 + InstanceSwitchRenderable *small_flames_instance_switch = + #endif + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + small_flames_instance, // the instance to control + True, // Instance is on when trigger is... + fires_delay->GetTriggerAttribute()); + Register_Object(small_flames_instance_switch); + + dpl_OBJECT *big_flames_object = dpl_LoadObject("flamebig.bgf", dpl_load_normal); + DPLStaticChildRenderable *big_flames = + new DPLStaticChildRenderable( + entity, + dplMainZone, + big_flames_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + fires->GetDCS()); + Register_Object(big_flames); + // Make big flames object billboard along y-axis + dpl_SetDCSReorientAxes(big_flames->GetDCS(), dpl_reorient_axes_y); + dpl_FlushDCS(big_flames->GetDCS()); + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *big_flames_instance = dpl_GetDCSInstance(big_flames->GetDCS(), 1); + #if DEBUG_LEVEL > 0 + InstanceSwitchRenderable *big_flames_instance_switch = + #endif + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + big_flames_instance, // the instance to control + True, // Instance is on when trigger is... + fires_delay->GetTriggerAttribute()); + Register_Object(big_flames_instance_switch); + // + // These renderables create the rising smoke column using a pfx effect. + // +#if 0 + Point3D my_offset2(0.0, 5.0, 0.0); + #if DEBUG_LEVEL > 0 + OnePSFXRenderable *this_effect= + #endif + new OnePSFXRenderable( + entity, // Entity to attach the renderable to + OnePSFXRenderable::Static, // How/when to execute the renderable + myPSFXDescriptons[1], // name of file with the PFX description in it + this_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &my_offset2); // Offset (or world coordinants if DCS is NULL) + Register_Object(this_effect); +#endif + break; + } + //---------------------------------------- + case 5: // Sfx #105 - Delayed ground hit + //---------------------------------------- + { + // + // Create the delayed ground hit renderables + // + Point3D null_offset(0.0f, 0.0f, 0.0f); + OneShotDelayRenderable *ground_hit_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.15f); // How long to wait before raising the trigger + Register_Object(ground_hit_delay); + #if DEBUG_LEVEL > 0 + DPLEffectRenderable *ground_hit_effect = + #endif + new DPLEffectRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + ground_hit_delay->GetTriggerAttribute(), // address containing the trigger + 12, // GroundHit // DPL effect number to trigger + this_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &null_offset); // Offset (or world coordinants if DCS is NULL) + Register_Object(ground_hit_effect); + break; + } + //------------------------------------------ + case 6: // Sfx #106 - Thor death explosion + //------------------------------------------ + { + #if 0 + int status; // used with dpl calls + Point3D null_offset(0.0f, 0.0f, 0.0f); + LinearMatrix null_offset_matrix(True); + Point3D local_height(0.0f, 6.2f, 0.0f); // height of Thor + LinearMatrix local_offset(True); + local_offset = local_height; + DPLStaticChildRenderable *local_root = + new DPLStaticChildRenderable( + entity, + dplMainZone, + NULL, + dpl_isect_mode_obj, + NULL, + local_offset, + this_root->GetDCS()); + Register_Object(local_root); +#if 0 + //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + // + // Show static thor (TEMPORARY for testing) + // + dpl_OBJECT *static_thr_object = dpl_LoadObject("thr.bgf", dpl_load_normal); + DPLStaticChildRenderable *static_thr = + new DPLStaticChildRenderable( + entity, + dplMainZone, + static_thr_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + local_root->GetDCS()); + Register_Object(static_thr); + // This defines how long the static_thr stays visible + OneShotDelayRenderable *static_thr_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.5f); // How long to wait before raising the trigger + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *static_thr_instance = dpl_GetDCSInstance(static_thr->GetDCS(), 1); + InstanceSwitchRenderable *static_thr_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + static_thr_instance, // the instance to control + False, // Instance is on when trigger is... + static_thr_delay->GetTriggerAttribute()); + // + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#endif + // + // Load objects we will be using for the explosion effect + // + DPLObjectWrapper *flash_object_wrapper = + new DPLObjectWrapper( + entity, // Entity to attach the renderable to + "exdisk_A.bgf", // Name of the DPL object to load into the wrapper + dpl_load_nocache); // Type of loading to perform on this object + Register_Object(flash_object_wrapper); + dpl_OBJECT *flash_object_a = flash_object_wrapper->GetDPLObject(); + dpl_OBJECT *flash_object_b = dpl_LoadObject("exdisk_B.bgf", dpl_load_normal); + dpl_OBJECT *flash_object_c = dpl_LoadObject("exdisk_C.bgf", dpl_load_normal); + DPLObjectWrapper *debris_object_wrapper = + new DPLObjectWrapper( + entity, // Entity to attach the renderable to + "thrtor_A.bgf", // Name of the DPL object to load into the wrapper + dpl_load_nocache); // Type of loading to perform on this object + Register_Object(debris_object_wrapper); + dpl_OBJECT *morph_debris_a = debris_object_wrapper->GetDPLObject(); + dpl_OBJECT *morph_debris_b = dpl_LoadObject("thrtor_B.bgf", dpl_load_normal); + dpl_OBJECT *morph_debris_c = dpl_LoadObject("thrtor_C.bgf", dpl_load_normal); + DPLObjectWrapper *hips_object_wrapper = + new DPLObjectWrapper( + entity, // Entity to attach the renderable to + "thrhip_A.bgf", // Name of the DPL object to load into the wrapper + dpl_load_nocache); // Type of loading to perform on this object + Register_Object(hips_object_wrapper); + dpl_OBJECT *morph_hips_a = hips_object_wrapper->GetDPLObject(); + dpl_OBJECT *morph_hips_b = dpl_LoadObject("thrhip_B.bgf", dpl_load_normal); + dpl_OBJECT *morph_hips_c = dpl_LoadObject("thrhip_C.bgf", dpl_load_normal); + dpl_OBJECT *thor_debris_object = dpl_LoadObject("thrdbr.bgf", dpl_load_normal); + dpl_OBJECT *large_debris_object = dpl_LoadObject("ldbr.bgf", dpl_load_normal); + dpl_OBJECT *small_flames_object = dpl_LoadObject("flamesml.bgf", dpl_load_normal); + dpl_OBJECT *big_flames_object = dpl_LoadObject("flamebig.bgf", dpl_load_normal); + //---------------------------------------------- + // Renderables to perform morphing flash object + //---------------------------------------------- + SweepRenderable *flash_morph_sweep = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 1.0f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + NULL, // trigger + -0.5f, // Initial value + 2.0f); // Final value + ChildMorphRenderable *flash_morph = + new ChildMorphRenderable( + entity, // Entity to attach the renderable to + ChildMorphRenderable::Dynamic, // How/when to execute the renderable + flash_object_a, // destination + flash_object_b, // start object + flash_object_c, // end object + flash_morph_sweep->GetSweepAttribute(), // pointer to control variable + dpl_morph_vertices | dpl_morph_colors, // Defines type of morph to do + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS()); // the parent DCS we will be offsetting from + // Make flash object billboard along y-axis + dpl_SetDCSReorientAxes(flash_morph->GetDCS(), dpl_reorient_axes_y); + dpl_FlushDCS(flash_morph->GetDCS()); + // This defines how long the flash stays up + OneShotDelayRenderable *flash_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 1.0f); // How long to wait before raising the trigger + Register_Object(flash_delay); + // Find the instance with the flash in it and hook up the instance switch + dpl_INSTANCE *flash_morph_instance = dpl_GetDCSInstance(flash_morph->GetDCS(), 1); + InstanceSwitchRenderable *flash_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + flash_morph_instance, // the instance to control + False, // Instance is on when trigger is... + flash_delay->GetTriggerAttribute()); + //--------------------------------------------------- + // Create a material morph to fade flash object away + //--------------------------------------------------- + OneShotDelayRenderable *flash_fade_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.5f); // How long to wait before raising the trigger + SweepRenderable *flash_fade_sweep = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 0.4f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + flash_fade_delay->GetTriggerAttribute()); // trigger variable + Register_Object(flash_fade_sweep); + // Lookup texture for smoke column + dpl_TEXTURE *flash_texture = + dpl_LookupTexture("btfx:bexp9_tex", dpl_lookup_normal, &status); + if (flash_texture == NULL) + DEBUG_STREAM<<"couldn't find texture btfx:bexp9_tex for an effect\n"; + // + MorphMaterialRenderable *flash_fade_material = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 1.0f,1.0f,1.0f, // Material's ambient component + 1.0f,1.0f,1.0f, // Material's emissive component + 1.0f,1.0f,1.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0f, // Material's specular component + 1.0f,1.0f,1.0f, // Material's opacity + flash_texture, // Material's texture pointer + 0.0f, // Material's Z dither value + 1, // Material's Fog Imunity value + 1.0f,1.0f,1.0f, // Material's ambient component + 1.0f,1.0f,1.0f, // Material's emissive component + 1.0f,1.0f,1.0f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0f, // Material's specular component + 0.0f,0.0f,0.0f, // Material's opacity + 0.0f, // Material's Z dither value + flash_fade_sweep->GetSweepAttribute()); + Register_Object(flash_fade_material); +// dpl_INSTANCE *flash_morph_instance = dpl_GetDCSInstance(flash_morph->GetDCS(), 1); + if (!flash_morph_instance) + Fail("flash_morph_instance came back null\n"); + dpl_SetInstanceFrontMaterial(flash_morph_instance, flash_fade_material->GetMaterial()); + dpl_FlushInstance(flash_morph_instance); + //------------------------------------------------ + // Renderables to handle the chunks and fireballs + //------------------------------------------------ + OneShotDelayRenderable *fireball_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.25f); // How long to wait before raising the trigger + Register_Object(fireball_delay); + DPLEffectRenderable *chunks_effect = + new DPLEffectRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + fireball_delay->GetTriggerAttribute(), // address containing the trigger + 3, // Chunks // DPL effect number to trigger + local_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &null_offset); // Offset (or world coordinants if DCS is NULL) + Register_Object(chunks_effect); + Point3D fireball_offset(1.0f, 5.0f, 1.0f); + DPLEffectRenderable *fireball_effect = + new DPLEffectRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + fireball_delay->GetTriggerAttribute(), // address containing the trigger + 15, // Fireball // DPL effect number to trigger + local_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &fireball_offset); // Offset (or world coordinants if DCS is NULL) + Register_Object(fireball_effect); + OneShotDelayRenderable *fireball_delay_2 = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.55f); // How long to wait before raising the trigger + Register_Object(fireball_delay_2); + Point3D fireball_offset_2(-1.0f, 5.0f, -1.0f); + DPLEffectRenderable *fireball_effect_2 = + new DPLEffectRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + fireball_delay_2->GetTriggerAttribute(), // address containing the trigger + 15, // Fireball // DPL effect number to trigger + local_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &fireball_offset_2); // Offset (or world coordinants if DCS is NULL) + Register_Object(fireball_effect_2); + //------------------------------------------------------ + // Renderables to handle the torso debris explode morph + //------------------------------------------------------ + OneShotDelayRenderable *morph_debris_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.25f, // How long to wait before raising the trigger + 4.25f); // Duration of trigger + SweepRenderable *debris_morph_sweep = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 4.0f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + morph_debris_delay->GetTriggerAttribute(), // trigger variable + 0.0f, // initial value of sweep + 9.0f, // final value of sweep + SweepRenderable::Y_SQR_X); // function to apply + ChildMorphRenderable *debris_morph = + new ChildMorphRenderable( + entity, // Entity to attach the renderable to + ChildMorphRenderable::Dynamic, // How/when to execute the renderable + morph_debris_a, // destination + morph_debris_b, // start object + morph_debris_c, // end object + debris_morph_sweep->GetSweepAttribute(), // pointer to control variable + dpl_morph_vertices, // Defines type of morph to do + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + local_root->GetDCS()); // the parent DCS we will be offsetting from + MakeDCSFall *debris_make_fall = + new MakeDCSFall( + entity, // Entity to attach the renderable to + MakeDCSFall::Dynamic, // How/when to execute the renderable + debris_morph->GetDCS(), // the DCS to control + -9.81f, // Gravity in meters/sec squared + morph_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off + // Find the instance with the debris in it and hook up the instance switch + dpl_INSTANCE *debris_morph_instance = dpl_GetDCSInstance(debris_morph->GetDCS(), 1); + InstanceSwitchRenderable *debris_morph_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + debris_morph_instance, // the instance to control + True, // Instance is on when trigger is... + morph_debris_delay->GetTriggerAttribute()); + //----------------------------------------------------- + // Renderables to handle the hips debris explode morph + //----------------------------------------------------- + ChildMorphRenderable *hips_morph = + new ChildMorphRenderable( + entity, // Entity to attach the renderable to + ChildMorphRenderable::Dynamic, // How/when to execute the renderable + morph_hips_a, // destination + morph_hips_b, // start object + morph_hips_c, // end object + debris_morph_sweep->GetSweepAttribute(), // pointer to control variable + dpl_morph_vertices, // Defines type of morph to do + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + local_root->GetDCS()); // the parent DCS we will be offsetting from + MakeDCSFall *hips_make_fall = + new MakeDCSFall( + entity, // Entity to attach the renderable to + MakeDCSFall::Dynamic, // How/when to execute the renderable + hips_morph->GetDCS(), // the DCS to control + -9.81f, // Gravity in meters/sec squared + morph_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off + // Find the instance with the debris in it and hook up the instance switch + dpl_INSTANCE *hips_morph_instance = dpl_GetDCSInstance(hips_morph->GetDCS(), 1); + InstanceSwitchRenderable *hips_morph_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + hips_morph_instance, // the instance to control + True, // Instance is on when trigger is... + morph_debris_delay->GetTriggerAttribute()); + //----------------------------------------------- + // Renderables to handle static debris and fires + //----------------------------------------------- + OneShotDelayRenderable *static_debris_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.25f); // How long to wait before raising the trigger + DPLStaticChildRenderable *mech_debris = + new DPLStaticChildRenderable( + entity, + dplMainZone, + thor_debris_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + this_root->GetDCS()); + Register_Object(mech_debris); + MakeDCSFall *mech_debris_fall = + new MakeDCSFall( + entity, // Entity to attach the renderable to + MakeDCSFall::Dynamic, // How/when to execute the renderable + mech_debris->GetDCS(), // the DCS to control + -0.01f, // Gravity in meters/sec squared + static_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *mech_debris_instance = dpl_GetDCSInstance(mech_debris->GetDCS(), 1); + InstanceSwitchRenderable *mech_debris_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + mech_debris_instance, // the instance to control + True, // Instance is on when trigger is... + static_debris_delay->GetTriggerAttribute()); + + DPLStaticChildRenderable *large_debris = + new DPLStaticChildRenderable( + entity, + dplMainZone, + large_debris_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + mech_debris->GetDCS()); + Register_Object(large_debris); + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *large_debris_instance = dpl_GetDCSInstance(large_debris->GetDCS(), 1); + InstanceSwitchRenderable *large_debris_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + large_debris_instance, // the instance to control + True, // Instance is on when trigger is... + static_debris_delay->GetTriggerAttribute()); + + DPLStaticChildRenderable *small_flames = + new DPLStaticChildRenderable( + entity, + dplMainZone, + small_flames_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + mech_debris->GetDCS()); + Register_Object(small_flames); + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *small_flames_instance = dpl_GetDCSInstance(small_flames->GetDCS(), 1); + InstanceSwitchRenderable *small_flames_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + small_flames_instance, // the instance to control + True, // Instance is on when trigger is... + static_debris_delay->GetTriggerAttribute()); + + DPLStaticChildRenderable *big_flames = + new DPLStaticChildRenderable( + entity, + dplMainZone, + big_flames_object, + dpl_isect_mode_obj, + NULL, + null_offset_matrix, + mech_debris->GetDCS()); + Register_Object(big_flames); + // Make big flames object billboard along y-axis + dpl_SetDCSReorientAxes(big_flames->GetDCS(), dpl_reorient_axes_y); + dpl_FlushDCS(big_flames->GetDCS()); + // Find the instance with the static_thr in it and hook up the instance switch + dpl_INSTANCE *big_flames_instance = dpl_GetDCSInstance(big_flames->GetDCS(), 1); + InstanceSwitchRenderable *big_flames_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + big_flames_instance, // the instance to control + True, // Instance is on when trigger is... + static_debris_delay->GetTriggerAttribute()); + //------------------------------------------------------------- + // Renderables to handle the rising smoke column (first shape) + //------------------------------------------------------------- +#if 1 + OneShotDelayRenderable *first_one_shot = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 0.0f); // How long to wait before raising the trigger + Register_Object(first_one_shot); + Point3D my_offset(0.0, 6.0, 0.0); + #if DEBUG_LEVEL > 0 + DPLPSFXRenderable* this_effect = + #endif + new DPLPSFXRenderable( + entity, // Entity to attach the renderable to + DPLPSFXRenderable::Dynamic, // How/when to execute the renderable + first_one_shot->GetTriggerAttribute(), // address containing the trigger + myPSFXDescriptons[1], // pointer to the PFX description + this_root->GetDCS(), // DCS the effect is relative to (may be NULL) + &my_offset); // Offset (or world coordinants if DCS is NULL) + Register_Object(this_effect); + +// the below code will be removed in favor of PFX effects once they are tested +#else +// OneShotDelayRenderable *smoke_1_morph_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.25f); // How long to wait before raising the trigger + SweepRenderable *smoke_1_sweep = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 40.0f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + static_debris_delay->GetTriggerAttribute(), + 0.2f, + 2.5f); + ChildMorphRenderable *smoke_1_morph = + new ChildMorphRenderable( + entity, // Entity to attach the renderable to + ChildMorphRenderable::Dynamic, // How/when to execute the renderable + smoke_1_a, // destination + smoke_b, // start object + smoke_c, // end object + smoke_1_sweep->GetSweepAttribute(), // pointer to control variable + dpl_morph_vertices, // Defines type of morph to do + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS()); // the parent DCS we will be offsetting from + // Find the instance with the flash in it and hook up the instance switch + dpl_INSTANCE *smoke_1_instance = dpl_GetDCSInstance(smoke_1_morph->GetDCS(), 1); + InstanceSwitchRenderable *smoke_1_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + smoke_1_instance, // the instance to control + True, // Instance is on when trigger is... + static_debris_delay->GetTriggerAttribute()); + //-------------------------------------------------------------- + // Renderables to handle the rising smoke column (second shape) + //-------------------------------------------------------------- +#if 0 + OneShotDelayRenderable *smoke_2_morph_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 6.0f); // How long to wait before raising the trigger + SweepRenderable *smoke_2_sweep = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 30.0f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + smoke_2_morph_delay->GetTriggerAttribute(), + 0.1f, + 1.0f); + ChildMorphRenderable *smoke_2_morph = + new ChildMorphRenderable( + entity, // Entity to attach the renderable to + ChildMorphRenderable::Dynamic, // How/when to execute the renderable + smoke_2_a, // destination + smoke_b, // start object + smoke_c, // end object + smoke_2_sweep->GetSweepAttribute(), // pointer to control variable + dpl_morph_vertices, // Defines type of morph to do + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + this_root->GetDCS()); // the parent DCS we will be offsetting from + // Find the instance with the flash in it and hook up the instance switch + dpl_INSTANCE *smoke_2_instance = dpl_GetDCSInstance(smoke_2_morph->GetDCS(), 1); + InstanceSwitchRenderable *smoke_2_morph_instance_switch = + new InstanceSwitchRenderable( + entity, // Entity to attach the renderable to + InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable + smoke_2_instance, // the instance to control + True, // Instance is on when trigger is... + smoke_2_morph_delay->GetTriggerAttribute()); +#endif + //------------------------------------------- + // Set dither Z on material for smoke column + //------------------------------------------- + dpl_MATERIAL *damage_material = + dpl_LookupMaterial ("btfx:smoke1_mtl", + dpl_lookup_normal, + &status); + if (damage_material == 0) + { + cout << "couldn't find material\n"; + } + else + { + dpl_SetMaterialDitherZ(damage_material, 10.0f); + dpl_FlushMaterial(damage_material); + } + //--------------------------------------------------- + // Create a material morph to fade smoke column away + //--------------------------------------------------- + OneShotDelayRenderable *smoke_fade_delay = + new OneShotDelayRenderable( + entity, // Entity to attach the renderable to + OneShotDelayRenderable::Dynamic, // How/when to execute the renderable + 25.0f); // How long to wait before raising the trigger + SweepRenderable *smoke_fade_sweep = + new SweepRenderable( + entity, // Entity to attach the renderable to + SweepRenderable::Dynamic, // How/when to execute the renderable + 18.5f, // How long to take to sweep from 0 to 1 + 1, // number of times to cycle before stopping + smoke_fade_delay->GetTriggerAttribute()); // trigger variable + Register_Object(smoke_fade_sweep); + // Lookup texture for smoke column + dpl_TEXTURE *smoke_texture = + dpl_LookupTexture("btfx:smoke1_scr_tex", dpl_lookup_normal, &status); + if (smoke_texture == NULL) + DEBUG_STREAM<<"couldn't find texture btfx:smoke1_scr_tex for an effect\n"; + // + MorphMaterialRenderable *smoke_fade_material = + new MorphMaterialRenderable( + entity, // Entity to attach the renderable to + MorphMaterialRenderable::Dynamic, // How/when to execute the renderable + 1.0f,1.0f,1.0f, // Material's ambient component + 0.7f,0.4f,0.4f, // Material's emissive component + 0.3714f,0.2899f,0.3714f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0f, // Material's specular component + 0.7f,0.99f,0.0f, // Material's opacity + smoke_texture, // Material's texture pointer + 10.0f, // Material's Z dither value + 3, // Material's Fog Imunity value + 1.0f,1.0f,1.0f, // Material's ambient component + 0.7f,0.4f,0.4f, // Material's emissive component + 0.3714f,0.2899f,0.3714f, // Material's diffuse component + 0.0f,0.0f,0.0f,0.0f, // Material's specular component + 0.0f,0.99f,0.0f, // Material's opacity + 10.0f, // Material's Z dither value + smoke_fade_sweep->GetSweepAttribute()); + Register_Object(smoke_fade_material); +// dpl_INSTANCE *smoke_1_instance = dpl_GetDCSInstance(smoke_1_morph->GetDCS(), 1); + if (!smoke_1_instance) + Fail("smoke_1_instance came back null\n"); + dpl_SetInstanceFrontMaterial(smoke_1_instance, smoke_fade_material->GetMaterial()); + dpl_FlushInstance(smoke_1_instance); +#endif + #else + DEBUG_STREAM <<"Explosion effect 104 called, this is disabled and shouldn't be used!\n"; + #endif + break; + } + default: + { + break; + } + } +} +// +//############################################################################# +// MakeEntityRenderables handles creating all the renderables necessary to +// display an object. This routine contains default behaviors for creating +// some types of simple objects. The idea is that if a higher level routine +// can't figure out how to make renderables for something this routine will be +// called and the default behavior will be used. +//############################################################################# +// +void + DPLRenderer::MakeEntityRenderables( + Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom view_type) // Type of reference (inside/outside...etc.) +{ + char + *object_filename; + #if DEBUG_LEVEL > 0 + int + object_count; + #endif + L4VideoObject // should be const + *video_object; + L4VideoObjectWrapper + *video_wrapper; + ChainOf + video_chain(NULL); + L4VideoObject::ResourceType + resource_type; + dpl_DCS + *my_root_dcs; + Enumeration // L4VideoObject::RendererModes + renderer_modes; + // + // Set the Entity_Being_Created global so the C language callback will + // be able to mark the geometry with damage zone values if necessary. + // + Entity_Being_Created = entity; + my_root_dcs = NULL; + // + // convert video resource into chain of video objects and make an iterator + // for that chain + // + if (model_resource) + { + #if DEBUG_LEVEL > 0 + object_count = + #endif + L4VideoObjectWrapper::BuildVideoObjectChainFromResource( + &video_chain, + model_resource + ); + } + ChainIteratorOf + video_iterator(video_chain); + // + // Switch to allow us to have scripts at this level for constructing certain + // types of video objects (whether or not they have a video resource) + // + switch (entity->GetClassID()) + { + // + // Dropzones have no graphical appearance so we do nothing + // + case DropZoneClassID: + break; + // + // Player objects have no graphical appearance unless one is created + // at a higher (game specific) level, so we do nothing here. + // + case PlayerClassID: + break; + // this entity has no visual appearance + case AudioEntityClassID: + break; + // + // Cultural and landmark are the only ones with "destroyed" processing + // This is similar to the default case but does not allow us to be + // inside the entity, does not allow us to be a mover, + // + case CulturalIconClassID: + case LandmarkClassID: + { + dpl_INSTANCE + *this_instance; + dpl_OBJECT + *this_object; + dpl_ISECT_MODE + intersect_mode; + uint32 + intersect_mask; + LinearMatrix + offset_matrix = LinearMatrix::Identity; + dpl_DCS + *root_DCS, + *this_DCS; + // + // Make sure the object has a video resource + // + if (!model_resource) + { + VideoRenderer::MakeEntityRenderables(entity, model_resource, view_type); + Entity_Being_Created = NULL; + return; + } + intersect_mode = dpl_isect_mode_geometry; + intersect_mask = INTERSECT_ALL; + Logical + first_object = True; + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + object_filename = video_object->GetObjectFilename(); + resource_type = video_object->GetResourceType(); + renderer_modes = video_object->GetRendererModes(); + + #if NOISY_RENDERER + Tell("L4VIDEO.cpp loading object " << object_filename); + Tell(" type " << resource_type); + Tell(" mode 0x" < + dplMainZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + Register_Object(this_static_root); + root_DCS = this_static_root->GetDCS(); + //------------------------------------------------------ + // if root object billboards (all others billboard too) + //------------------------------------------------------ + this_DCS = root_DCS; + this_instance = this_static_root->GetInstance(); + // + // Set my_root_dcs because we want this guy's hiearchy to be marked + // with his entity pointer + // + my_root_dcs = root_DCS; + } + else + { + if (renderer_modes | L4VideoObject::BillboardObject) + { + //------------------------------------------ + // attach additional object to separate DCS + // because it is billboarded + //------------------------------------------ + DPLStaticChildRenderable *this_child = + new DPLStaticChildRenderable( + entity, + dplMainZone, + this_object, + intersect_mode, + intersect_mask, + offset_matrix, + root_DCS); + Register_Object(this_child); + this_DCS = this_child->GetDCS(); + this_instance = this_child->GetInstance(); + } + else + { + //---------------------------------------- + // attach additional objects to root_DCS + // (HACK) temporary implementation (HACK) + //---------------------------------------- + DCSInstanceRenderable *another_instance = + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + this_object, // object to connect to the instance + root_DCS, // the DCS to add the instance to + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + True); // initial visibility setting + Register_Object(another_instance); + this_DCS = NULL; + this_instance = another_instance->GetInstance(); + } + } + // + // Hook up the object to an instance switch renderable responsive to state + // + StateIndicator* simulation_state = + (StateIndicator *)entity->GetAttributePointer("SimulationState"); + switch(resource_type) + { + case L4VideoObject::Object: + { + #if DEBUG_LEVEL > 0 + StateInstanceSwitchRenderable *undamaged_state = + #endif + new StateInstanceSwitchRenderable( + entity, // Entity to attach the renderable to + StateInstanceSwitchRenderable::Watcher, // How/when to execute the renderable + this_instance, // the instance to control + False, // true to turn on in this state, false for off + simulation_state, // State dial we use to control the on/off + CulturalIcon::BurningState); // State that we look for + Register_Object(undamaged_state); + break; + } + case L4VideoObject::Rubble: + { + #if DEBUG_LEVEL > 0 + StateInstanceSwitchRenderable *undamaged_state = + #endif + new StateInstanceSwitchRenderable( + entity, // Entity to attach the renderable to + StateInstanceSwitchRenderable::Watcher, // How/when to execute the renderable + this_instance, // the instance to control + True, // true to turn on in this state, false for off + simulation_state, // State dial we use to control the on/off + CulturalIcon::BurningState); // State that we look for + Register_Object(undamaged_state); + break; + } + } + //---------------------------------- + // billboard object if so indicated + //---------------------------------- + if (this_DCS && (renderer_modes & L4VideoObject::BillboardObject)) + { + int + axes = dpl_reorient_axes_none; + + if (renderer_modes & L4VideoObject::BillboardXAxis) + { + axes |= dpl_reorient_axes_x; + } + if (renderer_modes & L4VideoObject::BillboardYAxis) + { + axes |= dpl_reorient_axes_y; + } + if (renderer_modes & L4VideoObject::BillboardZAxis) + { + axes |= dpl_reorient_axes_z; + } + dpl_SetDCSReorientAxes(this_DCS, (dpl_REORIENT_AXES)axes); + dpl_FlushDCS(this_DCS); + } + } + break; + } + // + // Case to handle rivets using the fast projectile code + // + case RivetClassID: + { + dpl_OBJECT + *this_object; + video_iterator.First(); + video_wrapper = video_iterator.ReadAndNext(); + Check(video_wrapper); + video_object = video_wrapper->GetVideoObject(); + Check_Pointer(video_object); + object_filename = video_object->GetObjectFilename(); + this_object = dpl_LoadObject(object_filename, dpl_load_normal); + #if DEBUG_LEVEL > 0 + ProjectileRootRenderable *projectile = + #endif + new ProjectileRootRenderable( + entity, // Entity to attach the renderable to + ProjectileRootRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + dplMainZone); // DPL Zone this stuff will live in (for culling) + Register_Object(projectile); + break; + } + // + // Script for generating renderables for eyecandy + // + case EyeCandyClassID: + { + int effect_number; + + RootRenderable *this_root = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Dynamic, // How/when to execute the renderable + NULL, // object to hang on the DCS, may be a list later + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL); // intersection mask for the object + Register_Object(this_root); + StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState"); + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + effect_number = atoi(video_object->GetObjectFilename()); + #if DEBUG_LEVEL > 0 + DPLSFXRenderable *this_effect = + #endif + new DPLSFXRenderable( + entity, // Entity to attach the effect to + dplMainZone, // DPL zone everything will be in + Point3D::Identity, // Point offset from the parent DCS + this_root->GetDCS(), // Parent DCS (can be NULL for world) + simulation_state, // Trigger effect when this state changes + EyeCandy::effectOn, // Trigger effect when in this state + effect_number, // Type of effect to trigger + .01); // Effect repeat speed. + Register_Object(this_effect); + } + break; + } + // + // Script for generating an explosion of type specified in the resource file + // + case ExplosionClassID: + { + int effect_number; + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + effect_number = atoi(video_object->GetObjectFilename()); + if(effect_number < 100 || effect_number >= 1000) + { + DPLIndependantEffect( + entity->localOrigin.linearPosition, + effect_number); + } + else + { + ExplosionScripts( + entity, // The entity we are dealing with + model_resource, // Pointer to the video resource + view_type, // Type of reference (inside/outside...etc.) + effect_number - 100); + } + } + break; + } + case CameraDirectorClassID: + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the CameraDirector HUD Renderable if not a Replicant + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (entity->GetInstance() == CameraDirector::MasterInstance) + { + CameraDirector *camera_director = (CameraDirector*) entity; + Check_Pointer(camera_director); + + int *player_index = &camera_director->goalPlayerIndex; + Check_Pointer(player_index); + + Logical *display_rank_window = &camera_director->displayRankingWindow; + Check_Pointer(display_rank_window); + + #if DEBUG_LEVEL > 0 + CameraShipHUDRenderable *my_camera_hud = + #endif + new CameraShipHUDRenderable( + entity, + CameraShipHUDRenderable::Dynamic, + player_index, + display_rank_window + ); + Register_Object(my_camera_hud); + } + break; + } + // + // Script for a drivable camera, the camera is invisible to other players + // + case CameraShipClassID: + { + if(view_type == insideEntity) + { + // + // Build an empty root renderable and an eye renderable + // + RootRenderable *this_root = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Dynamic, // How/when to execute the renderable + NULL, // object to hang on the DCS, may be a list later + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL); // intersection mask for the object + Register_Object(this_root); + + #if DEBUG_LEVEL > 0 + DPLEyeRenderable* this_eye = + #endif + new DPLEyeRenderable( + entity, + dplMainZone, + LinearMatrix::Identity, + this_root->GetDCS(), + dplMainView, + NULL + ); + Register_Object(this_eye); + } + break; + } + // + // Script for doorframe, so it can be used in any game + // + case DoorFrameClassID: + { + Verify( object_count == 6 ); + //------------------------------------------------ + // First video object is root shape for the door + // followed by left door shape, right door shape, + // door lights, left door lights, and right door + // lights. + //------------------------------------------------ + dpl_OBJECT + *object, + *left, + *right, + *object_lights, + *left_lights, + *right_lights; + int object_number = 0; + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + object_filename = video_object->GetObjectFilename(); + + #if NOISY_RENDERER + Tell("L4VIDEO.cpp loading door object "<GetSubsystem(0); + Point3D* left_door_position = &left_door_sub->currentPosition; + Door *right_door_sub = (Door*) entity->GetSubsystem(1); + Point3D* right_door_position = &right_door_sub->currentPosition; + RootRenderable *door_sill = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Static, // How/when to execute the renderable + object, // object to hang on the DCS, may be a list later + dplMainZone, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL); // intersection mask for the object + Register_Object(door_sill); + // + // Set my_root_dcs because we want this guy's hiearchy to be marked + // with his entity pointer + // + my_root_dcs = door_sill->GetDCS(); + LinearMatrix my_ident(True); + DPLChildPointRenderable* left_door = + new DPLChildPointRenderable( + entity, + dplMainZone, + left, + dpl_isect_mode_obj, + NULL, + my_ident, + door_sill->GetDCS(), + left_door_position); + Register_Object(left_door); + DPLChildPointRenderable* right_door = + new DPLChildPointRenderable( + entity, + dplMainZone, + right, + dpl_isect_mode_obj, + NULL, + my_ident, + door_sill->GetDCS(), + right_door_position); + Register_Object(right_door); + #if DEBUG_LEVEL > 0 + DCSInstanceRenderable *door_sill_lights_instance = + #endif + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + object_lights, // object to connect to the instance + door_sill->GetDCS(), // the DCS to add the instance to + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + True); // initial visibility setting + Register_Object(door_sill_lights_instance); + #if DEBUG_LEVEL > 0 + DCSInstanceRenderable *left_door_lights_instance = + #endif + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + left_lights, // object to connect to the instance + left_door->GetDCS(), // the DCS to add the instance to + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + True); // initial visibility setting + Register_Object(left_door_lights_instance); + #if DEBUG_LEVEL > 0 + DCSInstanceRenderable *right_door_lights_instance = + #endif + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + right_lights, // object to connect to the instance + right_door->GetDCS(), // the DCS to add the instance to + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + True); // initial visibility setting + Register_Object(right_door_lights_instance); + break; + } + // + // This is the script run on anything that isn't already listed above + // + default: + { + dpl_OBJECT + *this_object; + dpl_ISECT_MODE + intersect_mode; + uint32 + intersect_mask; + LinearMatrix + offset_matrix = LinearMatrix::Identity; + dpl_DCS + *root_DCS, + *this_DCS; + // + // First, establish that this level doesn't know what to do + // if the object has no video resource. + // + if (!model_resource) + { + VideoRenderer::MakeEntityRenderables(entity, model_resource, view_type); + Entity_Being_Created = NULL; + return; + } + // + // If we're inside the entity, set up the intersect mode and mask so we + // won't intersect ourselves with the pickpoint. Other items get full + // geometry intersection. + // + if (view_type == insideEntity) + { + intersect_mode = dpl_isect_mode_obj; + intersect_mask = NULL; + } + else + { + intersect_mode = dpl_isect_mode_geometry; + intersect_mask = INTERSECT_ALL; + } + + Logical + first_object = True; + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + object_filename = video_object->GetObjectFilename(); + resource_type = video_object->GetResourceType(); + renderer_modes = video_object->GetRendererModes(); + + #if NOISY_RENDERER + Tell("L4VIDEO.cpp loading object " << object_filename); + Tell(" type " << resource_type); + Tell(" mode 0x" <IsDerivedFrom(Mover::ClassDerivations)) + { + // + // It's a mover, construct it with a dynamic root renderable so it can move + // also remember it's DCS so we can hook other shapes to it later. + // + SET_VIDEO_CONSTRUCT_ROOT(); + RootRenderable *this_root = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + dplMainZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + Register_Object(this_root); + CLEAR_VIDEO_CONSTRUCT_ROOT(); + + root_DCS = this_root->GetDCS(); + } + else + { + // + // It's a static, construct it with a static RootRenderable and + // remember it's DCS so we can hook other shapes to it later. + // + RootRenderable *this_static_root = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Static, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + dplMainZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + Register_Object(this_static_root); + root_DCS = this_static_root->GetDCS(); + } + // + // Set my_root_dcs because we want this guy's hiearchy to be marked + // with his entity pointer + // + my_root_dcs = root_DCS; + // + // If we are inside the entity, then we must build an eyepoint for it too. + // since there is no special construction, we build the eyepoint with a + // zero offset. + // + if (view_type == insideEntity) + { + EulerAngles *eyepoint_rotation = + (EulerAngles *)entity->GetAttributePointer("EyepointRotation"); + #if DEBUG_LEVEL > 0 + DPLEyeRenderable *this_eye = + #endif + new DPLEyeRenderable( + entity, + dplMainZone, + LinearMatrix::Identity, + root_DCS, + dplMainView, + eyepoint_rotation); + Register_Object(this_eye); + } + //------------------------------------------------------ + // if root object billboards (all others billboard too) + //------------------------------------------------------ + this_DCS = root_DCS; + } + else + { + if (renderer_modes | L4VideoObject::BillboardObject) + { + //------------------------------------------ + // attach additional object to separate DCS + // because it is billboarded + //------------------------------------------ + DPLStaticChildRenderable *this_child = + new DPLStaticChildRenderable( + entity, + dplMainZone, + this_object, + intersect_mode, + intersect_mask, + offset_matrix, + root_DCS); + Register_Object(this_child); + this_DCS = this_child->GetDCS(); + } + else + { + //---------------------------------------- + // attach additional objects to root_DCS + // (HACK) temporary implementation (HACK) + //---------------------------------------- + #if DEBUG_LEVEL > 0 + DCSInstanceRenderable *another_instance = + #endif + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + this_object, // object to connect to the instance + root_DCS, // the DCS to add the instance to + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + True); // initial visibility setting + Register_Object(another_instance); + this_DCS = NULL; + } + } + //---------------------------------- + // billboard object if so indicated + //---------------------------------- + if (this_DCS && (renderer_modes & L4VideoObject::BillboardObject)) + { + int + axes = dpl_reorient_axes_none; + + if (renderer_modes & L4VideoObject::BillboardXAxis) + { + axes |= dpl_reorient_axes_x; + } + if (renderer_modes & L4VideoObject::BillboardYAxis) + { + axes |= dpl_reorient_axes_y; + } + if (renderer_modes & L4VideoObject::BillboardZAxis) + { + axes |= dpl_reorient_axes_z; + } + dpl_SetDCSReorientAxes(this_DCS, (dpl_REORIENT_AXES)axes); + dpl_FlushDCS(this_DCS); + } + } + break; + } + } + // + // release the video chain memory + // + L4VideoObjectWrapper::DeleteVideoObjectChain(&video_chain); + // + // Clear the entity pointer passed to the callback system + // + Entity_Being_Created = NULL; + // + // If my_root_dcs is non-null, mark the entity's DCS hiearchy with it's + // entity pointer. + // + if(my_root_dcs) + { + MarkDCSHiearchy(my_root_dcs,entity); +#if 0 + if(entity->GetClassID() == DemolitionPackClassID) + { + Point3D temp_point(0.0,0.0,0.0); + #if DEBUG_LEVEL > 0 + OnePSFXRenderable *this_effect= + #endif + new OnePSFXRenderable( + entity, // Entity to attach the renderable to + OnePSFXRenderable::Static, // How/when to execute the renderable + myPSFXDescriptons[3], // name of file with the PFX description in it + my_root_dcs, // DCS the effect is relative to (may be NULL) + &temp_point); // Offset (or world coordinants if DCS is NULL) + Register_Object(this_effect); + } +#endif + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This should be called prior to the rendering of a frame to setup the culling +// data the renderer keeps (mostly the world to eye transform) +// +void + DPLRenderer::SetupCull() +{ + Entity + *linked_entity; + LinearMatrix + site_to_world, + world_to_site, + eye_rotation, + eye_inverted; + EntitySegment + *eyepoint_segment; + EulerAngles + *eyepoint_rotation; + // + // To test the functionality, this is not as efficient as it could be. + // when it gets fully patched into the renderer it will be improved. + // + // Figure out what type of entity this is. + // + linked_entity = GetLinkedEntity(); + eyepoint_rotation = (EulerAngles*)linked_entity->GetAttributePointer("EyepointRotation"); + if(linked_entity->IsDerivedFrom(JointedMover::ClassDerivations)) + { + JointedMover + *linked_jointed_mover; + + linked_jointed_mover = Cast_Object(JointedMover*, linked_entity); + eyepoint_segment = linked_jointed_mover->GetSegment("siteeyepoint"); + if(!eyepoint_segment) + { + Fail("DPLRenderer::SetupCull jointed mover had no siteeyepoint\n"); + } + if(!eyepoint_rotation) + { + Fail("DPLRenderer::SetupCull jointed mover had no EyepointRotation attribute\n"); + } + linked_jointed_mover->GetSegmentToWorld(*eyepoint_segment, &site_to_world); + if(eyepoint_rotation) + { + world_to_site.Invert(site_to_world); + eye_rotation = *eyepoint_rotation; + eye_inverted.Invert(eye_rotation); + worldToEyeMatrix.Multiply(world_to_site, eye_inverted); + } + else + { + worldToEyeMatrix.Invert(site_to_world); + } + } + else + { + site_to_world = linked_entity->localOrigin; + if(eyepoint_rotation) + { + world_to_site.Invert(site_to_world); + eye_rotation = *eyepoint_rotation; + eye_inverted.Invert(eye_rotation); + worldToEyeMatrix.Multiply(world_to_site, eye_inverted); + } + else + { + worldToEyeMatrix.Invert(site_to_world); + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void + DPLRenderer::ResetStatistics() +{ + total_cull = 0; + total_draw = 0; + total_pixelplanes = 0; + total_frame_time = 0; + frame_count = 0; + target_frame_time = 56000; + target_frame_count= 0; + report_time = currentFrameTime + 60.0f; +} +void + DPLRenderer::ReportStatistics() +{ + if(frame_count != 0) + { + cout<<"Frames "<GetApplicationState(); + if(application->GetApplicationState() != lastAppState) + { + switch(current_app_state) + { + case Application::RunningMission: + dpl_SetViewFog( + dplMainView, + dpl_fog_type_pixel_lin, + fogRed, + fogGreen, + fogBlue, + fogNear, + fogFar ); + dpl_FlushView(dplMainView); + dpl_DisableSyncOnCreate(); + break; + case Application::StoppingMission: +#if 0 + dpl_SetViewFog( + dplMainView, + dpl_fog_type_pixel_lin, + 0.0, + 0.0, + 0.0, + 0.1, + 0.2 ); + dpl_FlushView(dplMainView); +#endif + break; + } + lastAppState = current_app_state; + } +// +// !!!! This may be the WRONG place to do this, but we'll try it +// + // extern dpl_INSTANCE *dpl_SectPixel(dpl_VIEW *, float32, float32, uint32, + // float32 *, float32 *, float32 *, + // dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); + // extern dpl_INSTANCE *dpl_RapidSectPixel(float32, float32, float32, uint32, + // float32 *, float32 *, float32 *, + // dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); + // + // If there is a reticle pointer defined, do the pickpoint processing + // + SET_VIDEO_PICKPOINT(); + if(vehicleReticle) + { + // + // Check the reticle structure to make sure it's ok, then see if pick + // point processing is turned on. + // + Check(vehicleReticle); + if(vehicleReticle->pickPointingOn) + { + // + // Remember the last thing we were targeted on, then go ahead and do the + // intersection call. + // + #if PRINT_PICKPOINT_TEST + old_instance = dplHitInstance; + old_damage_zone = vehicleReticle->targetDamageZone; + #endif + #if RAPID_SECT_PIXEL + dplHitInstance = dpl_RapidSectPixel ( + (((vehicleReticle->reticlePosition.x*aspectRatio)/2.0) + 0.5), // go from reticle coordinant system + (((vehicleReticle->reticlePosition.y*aspectRatio)/2.0) + 0.5), // to the screen coordinant system. + 1.0e5, + INTERSECT_ALL, + &vehicleReticle->rayIntersection.x, + &vehicleReticle->rayIntersection.y, + &vehicleReticle->rayIntersection.z, + &dplHitDCS, + &dplHitGeoGroup, + &dplHitGeometry); + #else + dplHitInstance = dpl_SectPixel ( + dplMainView, + (vehicleReticle->reticlePosition.x/2.0) + 0.5, // go from reticle coordinant system + (vehicleReticle->reticlePosition.y/2.0) + 0.5, // to the screen coordinant system. + INTERSECT_ALL, + &vehicleReticle->rayIntersection.x, + &vehicleReticle->rayIntersection.y, + &vehicleReticle->rayIntersection.z, + &dplHitDCS, + &dplHitGeoGroup, + &dplHitGeometry); + #endif + } + else + { + // + // When pickpoint is off, we should return something sensable + // + dplHitInstance = 0; + } + // + // Set the reticle variables based on whether we hit anything or not + // + if(dplHitInstance) + { + #if PARTICLE_TEST + DPLIndependantEffect( + vehicleReticle->rayIntersection, + 1); + #endif + vehicleReticle->targetEntity = (Entity *)dpl_GetAppSpecific(dplHitDCS); + #if USE_TRACKER_STRUCTURE + this_tracker = (dpl_tracker *)dpl_GetAppSpecific(dplHitGeoGroup); + #endif + if(dpl_GetAppSpecific(dplHitGeoGroup)) + { + #if USE_TRACKER_STRUCTURE + vehicleReticle->targetDamageZone = this_tracker->Damage_Zone_Number; + #else + vehicleReticle->targetDamageZone = ((int)dpl_GetAppSpecific(dplHitGeoGroup))-1; + #endif + +// vehicleReticle->targetEntity = this_tracker->This_Entity; + } + else + { + vehicleReticle->targetDamageZone = -1; +// vehicleReticle->targetEntity = NULL; + } + } + else + { + vehicleReticle->targetDamageZone = -1; + vehicleReticle->targetEntity = NULL; + } + + #if PRINT_PICKPOINT_TEST + //------------------------------------------ + // code for testing and debugging pickpoint + //------------------------------------------ + // If the object we are targeted on changes, we will print out the data + if(dplHitInstance) + { + if( old_instance != dplHitInstance || old_damage_zone != vehicleReticle->targetDamageZone) + { + cout<<"instance app specific="<targetEntity) + cout<<"Target Class="<targetEntity->GetClassID()<<"\n"; + #if USE_TRACKER_STRUCTURE + cout<<"Damage zone #="<targetDamageZone<<" "<dz_name<<"\n"; + #else + cout<<"Damage zone #="<targetDamageZone<<"\n"; + #endif + } + } + #endif + } + CLEAR_VIDEO_PICKPOINT(); + // + // Setup the video culling system, this generates the world to eye matrix for + // the currently linked entity and sets the current frame time to Now() + // + #if VIDEO_CULLING + SET_VIDEO_CULL_SETUP(); + SetupCull(); + CLEAR_VIDEO_CULL_SETUP(); + #endif + // + // If we've asked the system to count renderables, setup the total count + // + SET_VIDEO_RENDERABLES(); + #if COUNT_RENDERABLES + int + renderable_socket_count; + renderable_socket_count = 0; + #endif + // + // Execute all the dynamic renderables attached to this renderer. + // + SChainIteratorOf renderable_iterator(&dplRenderableSocket); + while ((component = renderable_iterator.ReadAndNext()) != NULL) + { + #if COUNT_RENDERABLES + renderable_socket_count++; + #endif + SET_VIDEO_ALL_RENDERABLES(); + component->Execute(); + CLEAR_VIDEO_ALL_RENDERABLES(); + } + // + // Flip trace for all renderables and report renderable count if enabled + // + CLEAR_VIDEO_RENDERABLES(); + #if COUNT_RENDERABLES + cout<<"dplRenderableSocket "<ReadAndNext()) != NULL) + { + // + // If enabled, flip this trace on vehicle or player renderables + // + #if defined(TRACE_VIDEO_VEHICLE_RENDERABLES) + if( entity->GetClassID() == MechClassID || + entity->GetClassID() == VTVClassID || + entity->GetClassID() == BTPlayerClassID) + { + SET_VIDEO_VEHICLE_RENDERABLES(); + } + #endif + // + // Create an iterator to iterate over all the dynamic video components + // in this entity. If renderable counting is turned on, initialize + // a counter for this entities renderables + // + Entity::DynamicVideoSocketIterator component_iterator(entity); + component_count=0; + // + // Iterate through all the dynamic video components for this entity + // + while ((component = component_iterator.ReadAndNext()) != NULL) + { + // + // Execute each of the entities components + // + SET_VIDEO_ALL_RENDERABLES(); + component->Execute(); + CLEAR_VIDEO_ALL_RENDERABLES(); + component_count++; + } + // + // If renderable counting is on, report how many renderables this entity + // had and update the totals + // + if(component_count != 0) + { + cout<<"Class "<GetClassID()<<" had "<GetClassID() == MechClassID || + entity->GetClassID() == VTVClassID || + entity->GetClassID() == BTPlayerClassID) + { + CLEAR_VIDEO_VEHICLE_RENDERABLES(); + } + #endif + } + if(total_components != 0) + cout<<"Renderables in entity sockets "<GetSize()<<" in the all iterator\n"; + #endif + // + // Do a batch DCS flush if we need to + // + DPLDoDCSBatchFlush(); + // + // We use the complete cycle handler to take care of calling DrawScene as soon as + // the renderer completes the the frame it's working on. + // + completeCycleNeeded = True; + CLEAR_VIDEO_RENDERER(); + + CompleteCycle(); +} +// +//############################################################################# +// DPLDelayDCSFlush and DPLDoDCSBatchFlush queue up a list of DCS pointers +// for later flushing in one big batch. +//############################################################################# +// +void + DPLRenderer::DPLDelayDCSFlush( + dpl_DCS *my_dcs) // The DCS we want to remember for later +{ + // + // Make sure the array hasn't become overfilled somehow and make + // sure the DCS is valid. + // + Verify(delayedDCSCount <= DELAY_DCS_FLUSH_ARRAY_SIZE); + Check_Pointer(my_dcs); + // + // If the array is full, flush it out to make space for this DCS + // + if(delayedDCSCount == DELAY_DCS_FLUSH_ARRAY_SIZE) + { + DPLDoDCSBatchFlush(); + } + // + // Add the New DCS to the list + // + delayDCSFlushArray[delayedDCSCount++] = my_dcs; +} +void + DPLRenderer::DPLDoDCSBatchFlush() // Flush the dcs's remembered by DPLDelayDCSFlush +{ + SET_VIDEO_BATCH_FLUSH(); + // + // Make sure the array hasn't become overfilled somehow + // + Verify(delayedDCSCount <= DELAY_DCS_FLUSH_ARRAY_SIZE); + // + // Flush the array and reset the counters that go with it + // + if(delayedDCSCount != 0) + { + delayDCSFlushArray[delayedDCSCount] = NULL; + dpl_FlushDCSArticulations(delayDCSFlushArray); + delayedDCSCount = 0; + } + CLEAR_VIDEO_BATCH_FLUSH(); +} +// +//############################################################################# +// DPLReportFreeMemory writes current free memory in graphics card to any +// output stream. +//############################################################################# +// +void + DPLRenderer::DPLReportFreeMemory(ostream &output) +{ + output << "Free memory in card: " << dpl_FreeMemory() << " bytes." << endl; + return; +} +// +//############################################################################# +// DPLReportPerfStats writes performance statistics to cout (stdout). +//############################################################################# +// +void + DPLRenderer::DPLReportPerfStats(ostream &output) +{ + //----------------------------------------------------- + // HACK - copied from camera.c must re-copy if changed + // + // case '?': + // printf ("sect time %d dcs 0x%x inst 0x%x\n", + // __sect_time, sect_dcs, sect_inst ); + //----------------------------------------------------- + output << "sect time " << __sect_time << + " dcs and inst not available" << endl; + + //------------------------------------------------------------ + // HACK - copied from dpl_vpx.c must re-copy if changed + // + // void dpl_PerfStats(void) + // printf ( "cull %d draw %d frame %d pxpl %d prims %d\n", + // __last_cull_time, + // __last_draw_time, + // __last_frame_time, + // __last_pxpl_time, + // __last_frame_prims ); + //------------------------------------------------------------ + output << + "cull " << __last_cull_time << + " draw " << __last_draw_time << + " frame " << __last_frame_time << + " pxpl " << __last_pxpl_time << + " prims " << __last_frame_prims << + endl; + if(statistics_started) + { + ReportStatistics(); + } + else + { + ResetStatistics(); + statistics_started = True; + } + return; +} +// +//############################################################################# +// DPLToggleWireframe toggles the state of dpl global wireframe. +//############################################################################# +// +void + DPLRenderer::DPLToggleWireframe() +{ + static Logical wireframe_on = 0; + + if ((wireframe_on ^= 1) != 0) + { + DEBUG_STREAM << "wireframe ON" << endl; + dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_on, NULL ); + } + else + { + DEBUG_STREAM << "wireframe OFF" << endl; + dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_off, NULL ); + } +} +// +//############################################################################# +// DPLTogglePVision toggles the state of dpl "predator" vision. +//############################################################################# +// +void + DPLRenderer::DPLTogglePVision() +{ + static Logical pvision_on = 0; + dpl_EXPLOSION_EFFECT_INFO sfx_info; + + sfx_info.x = sfx_info.y = sfx_info.z = 0; + if ((pvision_on ^= 1) != 0) + { + DEBUG_STREAM << "pvision ON" << endl; + sfx_info.type = -1; + } + else + { + DEBUG_STREAM << "pvision OFF" << endl; + sfx_info.type = -2; + } + dpl_Effect(dpl_effect_type_explosion, NULL, &sfx_info); + return; +} +// +//############################################################################# +// DPLFrameDump writes screen image to targa file. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// oneD_filter() antialiased framegrab support +void + oneD_filter( + uint32 *linebuffer, + unsigned short *rframe, + unsigned short *gframe, + unsigned short *bframe, + int32 y, + int32 x_size + ) +{ + int32 + pos, + i, + r, g, b; + unsigned char + *clinebuf = (unsigned char *)linebuffer; + + pos = y * x_size; + + for (i=0; i> 8) & 0xff); + *clinebuf++ = (unsigned char)((g >> 8) & 0xff); + *clinebuf++ = (unsigned char)((b >> 8) & 0xff); + } + return; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// dump_frame_buffer() +void + dump_frame_buffer( + dpl_VIEW *eye, + int32 x_size, + int32 y_size, + Logical antialias + ) +{ + //do not check eye here + + //---------------------------------------- + // control variable and operating buffers + //---------------------------------------- + static uint32 + dumped_frames = 0, + *line_buffer = NULL; + static unsigned short + *rframebuffer = NULL, + *gframebuffer = NULL, + *bframebuffer = NULL; + + if (eye == NULL) + { + //-------------------------- + // release allocated memory + //-------------------------- + if (line_buffer) + { + Unregister_Pointer(line_buffer); + delete line_buffer; + } + if (rframebuffer) + { + Unregister_Pointer(rframebuffer); + delete rframebuffer; + } + if (gframebuffer) + { + Unregister_Pointer(gframebuffer); + delete gframebuffer; + } + if (bframebuffer) + { + Unregister_Pointer(bframebuffer); + delete bframebuffer; + } + return; + } + Check_Pointer(eye); + + //----------------------------------------------------------------- + // AA kernel definition: + // + // normalized screen coordinates are -1.0 .. +1.0 + // these map (in NTSC) to 705 and 512. + // So a pixel in x is + // 2.0 / 704 = 2.841e-3 + // in y = 3.906e-3 + // for the re-use 5-sample kernel we displace by 0.5 pixels ... + //----------------------------------------------------------------- + static const int32 kernel_size = 4; + + static const float xk = 2.0f / x_size; + static const float yk = 2.0f / y_size; + static const float ox = xk / 4.0f; + static const float oy = yk / 4.0f; + static const float jx = 0.0f; // ox / 4.0f + static const float jy = 0.0f; // oy / 4.0f + + static const float x_kernel[4] = { -(ox+jx), ox-jx, jx-ox, jx+ox }; + static const float y_kernel[4] = { oy-jy, oy+jy, -(jy+oy), jy-oy }; + static const int kernel_weights[4] = { 64, 64, 64, 64 }; + + //--------------------- + // operating variables + //--------------------- + int32 passes = (antialias)?kernel_size:1; + int32 size = x_size * y_size; + int32 frameptr; + int32 i, x, y; + + DEBUG_STREAM << "Dump frame buffer (antialias=" << + ((antialias)?"True":"False") << ") - press Esc to cancel." << endl; + + //---------------------------- + // allocate operating buffers + //---------------------------- + if (line_buffer == NULL) + { + //----------------------------------------------------------------------- + // NOTE - must call dump_frame_buffer(NULL, NULL, NULL, NULL) to release + //----------------------------------------------------------------------- + line_buffer = new uint32[1024]; + Register_Pointer(line_buffer); + rframebuffer = new unsigned short[size]; + Register_Pointer(rframebuffer); + gframebuffer = new unsigned short[size]; + Register_Pointer(gframebuffer); + bframebuffer = new unsigned short[size]; + Register_Pointer(bframebuffer); + } + + //------------------------------ + // clear out r g b framebuffers + //------------------------------ + frameptr = 0; + for (i=0; i> 8) & 0xff); + tga_hdr[14] = (unsigned char)(y_size & 0xff); + tga_hdr[15] = (unsigned char)((y_size >> 8) & 0xff); + + tga_hdr[16] = 0x18; + tga_hdr[17] = 0x00; + + DEBUG_STREAM << "Writing image to file '" << fname << "' . . . "; + fp = fopen(fname, "wb"); + fwrite(tga_hdr, 18, 1, fp); + + for (y=0; y report_time) + { + ReportStatistics(); + report_time = currentFrameTime + 60.0f; + } + } + #if DEBUG_LEVEL > 0 + // + // Code to try and measure average frame rate + // Only active for builds above d0 + // + current = Now(); + FrameCount ++; + if((current - StartSample) > 10.0f) + { + float frame_rate; + frame_rate = FrameCount / (current-StartSample); + if(frame_rate < 28.0f) + printf("%4.2f fps\n", frame_rate); + StartSample = Now(); + FrameCount = 0; + } + #endif + // + // We've started the next frame, so indicate we don't need to do this again. + // + completeCycleNeeded = False; + CLEAR_VIDEO_RENDERER_FRAME_DONE(); + return True; + } + CLEAR_VIDEO_RENDERER_FRAME_DONE(); + } + return False; +} +// +//############################################################################# +// DPLIndependantPFX lets you start up an effect in absolute space that is +// run to termination automatically by the renderer. +//############################################################################# +// +void + DPLRenderer::DPLIndependantPFX( + Point3D location, // Location in space to trigger the effect + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // Description of the pfx + dpl_DCS *my_DCS, // Optional DCS to link to + int subid) // inserted into third byte of effect id. + +{ + // we put our id into the lower 16 bits because (at least) the upper 8 bits are flags + // HACK...for testing pfx bug + + dpl_PARTICLESTART_EFFECT_INFO + tempParticle; + tempParticle = *psfx_definition; + tempParticle.identifier = (psfx_definition->identifier & 0xffff0000) | GetUniqueID() | ((subid<<16) & 0x00ff0000); + tempParticle.px = location.x; + tempParticle.py = location.y; + tempParticle.pz = location.z; + dpl_Effect ( dpl_effect_type_particlestart, my_DCS, &tempParticle ); +// cout<<"psfx identifier used was "<= 1000) + { + effect_number -= 1000; + if(effect_number < 0 || effect_number > MAX_PSFX_COUNT-1) + { + Fail("PSFX id number was not in the allowed range"); + } + DPLIndependantPFX(location,myPSFXDescriptons[effect_number],my_DCS,subid); + return; + } + dpl_EXPLOSION_EFFECT_INFO + my_explosion; + + my_explosion.type = effect_number; + my_explosion.x = location.x; + my_explosion.y = location.y; + my_explosion.z = location.z; + dpl_Effect ( dpl_effect_type_explosion, my_DCS, &my_explosion ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DPLRenderer::SetViewAngle(Degree new_angle) +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Convert From Degree To Radian + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Radian view_angle; + view_angle = new_angle; + viewAngle = view_angle; + viewRatio = tan(viewAngle/2.0f); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Calc Aspect Ratio and Set View Projection + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + aspectRatio = (float) y_size / (float) x_size; + dpl_SetViewProjection ( dplMainView, -1.0f, -aspectRatio, 1.0f, aspectRatio, 1.0f/viewRatio); + dpl_FlushView(dplMainView); +} +// +//############################################################################# +// Startup the implementation of the Division video renderer +//############################################################################# +// +void + DPLRenderer::LoadMissionImplementation(Mission *mission) +{ + Check(this); + Tell("DPLVideoRenderer::StartImplementation has been called\n"); + DPLReadEnvironment(mission); + + LoadNameBitmaps(); +} +//############################################################################## +// Name Bitmap Support +// + +void + DPLRenderer::SortAndReloadNameBitmaps() +{ + Check(this); + + uint32 *worst_case_texels = MakeBitSliceStorage(); + Register_Pointer(worst_case_texels); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Entity Group of Players + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + EntityGroup *player_group = application->GetEntityManager()->FindGroup("Players"); + Check(player_group); + ChainIteratorOf player_iterator(player_group->groupMembers); + Player *current_player; + BitMap *name_bitmap; + while((current_player = (Player*) player_iterator.ReadAndNext() ) != NULL) + { + Check(current_player); + name_bitmap = application->GetCurrentMission()-> + GetLargeNameBitmap(current_player->playerBitmapIndex); + if (name_bitmap && current_player->IsScoringPlayer()) + { + Check(name_bitmap); + LoadBitSliceTexture( + name_bitmap, // MUNGA 1 bit bitmap to load + (current_player->playerRanking + 1), // Position to load bitmap into + worst_case_texels // 8192 longword array for storage of the texmap + ); + } + } + LoadOrdinalBitmaps(worst_case_texels); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Flush all bitmaps down to the card + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + FlushBitSliceTexture(worst_case_texels); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Free the temporary memory the texmaps used + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Unregister_Pointer(worst_case_texels); + free(worst_case_texels); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DPLRenderer::LoadOrdinalBitmaps(unsigned int *worst_case_texels) +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Check if we have a Director on this machine, + // if so, create load the ordinal Bitmaps only + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + // + if ( + (application->GetMissionPlayer()->GetInstance() == CameraDirector::MasterInstance) && + (application->GetMissionPlayer()->IsDerivedFrom(CameraDirector::ClassDerivations)) + ) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make Sure index is in the right place + // in case < 8 players!!!! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int index = 9; + for(int ii=1;ii<5;++ii) + { + // + //~~~~~~~~~~~~~~~~~~ + // Index Starts at 1 + //~~~~~~~~~~~~~~~~~~ + // + BitMap *ordinal_bitmap = application->GetCurrentMission()->GetOrdinalBitmap(ii); + Check(ordinal_bitmap); + LoadBitSliceTexture( + ordinal_bitmap, // MUNGA 1 bit bitmap to load + index, // Position to load bitmap into + worst_case_texels // 8192 longword array for storage of the texmap + ); + ++index; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +unsigned int* + DPLRenderer::MakeBitSliceStorage() +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Allocate some temporary memory + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + uint32 *worst_case_texels = new uint32[128*64]; + if(!worst_case_texels) + { + Fail("Could not allocate RAM for worst case texels\n"); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Zero Out Memory so Empty Texture space is Black + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;ii<8192;++ii) + { + worst_case_texels[ii] = 0; + } + + return worst_case_texels; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DPLRenderer::LoadNameBitmaps() +{ + Check(this); + + uint32 *worst_case_texels = MakeBitSliceStorage(); + Register_Pointer(worst_case_texels); + + int player_count; + player_count = application->GetCurrentMission()->GetPlayerCount(); + Check(application); + Check(application->GetCurrentMission()); + + BitMap *name_bitmap; + for (int ii=0;iiGetCurrentMission()->GetLargeNameBitmap(ii+1); + if (name_bitmap) + { + Check(name_bitmap); + LoadBitSliceTexture( + name_bitmap, // MUNGA 1 bit bitmap to load + ii+1, // Position to load bitmap into + worst_case_texels // 8192 longword array for storage of the texmap + ); + } + } + LoadOrdinalBitmaps(worst_case_texels); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Flush all bitmaps down to the card + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + FlushBitSliceTexture(worst_case_texels); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Free the temporary memory the texmaps used + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Unregister_Pointer(worst_case_texels); + delete[] worst_case_texels; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DPLRenderer::ShutdownImplementation() +{ + Tell("DPLVideoRenderer::StopImplementation has been called\n"); + dpl_EnableSyncOnCreate(); + SChainIteratorOf projectile_iterator(&projectile_list); + TreeIteratorOf cache_iterator(&dplObjectCacheSocket); +#if defined(LAB_ONLY) + cout<<"max projectiles "<objectPointer; + delete my_cache_line; + + // + // Return the object pointer + // + return(object_pointer); +} + +void + DPLRenderer::PutCachedObject( + const CString &object_name, // Name of the object we will cache + dpl_OBJECT *object_pointer) // pointer to the object being cached +{ + // + // Create the cache line data structure + // + #if 0 + typedef PlugOf DPLObjectCacheLine; + + DPLObjectCacheLine *my_cache_line = new DPLObjectCacheLine(object_pointer); + #endif + + DPLObjectCacheLine *my_cache_line = + new DPLObjectCacheLine( + object_name, + object_pointer); + Register_Object(my_cache_line); + + // + // Store this cache line in the cache + // + dplObjectCacheSocket.AddValue(my_cache_line, object_name); + +} +//----------------------------------------------------------------------------- +//--------------------------Projectile Speedup--------------------------------- +//----------------------------------------------------------------------------- +InnerProjectileRenderable* + DPLRenderer::GetProjectile( + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone) // DPL Zone this stuff will live in (for culling) +{ + InnerProjectileRenderable + *return_projectile; + dpl_INSTANCE + *temp_instance; + // + // Are there projectiles in the list? + // + SChainIteratorOf iterator(&projectile_list); + if ((return_projectile = iterator.GetCurrent()) != NULL) + { + // Yes, remove it from the list set it's instance and return it + iterator.Remove(); + temp_instance = return_projectile->GetInstance(); + if(graphical_object != dpl_GetInstanceObject(temp_instance)) + { + dpl_SetInstanceObject (temp_instance, graphical_object); + dpl_FlushInstance (temp_instance); + } + return(return_projectile); + } + else + { + // no, make a new one and return that + InnerProjectileRenderable *projectile = + new InnerProjectileRenderable( + graphical_object, // object to hang on the DCS, may be a list later + this_zone); // DPL Zone this stuff will live in (for culling) + return(projectile); + } + +} +void + DPLRenderer::ReleaseProjectile( + InnerProjectileRenderable* inner_projectile) +{ + // add the projectile back to the list + projectile_list.Add(inner_projectile); +} +//----------------------------------------------------------------------------- +//--------------------------Joint to DCS translator---------------------------- +//----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLJointToDCSTranslator is a class that contains a joint number to dcs +// pointer translation table. This lets a renderer find the dcs that goes +// with a particular segment. +// + DPLJointToDCSTranslator::DPLJointToDCSTranslator( + Entity *entity, // The entity to translate + dpl_DCS *dcs_array[]) // Array of DCS's to translate +{ + JointedMover + *my_jointed_mover; + // + // Make sure this is a jointed mover, then cast the entity pointer over + // + if (entity->IsDerivedFrom(JointedMover::ClassDerivations)) + { + my_jointed_mover = (JointedMover*)entity; + } + else + { + Fail("DPLJointToDCSTranslator was called on an entity NOT a JointedMover\n"); + } + // + // Find out how many joints the entity has, then allocate enough RAM for a + // DCS pointer to every joint. + // + JointSubsystem* joint_subsystem = my_jointed_mover->GetJointSubsystem(); + Check(joint_subsystem); + translation_array = new (dpl_DCS(*[joint_subsystem->GetJointCount()])); + Register_Pointer(translation_array); + // + // Setup to iterate the entity segment table + // + EntitySegment::SegmentTableIterator segment_iterator(my_jointed_mover->segmentTable); + EntitySegment *current_segment; + while ((current_segment = segment_iterator.ReadAndNext()) != NULL) + { + // + // For each segment, see if it has a joint index, if it does, put the + // DCS for that joint into the translation array + // + Check(current_segment); + int joint_index = current_segment->GetJointIndex(); + if(joint_index != -1) + { + translation_array[joint_index] = dcs_array[current_segment->GetIndex()]; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +DPLJointToDCSTranslator::~DPLJointToDCSTranslator() +{ + Unregister_Pointer(translation_array); + delete[] translation_array; + translation_array = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Logical + DPLJointToDCSTranslator::TestInstance() const +{ + return True; +} +//----------------------------------------------------------------------------- +//--------------------------Resource creation support-------------------------- +//----------------------------------------------------------------------------- +//############################################################################# +//############# DPLRenderer::CreateModelVideoStreamResource ############# +//############################################################################# + +ResourceDescription::ResourceID + DPLRenderer::CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories * /*directories*/ + ) +{ + ResourceDescription *res_description = + resource_file->FindResourceDescription( + model_name, + ResourceDescription::VideoModelResourceType + ); + + if (res_description == NULL) + { + NameList *video_entries = model_file->MakeEntryList("video"); + + if (video_entries != NULL) + { + Register_Object(video_entries); + + //---------------------------------------------- + // parse video model data and store in resource + //---------------------------------------------- + Tell("Building video resource for model '" << model_name << "'.\n"); + + NameList::Entry + *entry, + *next_entry; + const char + *entry_name, + *entry_pointer, + *argument_start; + int + length; + char + argument[40], + *argument_pointer; + L4VideoObject::ResourceType + resource_type; + Enumeration //(see L4VideoObject::RendererModes) + renderer_modes; + enum + { + parsing_filename, + seeking_switch, + parsing_switch, + parsing_billboard + } state; + L4VideoObject + *video_object; + L4VideoObjectWrapper + *video_wrapper; + ChainOf + video_chain(NULL); + char + *video_stream, + *video_pointer; + int + object_count; + long + object_size, + stream_length; + + //------------------------------------------------ + // parse each entry in [video] page of model file + //------------------------------------------------ + next_entry = video_entries->GetFirstEntry(); + while (next_entry) + { + entry = next_entry; + Check(entry); + next_entry = entry->GetNextEntry(); // so 'continue' works + entry_name = entry->GetName(); + if (entry_name && *entry_name) + { + //-------------------------------------------- + // could be "skeleton" or "object" or comment + //-------------------------------------------- + if (strcmp(entry_name, "object") == 0) + { + resource_type = L4VideoObject::Object; + } + else if (strcmp(entry_name, "rubble") == 0) + { + resource_type = L4VideoObject::Rubble; + } + else if (strcmp(entry_name, "skeleton") == 0) + { + resource_type = L4VideoObject::Skeleton; + } + else if (Comment_Line(entry_name)) + { + // do nothing - skip comments + continue; + } + else if (strncmp(entry_name, "skeleton", 8) == 0) + { + // do nothing - skip temporary skeleton entries + continue; + } + else if (strncmp(entry_name, "destroyed", 9) == 0) + { + // do nothing - skip destroyed skeleton entries + continue; + } + else if (strncmp(entry_name, "dzm", 3) == 0) + { + // do nothing - skip damage zone material entries + continue; + } + else + { +// resource_type = L4VideoObject::Unknown; + DEBUG_STREAM << "Unknown entry '" << entry_name << + "' in model '" << model_name << "' ignored." << endl; + continue; + } + //--------------------------------- + // parse and process each argument + //--------------------------------- + entry_pointer = entry->GetChar(); + while (entry_pointer && *entry_pointer) + { + //------------------------- + // skip leading whitespace + //------------------------- + while (*entry_pointer != '\0' && isspace(*entry_pointer)) + { + ++entry_pointer; + } + //--------------------------- + // exit loop if nothing left + //--------------------------- + if (*entry_pointer == '\0') + { + break; + } + //------------------------------------------- + // parse the next argument into local buffer + //------------------------------------------- + argument_start = entry_pointer; + while (*entry_pointer != '\0' && !isspace(*entry_pointer)) + { + ++entry_pointer; + } + length = entry_pointer - argument_start; + Verify( length < sizeof(argument) ); + strncpy(argument, argument_start, length); + argument[length] = '\0'; + //---------------------- + // parse local argument + //---------------------- + argument_pointer = argument; + renderer_modes = L4VideoObject::Normal; + state = parsing_filename; + while (*argument_pointer != '\0') + { + switch (state) + { + case parsing_filename: + switch (*argument_pointer) + { + #if 0 + case '.': + if ((resource_type == L4VideoObject::Object) || + (resource_type == L4VideoObject::Rubble)) + { + *argument_pointer = '\0'; // terminate filename + state = seeking_switch; + } + break; + #endif + case '/': + *argument_pointer = '\0'; // terminate filename + state = parsing_switch; + break; + default: + // later check for valid filename character... + break; + } + break; + case seeking_switch: + if (*argument_pointer == '/') + { state = parsing_switch; } + break; + case parsing_switch: + switch (*argument_pointer) + { + case 'b': + case 'B': + state = parsing_billboard; + break; + case 'i': + case 'I': + renderer_modes |= L4VideoObject::IntersectImmune; + state = seeking_switch; + break; + default: + state = seeking_switch; + break; + } + break; + case parsing_billboard: + switch (*argument_pointer) + { + case 'x': + case 'X': + renderer_modes |= L4VideoObject::BillboardXAxis; + break; + case 'y': + case 'Y': + renderer_modes |= L4VideoObject::BillboardYAxis; + break; + case 'z': + case 'Z': + renderer_modes |= L4VideoObject::BillboardZAxis; + break; + case '/': + state = parsing_switch; + break; + default: + state = seeking_switch; + break; + } + break; + // no default: + } + ++argument_pointer; + } + //----------------------------------------------- + // create video resource object and add to chain + //----------------------------------------------- + video_object = + new L4VideoObject( + argument, + resource_type, + renderer_modes + ); + Register_Pointer(video_object); // not _Object! + + video_wrapper = + new L4VideoObjectWrapper( + video_object, + True // delete object when done + ); + Register_Object(video_wrapper); + + //Tell(" adding video object '"< + video_iterator(video_chain); + + object_count = video_iterator.GetSize(); + + object_size = sizeof(L4VideoObject); + stream_length = sizeof(int) + object_count * object_size; + + video_stream = new char[stream_length]; + Register_Pointer(video_stream); + + video_pointer = video_stream; + *((int *)video_pointer) = object_count; + video_pointer += sizeof(int); + + Tell(" count " <GetVideoObject(); + *((L4VideoObject *)video_pointer) = *video_object; + video_pointer += object_size; + } + //-------------------------------------------------- + // store stream of video resources in resource file + //-------------------------------------------------- + res_description = + resource_file->AddResource( + model_name, + ResourceDescription::VideoModelResourceType, + 1, + ResourceDescription::Preload, + video_stream, + stream_length + ); + //-------------------------- + // release allocated memory + //-------------------------- + // video_chain + L4VideoObjectWrapper::DeleteVideoObjectChain(&video_chain); + // video_stream + Unregister_Pointer(video_stream); + delete video_stream; + // video_entries + Unregister_Object(video_entries); + delete video_entries; + } + else + { + //------------------------------- + // no [video] page in model file + //------------------------------- + return (ResourceDescription::NullResourceID); + } + } + return (res_description->resourceID); +} +//===========================================================================// + diff --git a/CODE/RP/MUNGA_L4/L4VIDEO.HPP b/CODE/RP/MUNGA_L4/L4VIDEO.HPP new file mode 100644 index 0000000..f05ca2b --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VIDEO.HPP @@ -0,0 +1,637 @@ +//===========================================================================// +// File: l4video.hpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +// 07/11/95 KEO Modify video resource format. // +// 02/08/96 KEO Add rubble entry to video resource. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995-1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(L4VIDEO_HPP) +# define L4VIDEO_HPP + +# if !defined(VIDREND_HPP) +# include +# endif + +# if !defined(ROTATION_HPP) +# include +# endif + +# if !defined(RETICLE_HPP) +# include +# endif + +# if !defined(GRAPH2D_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(L4VIDRND_HPP) +# include +# endif + +# if !defined(TREE_HPP) +# include +# endif + +# if !defined(TABLE_HPP) +# include +# endif + +#include +#include + + class NotationFile; + +#define INTERSECT_ALL (0xFFFFFFFF) + + //########################################################################## + // Declaration of dpl callback function that performs in-place text + // substitution on all material names before they are looked up. + // There must be at least MATERIAL_NAME_LENGTH bytes available at source! + // +#define MATERIAL_NAME_BUFFER_LENGTH 256 + + char8* + substituteMaterial(char8 *source); + + //########################################################################## + // This structure is attached to DPL nodes so we can put information in them + // on what entity the node is part of and what damage zone it belongs to. + // +#define MAX_DZ_NAME_LENGTH 25 + + struct dpl_tracker + { + Entity + *This_Entity; // The entity this is part of + char + dz_name[MAX_DZ_NAME_LENGTH]; // this is temporary, to make testing easier + int + Damage_Zone_Number; // number of this damage zone + }; + +//----------------------------------------------------------------------------- +//--------------------------DPL video resource object-------------------------- +//----------------------------------------------------------------------------- + //########################################################################## + //########################## L4VideoObject ########################### + //########################################################################## + +#define MAX_OBJECT_FILENAME_LENGTH 15 + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // This class gets stored in a resource so it is derived from nothing. + // + class L4VideoObject + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: + enum ResourceType + { + Unknown, + Skeleton, + Object, + Rubble, + VidFile + }; + enum RendererModes // bit flags + { + Normal = 0x000, + BillboardXAxis = 0x001, + BillboardYAxis = 0x002, + BillboardZAxis = 0x004, + BillboardObject = (BillboardXAxis | BillboardYAxis | BillboardZAxis), + BlinkObject = 0x008, + IntersectImmune = 0x010 + }; + +// L4VideoObject(); + L4VideoObject( + const char *filename, + ResourceType resource_type, + Enumeration renderer_modes, // RendererModes + float blink_period = 0.0f, + float percent_time_on = 0.0f + ); + ~L4VideoObject(); + + const char* + GetObjectFilename() const + { return objectFilename; } + char* + GetObjectFilename() + { return objectFilename; } + ResourceType + GetResourceType() const + { return resourceType; } + Enumeration // RendererModes + GetRendererModes() const + { return rendererModes; } + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Implementations + // +// private: + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + char + objectFilename[MAX_OBJECT_FILENAME_LENGTH]; + ResourceType + resourceType; + Enumeration // RendererModes + rendererModes; // bit flags (see RendererModes) + float + blinkPeriod, // cycle length in seconds + percentTimeOn; // percent of cycle on + }; + + //########################################################################## + //####################### L4VideoObjectWrapper ####################### + //########################################################################## + + class L4VideoObjectWrapper: + public Plug + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction, Destruction and testing + // + public: +// L4VideoObjectWrapper(); + L4VideoObjectWrapper( + L4VideoObject *video_object, + Logical delete_object = False + ); + ~L4VideoObjectWrapper(); + + L4VideoObject* + GetVideoObject() const + { Check(this); return videoObject; } + + Logical + TestInstance() const; + + static int + BuildVideoObjectChainFromResource( + ChainOf *video_chain, + ResourceDescription *video_resource + ); + static void + DeleteVideoObjectChain( + ChainOf *video_chain + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Implementations + // +// public: + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + L4VideoObject + *videoObject; + Logical + deleteObject; + }; + +// +//----------------------------------------------------------------------------- +//--------------Actual DPL video renderer class starts below------------------- +//----------------------------------------------------------------------------- +// + class DPLObjectCacheLine: + public Plug + { + public: + DPLObjectCacheLine( + const CString &object_name, + dpl_OBJECT *object_ptr) + { + objectName = object_name; + objectPointer = object_ptr; + }; + + ~DPLObjectCacheLine(){}; + + Logical + TestInstance() const + { + Check(&objectName); + Check_Pointer(objectPointer); + + return True; + }; + + CString + objectName; + dpl_OBJECT + *objectPointer; + }; + + class DPLJointToDCSTranslator: + public Plug + { + public: + DPLJointToDCSTranslator( + Entity *entity, // The entity to translate + dpl_DCS *dcs_array[]); // Array of DCS's to translate + + ~DPLJointToDCSTranslator(); + + Logical + TestInstance() const; + + int + DCSCount; + dpl_DCS + **translation_array; // array to translate from joint # to DCS* + }; + + //########################################################################## + //########################### DPLRenderer ############################ + //########################################################################## +#define DELAY_DCS_FLUSH_ARRAY_SIZE 100 +#define MAX_PSFX_COUNT 40 + class DPLRenderer: + public VideoRenderer + { + public: + // + // Construction, Destruction and test instance declarations + // + DPLRenderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration); + + ~DPLRenderer(); + + Logical + TestInstance() const; + // + // These routines are the renderer side of the culling system, they are + // used to setup the stored data on the eyepoint's transformation matrices + // + inline Scalar + GetCurrentFrameTime() + {return(currentFrameTime);} // Returns the time at the start of the frame + + inline LinearMatrix* + GetWorldToEyeMatrix() + {return(&worldToEyeMatrix);} // Returns the world to eye matrix (for culling) + inline Scalar + GetViewRatio() + {return(viewRatio);} // Returns tan(viewAngle/2.0) + void + SetupCull(); // Sets up the WorldToEyeMatrix each frame + // + // These routines manage the renderer's list of renderables that need to be + // executed each frame. For the moment these routines just blindly add and + // remove the items from the dplRenderableSocket + // + void + AddDynamicRenderable(Component *my_renderable); + void + RemoveDynamicRenderable(Component *my_renderable); + // + // These routines are used for tracking target frame time + // + void + ResetStatistics(); + void + ReportStatistics(); + // + // Other renderer stuff + // + dpl_ZONE* + MakeNewZone(); + + void + MarkDCSHiearchy( + dpl_DCS *root_DCS, + Entity *entity); + void + FlushBitSliceTexture( + unsigned int *local_storage); + void + LoadBitSliceTexture( + BitMap *bitmap_to_load, // MUNGA 1 bit bitmap to load + int load_position, // Position to load bitmap into + unsigned int *local_storage); // 8192 longword array for storage of the texmap + + void + SetViewAngle(Degree new_angle); + + unsigned int* + MakeBitSliceStorage(); + + void + SortAndReloadNameBitmaps(); + + void + LoadNameBitmaps(); + + void + LoadOrdinalBitmaps(unsigned int *local_storage); + + void + DPLIndependantEffect( + Point3D location, // Location of the effect in world space + int effect_number, // DPL effect number to trigger at this location + dpl_DCS *my_dcs = NULL, + int subid = 0); // inserted into third byte of effect id. + + void + DPLIndependantPFX( + Point3D location, // Location in space to trigger the effect + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // Description of the pfx + dpl_DCS *my_dcs = NULL, // optional DCS to issue from + int subid = 0); // inserted into third byte of effect id. + + void + DPLDelayDCSFlush( + dpl_DCS *my_dcs); // The DCS we want to remember for later + + void + DPLDoDCSBatchFlush(); // Flush the dcs's remembered by DPLDelayDCSFlush + + void + DPLReportFreeMemory(ostream &output); // Report current free memory in card + + void + DPLReportPerfStats(ostream &output); // Report performance statistics + + void + DPLToggleWireframe(); // Toggle state of dpl wireframe + + void + DPLTogglePVision(); // Toggle state of dpl pvision + + void + DPLFrameDump(Logical antialias); // Write framedump to targa file + + Logical + CompleteCycle(); + + InnerProjectileRenderable* + GetProjectile( + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone); // DPL Zone this stuff will live in (for culling) + + void + ReleaseProjectile( + InnerProjectileRenderable *inner_projectile); + + int + GetUniqueID(); + + dpl_PARTICLESTART_EFFECT_INFO* + ReadPSFX( + const char *file_name); // Name of the file containing the PSFX description + + dpl_OBJECT* + GetCachedObject( + const CString &object_name); // Name of the object we want to get + + void + PutCachedObject( + const CString &object_name, // Name of the object we will cache + dpl_OBJECT *object_pointer); // pointer to the object being cached + + static ResourceDescription::ResourceID + CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories); + + void + CacheExplosionScripts( + int script_select); // The script to be cached + + enum FogStyle + { + updateFogSetting, + noUpdateFogSetting, + searchLightOnFogStyle, + searchLightOffFogStyle, + winnersCircleFogStyle + }; + + void + SetFogStyle(FogStyle my_fog); + + void + GetCurrentFogSettings( + float *fogRed, + float *fogGreen, + float *fogBlue, + float *fogNear, + float *fogFar); + private: + void + ExplosionScripts( + Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom view_type, // Type of reference (inside/outside...etc.) + int script_select); + void + DPLRenderer::DPLReadINIPage( + NotationFile *master_notation_file, + const char *starting_page_name, + Mission *mission, + Logical debug_print); + + void + DPLRenderer::DPLReadEnvironment(Mission *mission); + void + ShutdownImplementation(); + void + SuspendImplementation(); + void + ResumeImplementation(); + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + + + protected: + + void + LoadMissionImplementation(Mission *mission); + + // + // These variables hold some culling related information + // + + LinearMatrix + worldToEyeMatrix; // the current world to eye transform for our linked entity + Scalar + currentFrameTime; // the time at the start of renderable execution + + // + // These variables are used for tracking target frame time + // + unsigned long + total_cull, + total_draw, + total_pixelplanes, + total_frame_time, + target_frame_time, + frame_count, + target_frame_count; + Logical + statistics_started; + Scalar + report_time; + // + // The rest of the renderer's variables. + // + + Time + StartSample; // For generating a framerate printout + + Logical + fogUpdating, + eyeRelative, // True if the eye will be relative to the linked entity origin + completeCycleNeeded; // True when we are waiting for DPL to be ready for the next frame + + int + myUniqueID, // Generates a unique 16 bit id value for PSFX use + lastAppState; // For keeping track of what the application is doing + + float + aspectRatio, // aspect ratio of the screen + FrameCount, // For keeping track of framerate + // Fog is setup as standard fog used for vehicles without simulated lights + // and used when a vehicle with lights has them switched on. This setting + // is replicated into the "noSearchLight" setting so vehicles with lights + // will always get this setting if the environment doesn't specifically say + // that headlight simulation will work. + fogRed, // Fog setting to use when vehicle lights are on + fogBlue, // This is the default for vehicles with no lights + fogGreen, + fogNear, + fogFar, + searchLightFogRed, // Fog setting to use when vehicle lights are on + searchLightFogBlue, + searchLightFogGreen, + searchLightFogNear, + searchLightFogFar, + noSearchLightFogRed, // Fog setting to use when vehicle lights are off + noSearchLightFogBlue, + noSearchLightFogGreen, + noSearchLightFogNear, + noSearchLightFogFar, + clipNear, // Near clipping plane (from INI file) + clipFar, // Far clipping plane (from INI file) + backgroundRed, // Background color (from INI file) + backgroundGreen, + backgroundBlue, + viewAngle, // Viewing angle (from INI file) + viewRatio; // This is tan(viewAngle/2.0f) (handy for culling) + + dpl_DCS + *dplTestEyeDCS; // A DCS we temporarily hook our eye on (for testing) + + void + MakeEntityRenderables( + Entity *this_entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom type); // Type of reference (inside/outside...etc.) + + dpl_VIEW + *dplMainView; // The DPL view we create at the beginning and use for our eye + + dpl_ZONE + *dplDeathZone, // The DPL zone that holds our vehicle (for death effect) + *dplMainZone; // The DPL zone that holds the rest of the world + + Reticle + *vehicleReticle; // Pointer to our vehicle's reticle if one exists. + + dpl_DCS + *delayDCSFlushArray[DELAY_DCS_FLUSH_ARRAY_SIZE+1]; + int + delayedDCSCount; + dpl_PARTICLESTART_EFFECT_INFO + *myPSFXDescriptons[MAX_PSFX_COUNT]; + // + // This information is captured from the pickpoint when it is enabled + // + dpl_INSTANCE + *dplHitInstance; + dpl_DCS + *dplHitDCS; + dpl_GEOGROUP + *dplHitGeoGroup; + dpl_GEOMETRY + *dplHitGeometry; + // + // This information holds the list of projectile renderables + // + SChainOf + projectile_list; + // + // This holds the list of cached objects + // + TreeOf + dplObjectCacheSocket; + // + // This holds the list of jointed mover DCS tables + // + TableOf + dplJointToDCSTranslatorSocket; + // + // This chain contains the list of active renderables + // + SChainOf + dplRenderableSocket; + +public: + // + // Store Lights for Later Revision + // + dpl_LIGHT + *ambientLight, + **sceneLight; // Array of all the lights + + dpl_DCS + **sceneLightDCS; // Array of DCS's for Lights + + int + sceneLightCount; + + static UserHeap + *DPLHeap; + }; + +#endif + +//===========================================================================// + diff --git a/CODE/RP/MUNGA_L4/L4VIDEO.TCP b/CODE/RP/MUNGA_L4/L4VIDEO.TCP new file mode 100644 index 0000000..1ca787c --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VIDEO.TCP @@ -0,0 +1,75 @@ +//===========================================================================// +// File: vidrend.tst // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "entity.thh" + +Logical + VideoRenderer::TestClass() + +{ + + Tell("Starting VideoRenderer::TestClass\n"); +#if 0 +// Create the message that will be used to make my entities + + TestEntity::MakeMessage + message1( + TestEntity::MakeMessageID, + sizeof(TestEntity::MakeMessage), + TestEntity::TrivialEntityClassID, + TestEntity::DefaultFlags, + LinearOrigin::Identity + ); + +// Send the message that creates the entity in Entity_1 + + message1.localOrigin.translation.z = -30.0f; + + Entity* Entity_1 = TestEntity::Make(&message1); + + Register_Object(Entity_1); + + // Push the origin in the message forward 30 meters + + message1.localOrigin.translation.z = 30.0f; + + // Create the second entity 30 meters in front of the first + + Entity* Entity_2 = TestEntity::Make(&message1); + + Register_Object(Entity_2); + +// create more + + message1.localOrigin.translation.z = 0.0f; + message1.localOrigin.translation.x = 30.0f; + Entity* Entity_3 = TestEntity::Make(&message1); + Register_Object(Entity_3); + + + message1.localOrigin.translation.x = -30.0f; + Entity* Entity_4 = TestEntity::Make(&message1); + Register_Object(Entity_4); + + message1.localOrigin.translation.x = 0.0f; + message1.localOrigin.translation.y = 30.0f; + Entity* Entity_5 = TestEntity::Make(&message1); + Register_Object(Entity_5); + + message1.localOrigin.translation.y = -30.0f; + Entity* Entity_6 = TestEntity::Make(&message1); + Register_Object(Entity_6); +#endif + return False; +} diff --git a/CODE/RP/MUNGA_L4/L4VIDPER.CPP b/CODE/RP/MUNGA_L4/L4VIDPER.CPP new file mode 100644 index 0000000..e01ce0f --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VIDPER.CPP @@ -0,0 +1,484 @@ +//===========================================================================// +// File: l4vidper.cpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video performance monitoring tools // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/5/96 GAC initial coding // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include "l4munga.hpp" +#if !defined(L4VIDPER_HPP) +# include "l4vidper.hpp" +#endif + +extern "C" const int32 __sect_time; +extern "C" const int32 __last_cull_time; +extern "C" const int32 __last_draw_time; +extern "C" const int32 __last_frame_time; +extern "C" const int32 __last_pxpl_time; +extern "C" const int32 __last_frame_prims; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the StripChartRenderable +// Used to performance monitor a variable that can change every frame +// +StripChartRenderable::StripChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int *value_to_chart, // the value we will be graphing + int update_interval // How frequently (in frames) to update the graphics +): + VideoRenderable(entity, execution_type) +{ + int + i; + // + // Save the incoming data inside this class + // + myView = this_view; + myLeft = left; + myRight = right; + myTop = top; + myBottom = bottom; + myMaxSamples = max_samples; + myMaxValue = max_value; + myMinValue = min_value; + myValue = value_to_chart; + myUpdateInterval = update_interval; + myFrameCount = 0; + myCurrentSample = 0; + // + // Allocate the RAM to store the values we are charting and clear them out + // + myValueStorage = new int[max_samples]; + if(!myValueStorage) + Fail("stripchart couldn't allocate value storage\n"); + + Check_Pointer(myValueStorage); + for(i = 0; i= myUpdateInterval) + { + myFrameCount = 0; + // + // Figure the scale factor for the graph + // + float + current_x, + current_y, + x_increment, + y_increment; + x_increment = (myRight - myLeft)/ (float)(myMaxSamples); + y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue); + dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear); + dpl2d_AddFullScreenClipRegion (myDisplayList); + dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f); + dpl2d_AddOpenPolyline (myDisplayList); + dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + dpl2d_AddPoint (myDisplayList, myRight, myBottom); + dpl2d_AddPoint (myDisplayList, myRight, myTop); + dpl2d_AddPoint (myDisplayList, myLeft, myTop); + dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + dpl2d_AddClosePolyline (myDisplayList); + dpl2d_AddOpenPolyline (myDisplayList); + current_x = myLeft; + for(i = 0; i < myMaxSamples; i++) + { + current_y = myBottom-((float)myValueStorage[i] * y_increment); + dpl2d_AddPoint(myDisplayList,current_x,current_y); + current_x += x_increment; + } + dpl2d_AddClosePolyline (myDisplayList); + dpl2d_AddOpenLines (myDisplayList); + dpl2d_AddPoint (myDisplayList, + myLeft + (x_increment*myCurrentSample), + myBottom); + dpl2d_AddPoint (myDisplayList, + myLeft + (x_increment*myCurrentSample), + myTop); + dpl2d_AddCloseLines (myDisplayList); + dpl2d_CloseDisplayList (myDisplayList); + dpl2d_FlushDisplayList (myDisplayList); + } + // + // Update the current sample pointer + // + myCurrentSample ++; + if(myCurrentSample >= myMaxSamples) + myCurrentSample = 0; + + // + // Call the execute method in our parent + // + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the RendererChartRenderable +// Used to performance monitor a variable that can change every frame +// +RendererChartRenderable::RendererChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int update_interval // How frequently (in frames) to update the graphics +): + VideoRenderable(entity, execution_type) +{ + int + i; + // + // Save the incoming data inside this class + // + myView = this_view; + myLeft = left; + myRight = right; + myTop = top; + myBottom = bottom; + myMaxSamples = max_samples; + myMaxValue = max_value; + myMinValue = min_value; + myUpdateInterval = update_interval; + myFrameCount = 0; + myCurrentSample = 0; + // + // Allocate the RAM to store the values we are charting and clear them out + // + myCullStorage = new int[max_samples]; + myDrawStorage = new int[max_samples]; + myFrameStorage = new int[max_samples]; + myPixelPlanesStorage = new int[max_samples]; + myPrimativeStorage = new int[max_samples]; + if(!myCullStorage || !myDrawStorage || !myFrameStorage || !myPixelPlanesStorage || !myPrimativeStorage) + Fail("RendererChartRenderable couldn't allocate storage\n"); + + Check_Pointer(myValueStorage); + for(i = 0; i= myUpdateInterval) + { + myFrameCount = 0; + // + // Figure the scale factor for the graph + // + float + current_x, + current_y, + x_increment, + y_increment; + x_increment = (myRight - myLeft)/ (float)(myMaxSamples); + y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue); + dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear); + dpl2d_AddFullScreenClipRegion (myDisplayList); + dpl2d_AddSetLineWidth (myDisplayList,1.0); + dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f); + dpl2d_AddOpenPolyline (myDisplayList); + dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + dpl2d_AddPoint (myDisplayList, myRight, myBottom); + dpl2d_AddPoint (myDisplayList, myRight, myTop); + dpl2d_AddPoint (myDisplayList, myLeft, myTop); + dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + dpl2d_AddClosePolyline (myDisplayList); + // + // Draw the primative count trace + // + dpl2d_AddOpenLines (myDisplayList); + dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (500.0f * y_increment * 50.0f)); + dpl2d_AddPoint(myDisplayList,myRight, myBottom + (500.0f * y_increment * 50.0f)); + dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (1000.0f * y_increment * 50.0f)); + dpl2d_AddPoint(myDisplayList,myRight, myBottom + (1000.0f * y_increment * 50.0f)); + dpl2d_AddCloseLines (myDisplayList); + dpl2d_AddOpenPolyline (myDisplayList); + current_x = myLeft; + for(i = 0; i < myMaxSamples; i++) + { + current_y = myBottom+((float)myPrimativeStorage[i] * y_increment * 50.0f); + dpl2d_AddPoint(myDisplayList,current_x,current_y); + current_x += x_increment; + } + dpl2d_AddClosePolyline (myDisplayList); + // + // Draw the frame time trace + // + dpl2d_AddSetColor (myDisplayList, 0.75f, 0.75f, 0.75f); + dpl2d_AddOpenPolyline (myDisplayList); + current_x = myLeft; + for(i = 0; i < myMaxSamples; i++) + { + current_y = myBottom-((float)myFrameStorage[i] * y_increment); + dpl2d_AddPoint(myDisplayList,current_x,current_y); + current_x += x_increment; + } + dpl2d_AddClosePolyline (myDisplayList); + // + // Draw the draw time trace + // + dpl2d_AddSetColor (myDisplayList, 0.75f, 0.0f, 0.0f); + dpl2d_AddOpenPolyline (myDisplayList); + current_x = myLeft; + for(i = 0; i < myMaxSamples; i++) + { + current_y = myBottom-((float)myDrawStorage[i] * y_increment); + dpl2d_AddPoint(myDisplayList,current_x,current_y); + current_x += x_increment; + } + dpl2d_AddClosePolyline (myDisplayList); + // + // Draw the pixel planes time trace + // + dpl2d_AddSetColor (myDisplayList, 0.0f, 0.0f, 0.75f); + dpl2d_AddOpenPolyline (myDisplayList); + current_x = myLeft; + for(i = 0; i < myMaxSamples; i++) + { + current_y = myBottom-((float)myPixelPlanesStorage[i] * y_increment); + dpl2d_AddPoint(myDisplayList,current_x,current_y); + current_x += x_increment; + } + dpl2d_AddClosePolyline (myDisplayList); + // + // Stack the cull time on top of the draw + // + dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f); + dpl2d_AddOpenPolyline (myDisplayList); + current_x = myLeft; + for(i = 0; i < myMaxSamples; i++) + { + current_y = myBottom-(((float)myCullStorage[i] + (float)myDrawStorage[i]) * y_increment); + dpl2d_AddPoint(myDisplayList,current_x,current_y); + current_x += x_increment; + } + dpl2d_AddClosePolyline (myDisplayList); + // + // Draw a line indicating the current time + // + dpl2d_AddOpenLines (myDisplayList); + dpl2d_AddPoint (myDisplayList, + myLeft + (x_increment*myCurrentSample), + myBottom); + dpl2d_AddPoint (myDisplayList, + myLeft + (x_increment*myCurrentSample), + myTop); + dpl2d_AddCloseLines (myDisplayList); + // + // If there is a pre existing dlist, insert a call to it here + // + if(mySystemDisplayList) + { + dpl2d_AddCallDisplayList (myDisplayList, mySystemDisplayList ); + } + // + // Close up the display list and flush it + // + dpl2d_CloseDisplayList (myDisplayList); + dpl2d_FlushDisplayList (myDisplayList); + } + // + // Update the current sample pointer + // + myCurrentSample ++; + if(myCurrentSample >= myMaxSamples) + myCurrentSample = 0; + + // + // Call the execute method in our parent + // + VideoRenderable::Execute(); +} diff --git a/CODE/RP/MUNGA_L4/L4VIDPER.HPP b/CODE/RP/MUNGA_L4/L4VIDPER.HPP new file mode 100644 index 0000000..5e2c8d6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VIDPER.HPP @@ -0,0 +1,148 @@ +//===========================================================================// +// File: l4vidper.hpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video performance monitoring renderables// +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/05/96 GAC initial code // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4VIDPER_HPP) +# define L4VIDPER_HPP + +# if !defined(L4VIDRND_HPP) +# include "l4vidrnd.hpp" +# endif + +# if !defined(ROTATION_HPP) +# include +# endif + +# if !defined(RETICLE_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(LINMTRX_HPP) +# include +# endif + +#include +#include +#include + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// StripChartRenderable +// + class StripChartRenderable: + public VideoRenderable + { + public: + StripChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int *value_to_chart, // the value we will be graphing + int update_interval); // How frequently (in frames) to update the graphics + + ~StripChartRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_VIEW + *myView; + dpl2d_DISPLAY + *mySystemDisplayList, + *myDisplayList; + int + myMaxSamples, + myMaxValue, + myMinValue, + *myValue, + *myValueStorage, + myUpdateInterval, + myFrameCount, + myCurrentSample; + float + myLeft, + myRight, + myTop, + myBottom; + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RendererChartRenderable +// + class RendererChartRenderable: + public VideoRenderable + { + public: + RendererChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int update_interval); // How frequently (in frames) to update the graphics + + ~RendererChartRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_VIEW + *myView; + dpl2d_DISPLAY + *mySystemDisplayList, + *myDisplayList; + int + *myCullStorage, + *myDrawStorage, + *myFrameStorage, + *myPixelPlanesStorage, + *myPrimativeStorage, + myMaxSamples, + myMaxValue, + myMinValue, + myUpdateInterval, + myFrameCount, + myCurrentSample; + float + myLeft, + myRight, + myTop, + myBottom; + + }; + + +#endif \ No newline at end of file diff --git a/CODE/RP/MUNGA_L4/L4VIDRND.CPP b/CODE/RP/MUNGA_L4/L4VIDRND.CPP new file mode 100644 index 0000000..dbebff0 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VIDRND.CPP @@ -0,0 +1,6725 @@ +//===========================================================================// +// File: l4vidrnd.cpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 07/08/95 GAC Took renderables out of l4video and moved them here // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4VIDRND_HPP) +# include +#endif + +#if !defined(VECTOR2D_HPP) +# include +#endif + +#if !defined(MATRIX_HPP) +# include +#endif + +#if !defined(MOVER_HPP) +# include +#endif + +#if !defined(PLAYER_HPP) +# include +#endif + +#if !defined(L4VIDEO_HPP) +# include +#endif + +#if !defined(NTTMGR_HPP) +# include +#endif + +#if !defined(l4APP_HPP) +# include +#endif + +#include +#include +#include +#include +#include + +#if defined(TRACE_VIDEO_MECH_CULL_RENDERABLE) + static BitTrace Video_Mech_Cull_Renderable("Video Mech Cull Renderable"); + #define SET_VIDEO_MECH_CULL_RENDERABLE() Video_Mech_Cull_Renderable.Set() + #define CLEAR_VIDEO_MECH_CULL_RENDERABLE() Video_Mech_Cull_Renderable.Clear() +#else + #define SET_VIDEO_MECH_CULL_RENDERABLE() + #define CLEAR_VIDEO_MECH_CULL_RENDERABLE() +#endif + +// +// Below allows the use of DPLDelayDCSFlush to be on or off +// +#if 1 +# define HACK_DPL_FLUSH_DCS(a)\ + {L4Application *l4_application = Cast_Object(L4Application*, application);\ + Check(l4_application);\ + l4_application->GetVideoRenderer()->DPLDelayDCSFlush(a);} +# define DPL_FLUSH_DCS(a)\ + {myRenderer->DPLDelayDCSFlush(a);} +#else +# define DPL_FLUSH_DCS(a)\ + dpl_FlushDCS(a) +# define HACK_DPL_FLUSH_DCS(a)\ + dpl_FlushDCS(a) +#endif + +// +// All renderables that need to use "Now()" should use renderer frame time +// as it should be much quicker (it returns the time at the start of the +// frame execution. All the renderables should know which renderer they belong +// to, but since many don't, this macro will supply the time from the default one +// +#define GET_CURRENT_FRAME_TIME() \ +{L4Application *l4_application = Cast_Object(L4Application*, application);\ +Check(l4_application);\ +l4_application->GetVideoRenderer()->GetCurrentFrameTime();} + +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +// All the stuff between these big ugly bars is the new video component stuff// +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~This is a special class to speed up projectiles~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for InnerProjectileRenderable +// +InnerProjectileRenderable::InnerProjectileRenderable( + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone // DPL Zone this stuff will live in (for culling) +): + Component(TrivialNodeClassID) // Inherited constructor +{ + // + // Check incoming data + // + Check_Pointer(this_zone); + Check_Pointer(graphical_object); + // + // Construct the hiearchy the projectile needs to be renderable + // + myDCS = dpl_NewDCS (); + myInstance = dpl_NewInstance(); + Check_Pointer (myDCS); + Check_Pointer (myInstance); + dpl_SetDCSZone (myDCS, this_zone); + dpl_SetInstanceObject (myInstance, graphical_object); + dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj ); + dpl_SetInstanceSectMask (myInstance, NULL ); + dpl_SetInstanceVisibility (myInstance, 1 ); + dpl_AddInstanceToDCS (myDCS, myInstance ); + dpl_AddDCSToScene (myDCS ); + dpl_FlushInstance (myInstance); + dpl_FlushDCS (myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for InnerProjectileRenderable +// +InnerProjectileRenderable::~InnerProjectileRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Delete the instance(s) hanging on the DCS (if any) + // NOTE: we may want to iterate through all the instances here using DPL routines + // + dpl_RemoveInstanceFromDCS(myDCS, myInstance); + dpl_RemoveDCSFromScene(myDCS); + dpl_DeleteInstance(myInstance); + // + // Delete the DCS + // + dpl_DeleteDCS(myDCS); + myDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the InnerProjectileRenderable +// +Logical + InnerProjectileRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + Component::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myInstance); + Check_Pointer(myDCS); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ProjectileRootRenderable +// +ProjectileRootRenderable::ProjectileRootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone // DPL Zone this stuff will live in (for culling) +): +VideoRenderable(entity, execution_type) +{ + // + // Check the incoming pointers + // + Check_Pointer(graphical_object); + Check_Pointer(this_zone); + // + // Get a projectile renderable we can use + // + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + myInnerProjectile = l4_application->GetVideoRenderer()->GetProjectile( + graphical_object, + this_zone); + Check(myInnerProjectile); + // + // Set the DCS matrix and flush it + // + float32* tempMatrix = dpl_GetDCSMatrix( myInnerProjectile->GetDCS()); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = myEntity->localToWorld; + DPL_FLUSH_DCS ( myInnerProjectile->GetDCS()); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ProjectileRootRenderable +// +ProjectileRootRenderable::~ProjectileRootRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // return our inner renderable to the pool + // + Point3D infinity(0.0f, 10000.0f, 0.0f); + float32* tempMatrix = dpl_GetDCSMatrix(myInnerProjectile->GetDCS()); + Check_Pointer (tempMatrix); + *(Matrix4x4*)tempMatrix = infinity; + DPL_FLUSH_DCS ( myInnerProjectile->GetDCS() ); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->ReleaseProjectile(myInnerProjectile); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ProjectileRootRenderable +// +Logical + ProjectileRootRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check(&oldLocalToWorld); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ProjectileRootRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ProjectileRootRenderable::Execute() +{ + + // + // Check our variables + // + Check(this); + // + // If our entity has changed it's localToWorld matrix, update DPL + // + if(oldLocalToWorld != myEntity->localToWorld) + { + oldLocalToWorld = myEntity->localToWorld; + float32* tempMatrix = dpl_GetDCSMatrix(myInnerProjectile->GetDCS()); + Check_Pointer (tempMatrix); + *(Matrix4x4*)tempMatrix = oldLocalToWorld; + DPL_FLUSH_DCS ( myInnerProjectile->GetDCS() ); + } + // + // Call the next lower execute method + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLObjectWrapper +// +DPLObjectWrapper::DPLObjectWrapper( + Entity *entity, // Entity to attach the renderable to + const CString &name, // Name of the DPL object to load into the wrapper + dpl_LOAD_MODE cache_mode // DPL Zone this stuff will live in (for culling) +): +VideoRenderable(entity, DPLObjectWrapper::Static) +{ + // + // Check the incoming pointers + // + Check(&name); + // + // Load the DPL object into the wrapper, try to get the object pointer from + // the cache, if it isn't there, do a regular load. + // + if(cache_mode == dpl_load_nocache) + { + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + myDPLObject = l4_application->GetVideoRenderer()->GetCachedObject(name); + if(!myDPLObject) + { + myDPLObject = dpl_LoadObject(name, cache_mode); + } + } + else + { + myDPLObject = dpl_LoadObject(name, cache_mode); + } + myCacheMode = cache_mode; + myDPLObjectName = name; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLObjectWrapper +// +DPLObjectWrapper::~DPLObjectWrapper() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Handle the unloading of DPL objects + // + if(myCacheMode == dpl_load_nocache) + { + // + // If this object was not cached, we will eventually return it to the video + // renderer's list of unused uncached objects for later use by someone else + // + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->PutCachedObject(myDPLObjectName, myDPLObject); + } + else + { + // + // Do nothing (should unload the object) + // + //dpl_UnloadObject(myDPLObject); + } + myDPLObject = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLObjectWrapper +// +Logical + DPLObjectWrapper::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myDPLObject); + Check(&myDPLObjectName); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLObjectWrapper +// Nothing to execute here so we just pass it down to the next lower level. +// +void + DPLObjectWrapper::Execute() +{ + + // + // Check our variables + // + Check(this); + // + // Call the next lower execute method + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~New Class Hiearchy for Renderables~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for VideoRenderable +// +VideoRenderable::VideoRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type // How/when to execute the renderable +): + Component(TrivialNodeClassID) // Inherited constructor +{ + // + // Check incoming data + // + Check(entity); + // + // Remember the entity and execution type + // + myEntity = entity; + myExecutionType = execution_type; + // + // HACK HACK HACK + // This initializes the video renderable's pointer back to the renderer that + // owns it so it can get information from that renderer. The renderer pointer + // really should be passed in as an argument, this is a concession to avoid + // spending the time to edit all references to the renderer so they support + // a new argument. This will be fixed later, for now we know there is only + // on renderer so we grab the application pointer and get the video renderer + // from it. + // + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + myRenderer = l4_application->GetVideoRenderer(); + // + // Register us as static or dynamic + // + switch(myExecutionType) + { + case Static: + myEntity->AddStaticVideoComponent(this); + break; + case Dynamic: +// myEntity->AddDynamicVideoComponent(this); + myEntity->AddStaticVideoComponent(this); + myRenderer->AddDynamicRenderable(this); + break; + case Watcher: + myEntity->AddStaticVideoComponent(this); + break; + case Dependant: + myEntity->AddStaticVideoComponent(this); + break; + default: + Fail("VideoRenderable--Illegal execution type\n"); + break; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for VideoRenderable +// +VideoRenderable::~VideoRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Nothing else to do here + // +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the VideoRenderable +// +Logical + VideoRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + Component::TestInstance(); + // + // Test our own variables + // + Check(myEntity); + Check(myRenderer); + Verify(myExecutionType >= Static && myExecutionType <= Dependant); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the VideoRenderable +// This method just checks to be sure we are not trying to execute a static +// renderable, then returns. +// +void + VideoRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Make sure we are not trying to execute a static renderable + // + #if DEBUG_LEVEL > 0 + if(myExecutionType == Static) + { + Fail("VideoRenderable--someone executed a STATIC renderable\n"); + } + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the ChildLightRenderable +// +// This renderable is used to connect a light as a child of an existing DCS +// the light isn't setup to move on it's own and creates a DCS only for the +// purpose of offsetting it from it's parent. +// +ChildLightRenderable::ChildLightRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Scalar red, // light color + Scalar green, + Scalar blue, + Scalar inner_radius, + Scalar outer_radius, + dpl_LIGHT_TYPE light_type, + int light_mask +): + VideoRenderable(entity, execution_type) +{ + // + // Check the inbound data + // + Check_Pointer(this_zone); + Check_Pointer(parent_DCS); + Check(offset_matrix); + // + // Remember the interesting parameters + // + myZone = this_zone; + myParentDCS = parent_DCS; + myOffsetMatrix = *offset_matrix; + // + // Create the dpl DCS and the light that we will be using + // + myDCS = dpl_NewDCS (); + myLight = dpl_NewLight(); + Check_Pointer(myDCS); + Check_Pointer(myLight); + // + // Setup light type and color + // + dpl_SetLightType (myLight, light_type ); + dpl_SetLightColor (myLight, red, green, blue ); + dpl_SetLightDCS (myLight, myDCS ); + dpl_SetLightRadii (myLight, inner_radius, outer_radius ); + dpl_SetLightLightingMask (myLight, light_mask); + // + // Connect the DCS just created to a parent + // + dpl_AddDCSToDCS ( myParentDCS, myDCS ); + // + // Set the DCS into the requested zone for culling + // + dpl_SetDCSZone ( myDCS, this_zone ); + // + // Load up the DCS matrix with the supplied matrix + // + float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + Check_Pointer(tempMatrix); + *(Matrix4x4*)tempMatrix = myOffsetMatrix; + // + // Flip the light around to point the correct direction + // +// dpl_RotateDCS ( myDCS, 180.0f, dpl_Y ); + // + // Flush out the instance and DCS + // + dpl_FlushLight ( myLight); + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ChildLightRenderable +// +ChildLightRenderable::~ChildLightRenderable() +{ + Check(this); + dpl_DeleteDCS(myDCS); + dpl_DeleteLight(myLight); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ChildLightRenderable +// +Logical + ChildLightRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer(myDCS); + Check_Pointer(myParentDCS); + Check_Pointer(myLight); + Check(&myOffsetMatrix); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for ChildLightRenderable +// +void + ChildLightRenderable::Execute() +{ + // This might eventually handle turning the light on and off + + // + // Call the next lower execute method + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DCSObjectRenderable +// +DCSObjectRenderable::DCSObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask // intersection mask for the object +): + VideoRenderable(entity, execution_type) +{ + // + // Check incoming data + // + #if DEBUG_LEVEL > 0 + if(graphical_object) + Check_Pointer(graphical_object); // allowed to be null + #endif + Check_Pointer(this_zone); + // + // Remember my dpl object, intersect and offset data + // + myDPLObject = graphical_object; + myDPLZone = this_zone; + myIntersectMode = intersect_mode; + myIntersectMask = intersect_mask; + myDCS = NULL; + myInstance = NULL; + // + // We need to construct a DCS node here and remember it. The next class up is + // expected to handle the flushing and connecting of structure so we just setup + // the DCS and zone information here, leaving flushing to someone else. + // + myDCS = dpl_NewDCS (); + + Check_Pointer ( myDCS ); + dpl_SetDCSZone ( myDCS, myDPLZone ); + // + // Construct the instance(s) and hang them on the DCS. Since we may be building + // more than one instance, we have to take care of flushing them here. + // + if(myDPLObject) + { + myInstance = dpl_NewInstance(); + + Check_Pointer ( myInstance); + dpl_SetInstanceObject ( myInstance, myDPLObject); + dpl_SetInstanceIntersect ( myInstance, myIntersectMode ); + dpl_SetInstanceSectMask ( myInstance, myIntersectMask ); + dpl_SetInstanceVisibility ( myInstance, 1 ); + dpl_AddInstanceToDCS ( myDCS, myInstance ); + + dpl_FlushInstance ( myInstance ); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DCSObjectRenderable +// +DCSObjectRenderable::~DCSObjectRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Delete the instance(s) hanging on the DCS (if any) + // NOTE: we may want to iterate through all the instances here using DPL routines + // + if(myInstance) + { + dpl_RemoveInstanceFromDCS(myDCS, myInstance); + dpl_DeleteInstance(myInstance); + } + // + // Delete the DCS + // + dpl_DeleteDCS(myDCS); + myDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DCSObjectRenderable +// +Logical + DCSObjectRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + #if DEBUG_LEVEL > 0 + if(myDPLObject) + Check_Pointer(myDPLObject); + if(myInstance) + Check_Pointer(myInstance); + #endif + Check_Pointer(myDPLZone); + Check_Pointer(myDCS); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DCSObjectRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + DCSObjectRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Call the next lower execute method + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DCSInstanceRenderable +// +DCSInstanceRenderable::DCSInstanceRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to connect to the instance + dpl_DCS *parent_DCS, // the DCS to add the instance to + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + Logical visible // initial visibility setting +): + VideoRenderable(entity, execution_type) +{ + // + // Check incoming data + // + Check_Pointer(graphical_object); + Check_Pointer(parent_DCS); + // + // Remember my dpl object, intersect and offset data + // + myDPLObject = graphical_object; + myIntersectMode = intersect_mode; + myIntersectMask = intersect_mask; + myDCS = parent_DCS; + myInstance = dpl_NewInstance(); + Check_Pointer(myInstance); + // + // Construct the instance(s) and hang them on the parent DCS + // + dpl_SetInstanceObject ( myInstance, myDPLObject); + dpl_SetInstanceIntersect ( myInstance, myIntersectMode ); + dpl_SetInstanceSectMask ( myInstance, myIntersectMask ); + dpl_SetInstanceVisibility ( myInstance, visible ); + dpl_AddInstanceToDCS ( myDCS, myInstance ); + dpl_FlushInstance ( myInstance ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DCSInstanceRenderable +// +DCSInstanceRenderable::~DCSInstanceRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Disconnect the instance from the DCS and delete the instance + // + dpl_RemoveInstanceFromDCS(myDCS, myInstance); + dpl_DeleteInstance(myInstance); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DCSInstanceRenderable +// +Logical + DCSInstanceRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myDPLObject); + Check_Pointer(myInstance); + Check_Pointer(myDCS); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DCSInstanceRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + DCSInstanceRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Call the next lower execute method + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for RootRenderable +// +RootRenderable::RootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask // intersection mask for the object +): +DCSObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask) // intersection mask for the object +{ + // + // All the incoming data will have been checked by DCSObjectRenderable + // already, so we don't have to check anything locally. + // + // + // Initialize our variables + // + oldLocalToWorld = myEntity->localToWorld; + // + // Now we finish the work of hooking up and initializing the root renderable + // Add the DCS to the scene and initialize it's matrix with the localToWorld + // transformation from our entity + // + dpl_AddDCSToScene ( myDCS ); + + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = myEntity->localToWorld; + + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for RootRenderable +// +RootRenderable::~RootRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Remove the DCS from the scene, deletion of the DCS and it's instances is + // handled by our parent class. + // + dpl_RemoveDCSFromScene(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the RootRenderable +// +Logical + RootRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check(&oldLocalToWorld); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the RootRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + RootRenderable::Execute() +{ + + // + // Check our variables + // + Check(this); + // + // If our entity has changed it's localToWorld matrix, update DPL + // + if(oldLocalToWorld != myEntity->localToWorld) + { + oldLocalToWorld = myEntity->localToWorld; + float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + Check_Pointer (tempMatrix); + *(Matrix4x4*)tempMatrix = oldLocalToWorld; + DPL_FLUSH_DCS ( myDCS ); + } + // + // Call the execute method in our parent + // + DCSObjectRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ChildOffsetRenderable +// +ChildOffsetRenderable::ChildOffsetRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix // offset matrix to be applied prior to joint DCS +): +DCSObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask) // intersection mask for the object +{ + // + // Check incoming data not handled by lower levels + // + Check(offset_matrix); + // + // Remember my offset matrix + // + myOffsetMatrix = *offset_matrix; + myOffsetDCS = NULL; + myParentDCS = parent_DCS; + // + // We construct the offset DCS node and link the DCS carrying our our + // graphical instances to it. + // + myOffsetDCS = dpl_NewDCS (); + Check_Pointer ( myOffsetDCS ); + dpl_SetDCSZone ( myDCS, myDPLZone ); + dpl_AddDCSToDCS ( myOffsetDCS, myDCS ); + // + // Now we connect that DCS to our parent + // + dpl_AddDCSToDCS ( myParentDCS, myOffsetDCS); + // + // Then fill in the offset DCS and flush it + // + float32* tempMatrix = dpl_GetDCSMatrix( myOffsetDCS ); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = myOffsetMatrix; + dpl_FlushDCS ( myOffsetDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ChildOffsetRenderable +// +ChildOffsetRenderable::~ChildOffsetRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Delete the connection to our parent DCS + // + dpl_RemoveDCSFromDCS(myParentDCS, myOffsetDCS); + // + // Delete the static DCS and it's connections to the dynamic one + // + dpl_RemoveDCSFromDCS(myOffsetDCS, myDCS); + dpl_DeleteDCS(myOffsetDCS); + myOffsetDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ChildOffsetRenderable +// +Logical + ChildOffsetRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myParentDCS); + Check_Pointer(myOffsetDCS); + Check(&myOffsetMatrix); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ChildOffsetRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ChildOffsetRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Call the next lower execute method + // + DCSObjectRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for HingeRenderable +// +#define SINGLE_AXIS_HINGE True + +HingeRenderable::HingeRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const Hinge *my_hinge // Hinge attribute we will use to control the joint +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + // + // Check the incomming data + // + Check(my_hinge); + // + // Initialize our variables + // + myHinge = my_hinge; + oldHinge = *my_hinge; + // + // Dump the initial value of the hing into the DCS our instances are attached + // to, then flush it out. We have to copy the hinge to a quaternion because + // the math library doesn't support direct assignment of hing to matrix yet. + // +#if SINGLE_AXIS_HINGE + SinCosPair + temp_sin_cos_pair; + temp_sin_cos_pair = myHinge->rotationAmount; + switch(myHinge->axisNumber) + { + case X_Axis: + dpl_SetDCSXAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + case Y_Axis: + dpl_SetDCSYAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + case Z_Axis: + dpl_SetDCSZAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + } +#else + Quaternion + temp_quaternion; + float32 + *temp_matrix; + temp_matrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( temp_matrix ); + temp_quaternion = oldHinge; + *(Matrix4x4*)temp_matrix = temp_quaternion; +#endif + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for HingeRenderable +// +HingeRenderable::~HingeRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the HingeRenderable +// +Logical + HingeRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + // + // Test our own variables + // + Check(myHinge); + Check(&oldHinge); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the HingeRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + HingeRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // If the hinge we're watching has changed, update our matrix + // + if(oldHinge != *myHinge) + { + oldHinge = *myHinge; +#if SINGLE_AXIS_HINGE + SinCosPair + temp_sin_cos_pair; + temp_sin_cos_pair = myHinge->rotationAmount; + switch(myHinge->axisNumber) + { + case X_Axis: + dpl_SetDCSXAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + case Y_Axis: + dpl_SetDCSYAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + case Z_Axis: + dpl_SetDCSZAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + } +#else + Quaternion + temp_quaternion; + float32 + *temp_matrix; + temp_matrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( temp_matrix ); + temp_quaternion = oldHinge; + *(Matrix4x4*)temp_matrix = temp_quaternion; +#endif + DPL_FLUSH_DCS ( myDCS ); + } + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for BallJointRenderable +// +BallJointRenderable::BallJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler // Euler angles to control rotation of the ball joint +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + float32 + *temp_matrix; + // + // Check the incomming data + // + Check(my_euler); + // + // Initialize our variables + // + myEuler = my_euler; + oldEuler = *my_euler; + // + // Dump the initial value of the euler angles into the DCS our instances are attached + // to, then flush it out. + // + temp_matrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( temp_matrix ); + *(Matrix4x4*)temp_matrix = oldEuler; + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for BallJointRenderable +// +BallJointRenderable::~BallJointRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the BallJointRenderable +// +Logical + BallJointRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + // + // Test our own variables + // + Check(myEuler); + Check(&oldEuler); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the BallJointRenderable +// +void + BallJointRenderable::Execute() +{ + float32 + *temp_matrix; + // + // Check our variables + // + Check(this); + // + // If the hinge we're watching has changed, update our matrix + // + if(oldEuler != *myEuler) + { + oldEuler = *myEuler; + temp_matrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( temp_matrix ); + *(Matrix4x4*)temp_matrix = oldEuler; + DPL_FLUSH_DCS ( myDCS ); + } + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for BallTranslateJointRenderable +// +BallTranslateJointRenderable::BallTranslateJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler, // Euler angles to control rotation of the ball joint + const Point3D *my_translation // offset for the translation part of the joint +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + AffineMatrix + tempAffine(True); + + float32 + *temp_matrix; + // + // Check the incomming data + // + Check(my_euler); + Check(my_translation); + // + // Initialize our variables + // + myEuler = my_euler; + oldEuler = *my_euler; + myTranslation = my_translation; + oldTranslation = *my_translation; + // + // Dump the initial value of the euler angles into the DCS our instances are attached + // to, then flush it out. + // + temp_matrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( temp_matrix ); + tempAffine = oldTranslation; + tempAffine = oldEuler; + *(Matrix4x4*)temp_matrix = tempAffine; + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for BallTranslateJointRenderable +// +BallTranslateJointRenderable::~BallTranslateJointRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the BallTranslateJointRenderable +// +Logical + BallTranslateJointRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + // + // Test our own variables + // + Check(myEuler); + Check(&oldEuler); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the BallTranslateJointRenderable +// +void + BallTranslateJointRenderable::Execute() +{ + float32 + *temp_matrix; + // + // Check our variables + // + Check(this); + // + // If the hinge we're watching has changed, update our matrix + // + if(oldEuler != *myEuler || oldTranslation != *myTranslation) + { + oldEuler = *myEuler; + oldTranslation = *myTranslation; + temp_matrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( temp_matrix ); + AffineMatrix tempAffine(True); + tempAffine = oldTranslation; + tempAffine = oldEuler; + *(Matrix4x4*)temp_matrix = tempAffine; + DPL_FLUSH_DCS ( myDCS ); + } + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SpinScaleQuatRenderable +// +SpinScaleQuatRenderable::SpinScaleQuatRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Logical *visible, // turns the object on and off + Scalar z_spin_rate // spins the object about z (radians/frame) +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + // + // Check the inbound data + // + Check(rotation_quaternion); + Check(scale_vector); + Check_Pointer(visible); + // + // Remember the entity that this renderable is attached to and the + // orientation matrix that offsets it to the correct position. + // + myRotationQuaternion = rotation_quaternion; + myScaleVector = scale_vector; + myVisible = visible; + myZSpinRate = z_spin_rate; + OldVisible = *visible; + OldZSpin = 0; + // + // Setup the dcs matrix to it's initial state + // + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= (*myScaleVector); + tempAffine *= (*myRotationQuaternion); + *(Matrix4x4*)tempMatrix = tempAffine; + dpl_FlushDCS ( myDCS ); + // + // Set the instance visibility correctly + // + dpl_SetInstanceVisibility ( myInstance, OldVisible ); + dpl_FlushInstance ( myInstance ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SpinScaleQuatRenderable +// +SpinScaleQuatRenderable::~SpinScaleQuatRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SpinScaleQuatRenderable +// +Logical + SpinScaleQuatRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SpinScaleQuatRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + SpinScaleQuatRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Load up the DCS matrix with the localToWorld matrix from the entity + // then flush out the new DCS + // + if(OldVisible != *myVisible) + { + OldVisible = *myVisible; + dpl_SetInstanceVisibility ( myInstance, OldVisible ); + dpl_FlushInstance ( myInstance ); + } + // + // If the beam is visible, we have to update it + // + if(OldVisible) + { + OldZSpin += myZSpinRate; + if(OldZSpin > TWO_PI) + OldZSpin -= TWO_PI; + Hinge temp_hinge(Z_Axis, OldZSpin); + + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + + AffineMatrix tempAffine(True); + Quaternion temp_quaternion; + temp_quaternion = temp_hinge; + tempAffine = temp_quaternion; + tempAffine *= (*myScaleVector); + temp_quaternion = *myRotationQuaternion; + tempAffine *= temp_quaternion; + *(Matrix4x4*)tempMatrix = tempAffine; + DPL_FLUSH_DCS ( myDCS ); + } + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for POVTranslocateRenderable +// +POVTranslocateRenderable::POVTranslocateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + StateIndicator *effect_trigger, // State dial we use to control the translocation + unsigned effect_control_state // State that controls start/end of the effect +): + VideoRenderable(entity, execution_type) +{ +#define COLLAPSE_TIME 1.0f // Time in seconds for initial collapse +#define COLLAPSE_START_SCALE 30.0f // Scale factor of the sphere when we start collapse +#define EXPAND_TIME 1.0f // Time that expansion of the sphere should take +#define EXPAND_END_SCALE 100.0f // Scale factor of the sphere when expansion ends +#define ROTATE_RATE (0.5f * (0.01745329222222)) +#define ROTATE_LIMIT (20.0f * (0.01745329222222)) +#define TRANSLATE_RATE 0.2f +#define TRANSLATE_LIMIT 2.0f + // HACK HACK HACK this should be removed once red planet is checked out + if(execution_type != Watcher) + cout<<"POVTranslocateRenderable wants to be a watcher and isn't!\n"; + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(this_zone); + Check_Pointer(death_zone); + Check_Pointer(parent_DCS); + Check(effect_trigger); + // + // Remember the entity and DCS this renderable is attached to + // + myZone = this_zone; + myDeathZone = death_zone; + myParentDCS = parent_DCS; + myEffectTrigger = effect_trigger; + myEffectControlState = effect_control_state; + myState = IdleState; + myRotateY = 0.0f; + myRotateYSpeed = TRANSLATE_RATE; + // + // Load up the object we're going to use for the translocation + // + dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere.bgf", dpl_load_normal ); + Check_Pointer(myTranslocateSphere); + // + // Setup a DCS that we can put the sphere on so it can be rotated and scaled + // around the VTV. Attach the sphere to this DCS but make it invisible. + // + myInstance = dpl_NewInstance(); + myDCS = dpl_NewDCS(); + Check_Pointer (myInstance); + Check_Pointer (myDCS); + dpl_AddDCSToDCS (myParentDCS, myDCS); + dpl_SetDCSZone (myDCS, myDeathZone); + dpl_SetInstanceObject (myInstance, myTranslocateSphere); + dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj); + dpl_SetInstanceSectMask (myInstance, NULL); + dpl_SetInstanceVisibility (myInstance, False); + dpl_AddInstanceToDCS (myDCS, myInstance); + dpl_FlushInstance (myInstance); + dpl_FlushDCS (myDCS); + // + // Connect us to the state dial's watcher hook + // + myEffectTrigger->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for POVTranslocationRenderable +// +POVTranslocateRenderable::~POVTranslocateRenderable() +{ + Check(this); + // + // Disconnect the structure we have setup + // + dpl_RemoveDCSFromDCS(myParentDCS, myDCS); + dpl_RemoveInstanceFromDCS(myDCS,myInstance); + // + // Delete the DPL elements we created + // + dpl_DeleteInstance(myInstance); + dpl_DeleteDCS(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the POVTranslocateRenderable +// +Logical + POVTranslocateRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + + Check_Pointer(myZone); + Check_Pointer(myDeathZone); + Check_Pointer(myParentDCS); + Check(myEffectTrigger); + Check_Pointer(myInstance); + Check_Pointer(myDCS); + Verify(myState >= IdleState && myState <= ExpandRevealState); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for POVTranslocateRenderable. +// +void + POVTranslocateRenderable::Execute() +{ + + float32 + *tempMatrix; + Scalar + elapsed_time, + current_time, + percent_time_left, + percent_time_used, + scale_factor; + unsigned + current_trigger_state; + // + // Get the current state and the current time for later use + // + Check(myEffectTrigger); + current_trigger_state = myEffectTrigger->GetState(); + current_time = myRenderer->GetCurrentFrameTime(); + // + // State engine (running off myState) to manage running of the death effect + // +// cout<<"POVTranslocateRenderable::Execute\n"; + switch(myState) + { + // + // IdleState waits for a transition in the effect control state and starts + // the effect state machine when it detects one. + // + case IdleState: + { + if(current_trigger_state == myEffectControlState) + { + myState = InitialCollapseState; + myCollapseEnd = current_time + COLLAPSE_TIME; + dpl_SetInstanceVisibility (myInstance, True); + dpl_FlushInstance (myInstance); + myRenderer->AddDynamicRenderable(this); +// cout<<"POVTranslocateRenderable::Going Dynamic\n"; + } + break; + } + // + // This case handles ending the screen flash when we need to + // + case FlashScreenState: + { + myState = InitialCollapseState; + break; + } + // + // InitialCollapseState handles reducing the sphere from its max size down + // to one over a period of time. We figure the percentage of the time + // left then multiply it by the size the sphere started at to get the + // scale factor. + // + case InitialCollapseState: + { + percent_time_left = (myCollapseEnd - current_time)/COLLAPSE_TIME; + // + // See how much time is left in the effect. + // + if(percent_time_left <= 0.0f) + { + // + // Time's up! Go to WaitForReincarnate state, force scale factor to + // 1.0, and turn off the outside world + // + scale_factor = 1.0f; + dpl_SetZoneAllViewsOff (myZone); + dpl_FlushZone (myZone); + myCollapseEnd = current_time; + myState = WaitForReincarnateState; + } + else + { + // + // Recalculate the scale factor based on time left + // + scale_factor = (percent_time_left * COLLAPSE_START_SCALE) + 1.0f; + } + // + // Build a scaling identity matrix based on our scale factor + // + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + // + // Put the scale matrix into the DCS and flush it. + // + tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = tempAffine; + DPL_FLUSH_DCS (myDCS); + break; + } + // + // WaitForReincarnateState waits till we the trigger state switches off + // then does what we want to get us back into the world. + // + case WaitForReincarnateState: + { + if(current_trigger_state != myEffectControlState) + { + // + // Switch the world back on, then change states + // + dpl_SetZoneAllViewsOn (myZone); + dpl_FlushZone (myZone); + myState = ExpandRevealState; + myCollapseEnd = current_time + EXPAND_TIME; + } + else + { + // + // Mess with the DCS to make the tunnel effect more pronounced + // + elapsed_time = current_time - myCollapseEnd; + Point3D temp_point( + (cos(elapsed_time * 3.33) * TRANSLATE_LIMIT), + (sin(elapsed_time * 2.5) * TRANSLATE_LIMIT), + 0.0); + tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( tempMatrix ); + *(Matrix4x4*)tempMatrix = temp_point; + DPL_FLUSH_DCS(myDCS); + } + break; + } + // + // ExpandRevealState expands the sphere rapidly in size to reveal the world + // getting rid of the sphere when it hits a maximum size. + // + case ExpandRevealState: + { + // + // In case we get killed again while in this state, I watch for + // a change back into the trigger state and retrigger the + // effect if it shows up + // + if(current_trigger_state == myEffectControlState) + { + myState = InitialCollapseState; + myCollapseEnd = current_time + COLLAPSE_TIME; +// dpl_SetInstanceVisibility (myInstance, True); +// dpl_FlushInstance (myInstance); +// myRenderer->AddDynamicRenderable(this); +// cout<<"POVTranslocateRenderable::Going Dynamic\n"; + } + percent_time_used = 1.0f - ((myCollapseEnd - current_time)/EXPAND_TIME); + if(percent_time_used >= 1.0f) + { + dpl_SetInstanceVisibility (myInstance, False); + dpl_FlushInstance (myInstance); + myState = IdleState; + scale_factor = 1.0f; + myRenderer->RemoveDynamicRenderable(this); +// cout<<"POVTranslocateRenderable::Going Static\n"; + } + else + { + scale_factor = (percent_time_used * EXPAND_END_SCALE) + 1.0f; + } + // + // Build a scaling identity matrix based on our scale factor + // + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + // + // Put the scale matrix into the DCS and flush it. + // + tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = tempAffine; + DPL_FLUSH_DCS (myDCS); + break; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for POVStartEndRenderable This handles the effect we use when +// the mission begins and ends (different from death) +// +POVStartEndRenderable::POVStartEndRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + dpl_VIEW *this_view, // The view containing our eye + StateIndicator *effect_trigger, // State dial we use to control the translocation + float red_fog, // Fog color + float green_fog, + float blue_fog, + float near_fog, // The near fog plane + float far_fog, // The far fog plane + unsigned start_mission_state, // State that signals start of mission + unsigned end_mission_state // State that signals end of mission +): + VideoRenderable(entity, execution_type) +{ +#define FLASH_TIME (0.1f) // Time the screen will stay stark white +#define FADE_IN_TIME (1.0f) // Time to fade from white to the world +#define FADE_OUT_TIME (1.0f) // Time to fade to black at the end of the game + // HACK HACK HACK this should be removed once red planet is checked out + if(execution_type != Watcher) + cout<<"POVStartEndRenderable wants to be a watcher and isn't!\n"; + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(this_zone); + Check_Pointer(death_zone); + Check_Pointer(this_view); + Check(effect_trigger); + // + // Remember the entity and DCS this renderable is attached to + // + myZone = this_zone; + myDeathZone = death_zone; + myEffectTrigger = effect_trigger; + myView = this_view; + myState = WaitForStartState; + myFogRed = red_fog; + myFogGreen = green_fog; + myFogBlue = blue_fog; + myFogNear = near_fog; + myFogFar = far_fog; + myStartMissionState = start_mission_state; + myEndMissionState = end_mission_state; + myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting); + // + // Connect us to the state dial's watcher hook + // + myEffectTrigger->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for POVStartEndRenderable +// +POVStartEndRenderable::~POVStartEndRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the POVStartEndRenderable +// +Logical + POVStartEndRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + + Check_Pointer(myZone); + Check_Pointer(myDeathZone); + Check(myEffectTrigger); + Verify(myState >= WaitForStartState && myState <= FadeOutState); + Verify(myFogRed >= 0.0f && myFogRed <= 1.0f); + Verify(myFogGreen >= 0.0f && myFogGreen <= 1.0f); + Verify(myFogBlue >= 0.0f && myFogBlue <= 1.0f); + + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for POVStartEndRenderable. +// +void + POVStartEndRenderable::Execute() +{ + Scalar + current_time, + percent_time_left, + percent_time_used; + unsigned + current_trigger_state; + // + // Get the current state and the current time for later use + // + Check(myEffectTrigger); + current_trigger_state = myEffectTrigger->GetState(); + current_time = myRenderer->GetCurrentFrameTime(); + // + // State engine (running off myState) to manage running of the death effect + // +// cout<<"POVStartEndRenderable::Executing\n"; + switch(myState) + { + // + // WaitForStartState waits for the state that signals the start of the mission + // then sends the screen to full white by manipulating the fog color and limits. + // + case WaitForStartState: + { + myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting); + if(current_trigger_state == myStartMissionState) + { + myState = FlashScreenState; + myStateTimer = current_time + FLASH_TIME; + dpl_SetViewFog( + myView, + dpl_fog_type_pixel_lin, + 1.0, + 1.0, + 1.0, + 0.01, + 0.05 ); + dpl_FlushView(myView); + myRenderer->AddDynamicRenderable(this); +// cout<<"POVStartEndRenderable::Going Dynamic\n"; + } + break; + } + // + // FlashScreenState is a state we park in for a short time so the screen will + // stay white for more than one frame. + // + case FlashScreenState: + { + if(myStateTimer <= current_time) + { + myStateTimer = current_time + FADE_IN_TIME; + myState = FadeInState; + } + break; + } + // + // FadeInState fades the fog color down from white to what it's supposed to + // be, while sweeping the fog ranges out to their proper ranges. + // + case FadeInState: + { + percent_time_left = (myStateTimer - current_time)/FADE_IN_TIME; + if(percent_time_left <= 0.0f) + { + percent_time_left = 0.0f; + myState = MissionRunningState; + myRenderer->SetFogStyle(DPLRenderer::updateFogSetting); + myRenderer->RemoveDynamicRenderable(this); +// cout<<"POVStartEndRenderable::Going Static\n"; + + } + percent_time_used = 1.0f - percent_time_left; + myRenderer->GetCurrentFogSettings( + &myFogRed, + &myFogGreen, + &myFogBlue, + &myFogNear, + &myFogFar); + dpl_SetViewFog( + myView, + dpl_fog_type_pixel_lin, + myFogRed + ((1.0f - myFogRed) * percent_time_left), + myFogGreen + ((1.0f - myFogGreen) * percent_time_left), + myFogBlue + ((1.0f - myFogBlue) * percent_time_left), + (myFogNear * percent_time_used) + 0.01f, + (myFogFar * percent_time_used) + 0.05f); + dpl_FlushView(myView); + break; + } + // + // MissionRunningState is where we park while the mission is going on, waiting + // for the state that signals the end of the game + // + case MissionRunningState: + { + if(current_trigger_state == myEndMissionState) + { + myState = FadeOutState; + myStateTimer = current_time + FADE_OUT_TIME; + myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting); + myRenderer->AddDynamicRenderable(this); +// cout<<"POVStartEndRenderable::Going Dynamic\n"; + } + break; + } + // + // FadeOutState handles doing a fade-to-black at the end of the game + // + case FadeOutState: + { + percent_time_left = (myStateTimer - current_time)/FADE_OUT_TIME; + if(percent_time_left <= 0.0f) + { + myState = WaitForStartState; + percent_time_left = 0.0f; + myRenderer->RemoveDynamicRenderable(this); +// cout<<"POVStartEndRenderable::Going Static\n"; + } + myRenderer->GetCurrentFogSettings( + &myFogRed, + &myFogGreen, + &myFogBlue, + &myFogNear, + &myFogFar); + dpl_SetViewFog( + myView, + dpl_fog_type_pixel_lin, + myFogRed * percent_time_left, + myFogGreen * percent_time_left, + myFogBlue * percent_time_left, + (myFogNear * percent_time_left) + 0.01f, + (myFogFar * percent_time_left) + 0.05f); + dpl_FlushView(myView); + break; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the ReticleRenderable +// This produces a movable crosshair reticle that can be either static or +// dynamic. If static, it will position the graphic at wherever the reticle +// points when we construct this. +// +ReticleRenderable::ReticleRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Reticle **my_reticle, // points to renderable reticle pointer that points to entity's reticle + dpl_VIEW *this_view // the view associated with our eye +): + VideoRenderable(entity, execution_type) +{ + dpl2d_MATRIX + my_2d_matrix; +// +// Check the inbound data +// + Check_Pointer(my_reticle); + Check_Pointer(*my_reticle); + Check_Pointer(this_view); +// +// Remember the entity that this renderable is attached to +// + rendererReticle = my_reticle; + myReticle = *my_reticle; + myView = this_view; + myOldReticlePosition = myReticle->reticlePosition; + myOldReticleState = myReticle->reticleState; +// +// Build a main 2d display list with the reticle graphic in it, this should call +// a second display list that contains just a position command so only a short +// display list needs to be remade to move the cursor. +// + myReticleDisplayList = dpl2d_NewDisplayList(); + myPositionDisplayList = dpl2d_NewDisplayList(); + dpl2d_OpenDisplayList (myReticleDisplayList, dpl2d_open_mode_clear); + dpl2d_AddCallDisplayList(myReticleDisplayList, myPositionDisplayList ); + dpl2d_AddFullScreenClipRegion (myReticleDisplayList); + dpl2d_AddSetColor (myReticleDisplayList, 0.0f, 0.5f, 0.0f); + dpl2d_AddOpenLines (myReticleDisplayList); + dpl2d_AddPoint (myReticleDisplayList, -0.08f, 0.0f); + dpl2d_AddPoint (myReticleDisplayList, -0.02f, 0.0f); + dpl2d_AddPoint (myReticleDisplayList, 0.02f, 0.0f); + dpl2d_AddPoint (myReticleDisplayList, 0.08f, 0.0f); + dpl2d_AddPoint (myReticleDisplayList, 0.0f, -0.08f); + dpl2d_AddPoint (myReticleDisplayList, 0.0f, -0.02f); + dpl2d_AddPoint (myReticleDisplayList, 0.0f, 0.02f); + dpl2d_AddPoint (myReticleDisplayList, 0.0f, 0.08f); + dpl2d_AddCloseLines (myReticleDisplayList); + dpl2d_CloseDisplayList (myReticleDisplayList); + + dpl2d_OpenDisplayList (myPositionDisplayList, dpl2d_open_mode_clear); + dpl2d_IdMatrix (my_2d_matrix); + dpl2d_TranslateMatrix (my_2d_matrix, myReticle->reticlePosition.x, myReticle->reticlePosition.y ); + dpl2d_AddSetMatrix (myPositionDisplayList,my_2d_matrix ); + dpl2d_CloseDisplayList (myPositionDisplayList); + + dpl2d_FlushDisplayList (myReticleDisplayList); + dpl2d_FlushDisplayList (myPositionDisplayList); + // + // If the reticle is turned on bind the display list to our eyepoint + // + if(myOldReticleState == Reticle::ReticleOn) + { + dpl2d_SetViewDisplayList ( myView, myReticleDisplayList ); + dpl_FlushView ( myView ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the ReticleRenderable +// +ReticleRenderable::~ReticleRenderable() +{ + // + // Make sure our structure is still in one piece + // + Check(this); + // + // Unhook the display list from the view, then delete both lists + // + dpl2d_SetViewDisplayList ( myView, NULL ); + dpl_FlushView ( myView ); + dpl2d_DeleteDisplayList(myReticleDisplayList); + dpl2d_DeleteDisplayList(myPositionDisplayList); + // + // Unhook the renderer's pickpoint stuff from this renderable + // + *rendererReticle = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLDrawReticleRenderable +// Not much to check here, the entity and DCS pointers must be valid while +// the instance is allowed to be NULL +// +Logical + ReticleRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myReticle); + Check_Pointer(rendererReticle); + Check_Pointer(myView); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ReticleRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ReticleRenderable::Execute() +{ + dpl2d_MATRIX + my_2d_matrix; + // + // See if the reticle state has changed + // + if(myOldReticleState != myReticle->reticleState) + { + // + // Send the reticle into the appropriate state + // + myOldReticleState = myReticle->reticleState; + switch(myOldReticleState) + { + case Reticle::ReticleOff: + dpl2d_SetViewDisplayList ( myView, NULL ); + dpl_FlushView ( myView ); + break; + case Reticle::ReticleOn: + dpl2d_SetViewDisplayList ( myView, myReticleDisplayList ); + dpl_FlushView ( myView ); + break; + } + } + // + // See if the reticle has moved + // + if(myOldReticlePosition != myReticle->reticlePosition) + { + myOldReticlePosition = myReticle->reticlePosition; + // + // Re-create the display list that positions the reticle + // + dpl2d_OpenDisplayList( + myPositionDisplayList, + dpl2d_open_mode_clear); + dpl2d_IdMatrix(my_2d_matrix); + dpl2d_TranslateMatrix( + my_2d_matrix, + myOldReticlePosition.x, + myOldReticlePosition.y ); + dpl2d_AddSetMatrix( + myPositionDisplayList, + my_2d_matrix ); + dpl2d_CloseDisplayList(myPositionDisplayList); + dpl2d_FlushDisplayList(myPositionDisplayList); + } + // + // Call the execute method in our parent + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the CameraShipHUDRenderable +// +CameraShipHUDRenderable::CameraShipHUDRenderable( + Entity *entity, + ExecutionType execution_type, + int *player_index, + Logical *display_ranking_window +) : + VideoRenderable(entity, execution_type) +{ + Check_Pointer(player_index); + Check_Pointer(display_ranking_window); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in PlayerName Geometry + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + playerNameObject[0] = dpl_LoadObject("PNAME1.bgf", dpl_load_normal); + playerNameObject[1] = dpl_LoadObject("PNAME2.bgf", dpl_load_normal); + playerNameObject[2] = dpl_LoadObject("PNAME3.bgf", dpl_load_normal); + playerNameObject[3] = dpl_LoadObject("PNAME4.bgf", dpl_load_normal); + playerNameObject[4] = dpl_LoadObject("PNAME5.bgf", dpl_load_normal); + playerNameObject[5] = dpl_LoadObject("PNAME6.bgf", dpl_load_normal); + playerNameObject[6] = dpl_LoadObject("PNAME7.bgf", dpl_load_normal); + playerNameObject[7] = dpl_LoadObject("PNAME8.bgf", dpl_load_normal); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in Ordinal Rankings Geometry + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ordinalObject[0] = dpl_LoadObject("PLACE1.bgf", dpl_load_normal); + ordinalObject[1] = dpl_LoadObject("PLACE2.bgf", dpl_load_normal); + ordinalObject[2] = dpl_LoadObject("PLACE3.bgf", dpl_load_normal); + ordinalObject[3] = dpl_LoadObject("PLACE4.bgf", dpl_load_normal); + ordinalObject[4] = dpl_LoadObject("PLACE5.bgf", dpl_load_normal); + ordinalObject[5] = dpl_LoadObject("PLACE6.bgf", dpl_load_normal); + ordinalObject[6] = dpl_LoadObject("PLACE7.bgf", dpl_load_normal); + ordinalObject[7] = dpl_LoadObject("PLACE8.bgf", dpl_load_normal); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize CameraFollowing + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + followedPlayerIndex = player_index; + oldFollowedPlayerIndex = -1; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create One DCS for a Camera Following Name Bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + followedNameDCS = dpl_NewDCS(); + followedNameInstance = dpl_NewInstance(); + dpl_ScaleDCS ( followedNameDCS, 0.20f, 0.20f, 1.0f ); + dpl_TranslateDCS ( followedNameDCS, 0.0f, -0.15f, -0.5f ); + dpl_SetDCSIgnoreGeo ( followedNameDCS, 1 ); + dpl_SetDCSTraversal ( followedNameDCS, 0x7 ); + dpl_AddDCSToScene ( followedNameDCS ); + dpl_SetInstanceObject ( followedNameInstance, playerNameObject[0] ); + dpl_AddInstanceToDCS ( followedNameDCS, followedNameInstance ); + dpl_SetInstanceVisibility ( followedNameInstance, 1 ); + dpl_FlushInstance ( followedNameInstance ); + dpl_FlushDCS ( followedNameDCS ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create One DCS for Camera Following Ordinal Ranking Bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + followedOrdinalDCS = dpl_NewDCS(); + followedOrdinalInstance = dpl_NewInstance(); + dpl_AddDCSToDCS ( followedNameDCS, followedOrdinalDCS ); + dpl_SetInstanceObject ( followedOrdinalInstance, ordinalObject[0] ); + dpl_AddInstanceToDCS ( followedOrdinalDCS, followedOrdinalInstance ); + dpl_SetDCSIgnoreGeo ( followedOrdinalDCS, 1 ); + dpl_SetDCSTraversal ( followedOrdinalDCS, 0x7 ); + dpl_TranslateDCS ( followedOrdinalDCS, -0.75f, 0.0f, 0.0f ); + dpl_SetInstanceVisibility ( followedOrdinalInstance, 0 ); + dpl_FlushInstance ( followedOrdinalInstance ); + dpl_FlushDCS ( followedOrdinalDCS ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the Ranking Window + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + displayRankingWindow = display_ranking_window; + oldDisplayRankingWindow = False; + + Scalar rank_window_y; + rank_window_y = 0.16f; + + rankingWindowDCS = dpl_NewDCS(); + dpl_ScaleDCS ( rankingWindowDCS, 0.12f, 0.12f, 1.0f ); + dpl_TranslateDCS ( rankingWindowDCS, 0.22f, rank_window_y, -0.5f ); + dpl_SetDCSIgnoreGeo ( rankingWindowDCS, 1 ); + dpl_SetDCSTraversal ( rankingWindowDCS, 0x7 ); + dpl_AddDCSToScene ( rankingWindowDCS ); + dpl_FlushDCS ( rankingWindowDCS ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the pointer's to the player Ranks + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + playerRank = NULL; + oldPlayerRank = NULL; + nameDCS = NULL; + rankDCS = NULL; + nameInstance = NULL; + rankInstance = NULL; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See How Many Regular Players and CameraShip Players! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + playerCount = 0; + Check(application); + EntityManager *entity_mgr = application->GetEntityManager(); + Check(entity_mgr); + EntityGroup *player_group = entity_mgr->FindGroup("Players"); + if (player_group) + { + Check(player_group); + ChainIteratorOf player_iterator(player_group->groupMembers); + playerCount = player_iterator.GetSize(); + } + + EntityGroup *camera_player_group = entity_mgr->FindGroup("CameraPlayers"); + int camera_player_count=0; + if (camera_player_group) + { + Check(player_group); + ChainIteratorOf camera_iterator(camera_player_group->groupMembers); + camera_player_count = camera_iterator.GetSize(); + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make the Arrays for Ranking the size of regular and cameras players + // summed up. This is necessary since GameMachineHost type of Camera + // Ships also have a bitmapIndex! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (playerCount) + { + camera_player_count += playerCount; + Verify(camera_player_count <= MAX_PLAYER_NAMES); + playerRank = new (int (*[camera_player_count])); + Register_Pointer(playerRank); + Player *active_player; + if(player_group) + { + Check(player_group); + ChainIteratorOf player_iterator(player_group->groupMembers); + while ((active_player = (Player*) player_iterator.ReadAndNext()) != NULL) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PlayerRank Array indexed by bitmapIndex + // holds that player's ranking + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(active_player); + Verify( + active_player->playerBitmapIndex > 0 + && active_player->playerBitmapIndex <= MAX_PLAYER_NAMES + ); + playerRank[active_player->playerBitmapIndex - 1] = + &active_player->playerRanking ; + } + } + if (camera_player_group) + { + ChainIteratorOf camera_iterator(camera_player_group->groupMembers); + while ((active_player = (Player*) camera_iterator.ReadAndNext()) != NULL) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PlayerRank Array indexed by bitmapIndex + // holds that player's ranking + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(active_player); + Verify( + active_player->playerBitmapIndex > 0 + && active_player->playerBitmapIndex <= MAX_PLAYER_NAMES + ); + playerRank[active_player->playerBitmapIndex - 1] = + &active_player->playerRanking ; + } + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize OldPlayerRank + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // + oldPlayerRank = new int[camera_player_count]; + Register_Pointer(oldPlayerRank); + + int ii; + for(ii=0; ii= 0); +#if 0 + if ( + oldPlayerRank[oldFollowedPlayerIndex] + != *playerRank[oldFollowedPlayerIndex] + ) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Change the bitmap shown + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + Verify( + oldPlayerRank[oldFollowedPlayerIndex] >= 0 + && oldPlayerRank[oldFollowedPlayerIndex] < playerCount + ); + dpl_SetInstanceObject ( + followedOrdinalInstance, + ordinalObject[*playerRank[oldFollowedPlayerIndex]] + ); + dpl_FlushInstance ( followedOrdinalInstance ); + } +#endif + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update the Rankings for All Players + // whenever they change! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;ii= 0 && oldPlayerRank[ii] < playerCount); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Name instance corresponds to rank + // playerNameobject corresponds to playerBitmapIndex + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + dpl_SetInstanceObject( + nameInstance[oldPlayerRank[ii]], + playerNameObject[ii] + ); + dpl_FlushInstance ( nameInstance[oldPlayerRank[ii]] ); + } + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Toggle Ranking Window Visibility + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (oldDisplayRankingWindow != *displayRankingWindow) + { + oldDisplayRankingWindow = *displayRankingWindow; + for(int ii=0;iiGetApplicationState() == Application::StoppingMission || + application->GetApplicationState() == Application::EndingMission) + { + dpl_SetInstanceVisibility ( followedOrdinalInstance, 0 ); + dpl_SetInstanceVisibility ( followedNameInstance, 0 ); + dpl_FlushInstance ( followedOrdinalInstance ); + dpl_FlushInstance ( followedNameInstance ); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraShipHUDRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DCSMorphObjectRenderable +// +DCSMorphObjectRenderable::DCSMorphObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask // intersection mask for the object +): + VideoRenderable(entity, execution_type) +{ + // + // Check incoming data + // + Check_Pointer(destination_object); + Check_Pointer(start_object); + Check_Pointer(end_object); + Check_Pointer(morph_control); + Check_Pointer(this_zone); + // + // Remember my dpl object, intersect and offset data + // + myDPLObject = destination_object; + myStartObject = start_object; + myEndObject = end_object; + myMorphControl = morph_control; + oldMorphControl = *myMorphControl; + myMorphMode = morph_mode; + myDPLZone = this_zone; + myIntersectMode = intersect_mode; + myIntersectMask = intersect_mask; + myDCS = NULL; + myInstance = NULL; + // + // We need to construct a DCS node here and remember it. The next class up is + // expected to handle the flushing and connecting of structure so we just setup + // the DCS and zone information here, leaving flushing to someone else. + // + myDCS = dpl_NewDCS (); + Check_Pointer ( myDCS ); + dpl_SetDCSZone ( myDCS, myDPLZone ); + // + // Construct the instance(s) and hang them on the DCS. Since we may be building + // more than one instance, we have to take care of flushing them here. + // + myInstance = dpl_NewInstance(); + Check_Pointer ( myInstance); + dpl_SetInstanceObject ( myInstance, myDPLObject); + dpl_SetInstanceIntersect ( myInstance, myIntersectMode ); + dpl_SetInstanceSectMask ( myInstance, myIntersectMask ); + dpl_SetInstanceVisibility ( myInstance, 1 ); + dpl_AddInstanceToDCS ( myDCS, myInstance ); + dpl_FlushInstance ( myInstance ); + // + // Setup the morph and do the initial morph to get the destination object + //-------------------------------------------------------------------------- + // NOTE: dpl_MorphObject seems to have Start and End objects reversed + // so they are reversed here as well...(two negatives make positive) + //-------------------------------------------------------------------------- + dpl_MorphObject(myDPLObject,myStartObject,myEndObject,oldMorphControl,myMorphMode); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DCSMorphObjectRenderable +// +DCSMorphObjectRenderable::~DCSMorphObjectRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Delete the instance(s) hanging on the DCS (if any) + // NOTE: we may want to iterate through all the instances here using DPL routines + // + dpl_RemoveInstanceFromDCS(myDCS, myInstance); + dpl_DeleteInstance(myInstance); + // + // Delete the DCS + // + dpl_DeleteDCS(myDCS); + myDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DCSMorphObjectRenderable +// +Logical + DCSMorphObjectRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myDPLObject); + Check_Pointer(myStartObject); + Check_Pointer(myEndObject); + Check_Pointer(myMorphControl); + Check_Pointer(myDPLZone); + Check_Pointer(myDCS); + Check_Pointer(myInstance); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DCSMorphObjectRenderable +// If the morph control variable has changed, we re-do the morph +// +void + DCSMorphObjectRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // See if the morph control varaible has changed + // + if(oldMorphControl != *myMorphControl) + { + oldMorphControl = *myMorphControl; + //-------------------------------------------------------------------------- + // NOTE: dpl_MorphObject seems to have Start and End objects reversed + // so they are reversed here as well...(two negatives make positive) + //-------------------------------------------------------------------------- + + dpl_MorphObject(myDPLObject,myStartObject,myEndObject,oldMorphControl,myMorphMode); + } + // + // Call the next lower execute method + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for RootMorphRenderable +// +RootMorphRenderable::RootMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask // intersection mask for the object +): +DCSMorphObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + destination_object, // destination + start_object, // start object + end_object, // end object + morph_control, // pointer to control variable + morph_mode, // Defines type of morph to do + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask) // intersection mask for the object +{ + // + // All the incoming data will have been checked by DCSObjectRenderable + // already, so we don't have to check anything locally. + // + // + // Initialize our variables + // + oldLocalToWorld = myEntity->localToWorld; + // + // Now we finish the work of hooking up and initializing the root renderable + // Add the DCS to the scene and initialize it's matrix with the localToWorld + // transformation from our entity + // + dpl_AddDCSToScene ( myDCS ); + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = myEntity->localToWorld; + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for RootMorphRenderable +// +RootMorphRenderable::~RootMorphRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Remove the DCS from the scene, deletion of the DCS and it's instances is + // handled by our parent class. + // + dpl_RemoveDCSFromScene(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the RootMorphRenderable +// +Logical + RootMorphRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSMorphObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check(&oldLocalToWorld); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the RootMorphRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + RootMorphRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // If our entity has changed it's localToWorld matrix, update DPL + // + if(oldLocalToWorld != myEntity->localToWorld) + { + oldLocalToWorld = myEntity->localToWorld; + float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + Check_Pointer (tempMatrix); + *(Matrix4x4*)tempMatrix = oldLocalToWorld; + DPL_FLUSH_DCS ( myDCS ); + } + // + // Call the execute method in our parent + // + DCSMorphObjectRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ChildMorphRenderable +// +ChildMorphRenderable::ChildMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS // the parent DCS we will be offsetting from +): +DCSMorphObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + destination_object, // destination + start_object, // start object + end_object, // end object + morph_control, // pointer to control variable + morph_mode, // Defines type of morph to do + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask) // intersection mask for the object +{ + // + // All the incoming data will have been checked by DCSObjectRenderable + // already, so we don't have to check anything locally. + // + Check_Pointer(parent_DCS); + // + // Now we finish the work of hooking up and initializing the root renderable + // Add the DCS to the scene and initialize it's matrix with the localToWorld + // transformation from our entity + // + dpl_AddDCSToDCS ( parent_DCS, myDCS ); + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ChildMorphRenderable +// +ChildMorphRenderable::~ChildMorphRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ChildMorphRenderable +// +Logical + ChildMorphRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSMorphObjectRenderable::TestInstance(); + // + // Test our own variables + // + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ChildMorphRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ChildMorphRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Call the execute method in our parent + // + DCSMorphObjectRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ScalingExplosionRenderable +// +ScalingExplosionRenderable::ScalingExplosionRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // This will be the scaling explosion object + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Vector3D *control_vector, // Effect control velocity vector + Vector3D *accel_vector, // rate of change of control vector + Scalar gravity, + int *trigger // doesn't run till the trigger comes up +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + // + // Check the incoming data + // + Check(control_vector); + #if DEBUG_LEVEL > 0 + if(trigger) + Check_Pointer(trigger); + #endif + // + // Initialize our variables + // + myScalingVector.x = 0.01; + myScalingVector.y = 0.01; + myScalingVector.z = 0.01; + myVelocityVector = *control_vector; + myVelocityChange = *accel_vector; + myGravity = gravity; + myVelocity = 0.0f; + myTranslation.x = 0.0; + myTranslation.y = 0.0; + myTranslation.z = 0.0; + myTrigger = trigger; + // + // Initialize the matrix in this dcs + // + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= myScalingVector; + tempAffine *= myTranslation; + *(Matrix4x4*)tempMatrix = tempAffine; + dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ScalingExplosionRenderable +// +ScalingExplosionRenderable::~ScalingExplosionRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ScalingExplosionRenderable +// +Logical + ScalingExplosionRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check(&myScalingVector); + Check(&myVelocityVector); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ScalingExplosionRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ScalingExplosionRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + if(!myTrigger || *myTrigger != 0) + { + // + // Apply the scaling factor to the object + // + myVelocityVector += myVelocityChange; + myScalingVector += myVelocityVector; + myVelocity += myGravity; + myTranslation.y += myVelocity; + // + // Initialize the matrix in this dcs + // + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= myScalingVector; + tempAffine *= myTranslation; + *(Matrix4x4*)tempMatrix = tempAffine; + DPL_FLUSH_DCS ( myDCS ); + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); + } +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Micro Renderables +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// From here to the row of === is pretty kludgy stuff to allow dave to prototype +// some explosion stuff. +// I expect to replace most of it within a week with the all-new micro +// renderable system. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DependantRenderable +// This is a class of renderable that has other dependant renderables which it +// will execute on command. This is a base for this type of renderable and is +// not ment to be used by itself. +// +DependantRenderable::DependantRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type // How/when to execute the renderable +): + VideoRenderable(entity, execution_type), + dependantRenderableSocket(NULL) +{ + // Check incoming data + // Initialize variables +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DependantRenderable +DependantRenderable::~DependantRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DependantRenderable +Logical + DependantRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + // Now do our checking + Check(&dependantRenderableSocket); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AddDependantRenderable for the DependantRenderable +// This adds an existing renderable as a dependant on this renderable so it +// will be run when this renderable is executed. +void + DependantRenderable::AddDependantRenderable(Component *dependant) +{ + Check(dependant); + dependantRenderableSocket.Add(dependant); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DependantRenderable +void + DependantRenderable::Execute() +{ + Component + *dependant; + // + // Make an iterator for our components then execute them all + // +// cout<<"DependantRenderable::Execute()\n"; + SChainIteratorOf dependant_iterator(&dependantRenderableSocket); + while ((dependant = dependant_iterator.ReadAndNext()) != NULL) + { + dependant->Execute(); +// cout<<"dependant->Execute();\n"; + } + + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ScalarTriggerRenderable +// Whenever "watched_value" changes by "watched_precision" the dependants of this +// renderable will be called. +// +ScalarTriggerRenderable::ScalarTriggerRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar *watched_value, // we run dependants when this changes + Scalar watched_precision // watched_value must change by this much +): + DependantRenderable(entity, execution_type) +{ + // + // Check incoming data + // + Check_Pointer(watched_value); + // + // Initialize variables + // + myWatchedValue = watched_value; + myOldWatchedValue = *myWatchedValue; + myPrecision = watched_precision; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ScalarTriggerRenderable +ScalarTriggerRenderable::~ScalarTriggerRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ScalarTriggerRenderable +Logical + ScalarTriggerRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + DependantRenderable::TestInstance(); + // Now do our checking + Check_Pointer(myWatchedValue); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ScalarTriggerRenderable +void + ScalarTriggerRenderable::Execute() +{ + Check(this); + // + // If there hasn't been a significant enough change, return right now + // + if(Abs((*myWatchedValue - myOldWatchedValue)) < myPrecision) + return; + // + // Update my watcher data, then call my parent to execute the dependants + // + myOldWatchedValue = *myWatchedValue; + DependantRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for TimeCullRenderable +// This renderable will run all it's dependants at a set frequency based on +// a clock value supplied by the culling system. +// +TimeCullRenderable::TimeCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_between_runs // Time delay between executions of dependants +): + DependantRenderable(entity, execution_type) +{ + // + // Check incoming data + // + // + // Initialize the renderable, set clock so this will execute the first time + // it's called. + // + delayBetweenRuns = delay_between_runs; + nextRunTime = myRenderer->GetCurrentFrameTime(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for TimeCullRenderable +TimeCullRenderable::~TimeCullRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the TimeCullRenderable +Logical + TimeCullRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + DependantRenderable::TestInstance(); + // Now do our checking + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the TimeCullRenderable +void + TimeCullRenderable::Execute() +{ + Check(this); + // + // If it's time, call my parent to execute the dependants + // + if(nextRunTime <= myRenderer->GetCurrentFrameTime()) + { + nextRunTime = myRenderer->GetCurrentFrameTime() + delayBetweenRuns; + DependantRenderable::Execute(); +// cout<<"Time Cull ran dependants\n"; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MechCullRenderable::MechCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical always_run_all, // If true, disable culling and run everything + dpl_ZONE *my_zone // Switch off this zone when the mech goes off screen +): + DependantRenderable(entity, execution_type), + legRenderableSocket(NULL) +{ + Check_Pointer(my_zone); + myAlwaysRunAll = always_run_all; + myZone = my_zone; + myMechWasVisible = True; + myNextRootUpdate = myRenderer->GetCurrentFrameTime(); + myNextLegUpdate = myRenderer->GetCurrentFrameTime(); + myRootUpdateRate = 0.0; + myLegUpdateRate = 0.0; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for MechCullRenderable +MechCullRenderable::~MechCullRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AddDependantLegRenderable for the MechCullRenderable +// This adds an existing renderable as a dependant of the leg chain. +void + MechCullRenderable::AddDependantLegRenderable(Component *dependant) +{ + Check(dependant); + legRenderableSocket.Add(dependant); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the MechCullRenderable +Logical + MechCullRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + DependantRenderable::TestInstance(); + // Now do our checking + Check_Pointer(myZone); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the MechCullRenderable +void + MechCullRenderable::Execute() +{ + #define CULL_VOLUME_SIZE 11.0 // Assume mech (or other object) fills 10 meter bubble + Scalar + current_time; + Point3D + target_point; + Component + *dependant; + + Check(this); + // + // If we've been told to always run everything, do so. I don't flip the + // profile bit here because I only want to time the actual cull algorithim. + // + if(myAlwaysRunAll) + { + DependantRenderable::Execute(); + SChainIteratorOf dependant_iterator(&legRenderableSocket); + while ((dependant = dependant_iterator.ReadAndNext()) != NULL) + { + dependant->Execute(); + } + myMechWasVisible = True; + return; + } + SET_VIDEO_MECH_CULL_RENDERABLE(); + // + // Continue on to do the full culling process + // + current_time = myRenderer->GetCurrentFrameTime(); + // + // Transform this entities position into eye space + // + target_point = myEntity->localOrigin.linearPosition; + target_point *= (*myRenderer->GetWorldToEyeMatrix()); + Check(this); + // + // See if this is inside the viewing volume + // HACK, viewing volume is hard coded here for now + // negative z goes into the screen + // + // See if it's behind me + // + if((target_point.z - CULL_VOLUME_SIZE) >= 0.0f) + { + if(myMechWasVisible) + { + myMechWasVisible = False; + dpl_SetZoneAllViewsOff (myZone); + dpl_FlushZone (myZone); + // + // Set the root rate to slow and the leg rate to stopped + // + myRootUpdateRate = 1.0f; + myLegUpdateRate = 60.0f; + myNextRootUpdate = current_time + myRootUpdateRate; + myNextLegUpdate = current_time + myLegUpdateRate; + } + } + else + { + // + // Fix up the Z so objects very close behind us (close enough they might + // stick into our view) will be properly culled. + // + if(target_point.z >= 0) + target_point.z = 0.1; + else + target_point.z = Abs(target_point.z); + Check(this); + // + // See if the object's volume is to the left or right of the culling + // volume. + // + if(((Abs(target_point.x)-CULL_VOLUME_SIZE)/target_point.z) > myRenderer->GetViewRatio()) + { + // + // If we were visible before, we're not any more + // + Check(this); + if(myMechWasVisible) + { + myMechWasVisible = False; + dpl_SetZoneAllViewsOff (myZone); + dpl_FlushZone (myZone); + // + // Set the root rate to slow and the leg rate to stopped + // + myRootUpdateRate = 1.0f; + myLegUpdateRate = 60.0f; + myNextRootUpdate = current_time + myRootUpdateRate; + myNextLegUpdate = current_time + myLegUpdateRate; + } + } + else + { + // + // If we were invisible before, we're visible now + // + Check(this); + if(!myMechWasVisible) + { + myMechWasVisible = True; + dpl_SetZoneAllViewsOn (myZone); + dpl_FlushZone (myZone); + // + // Set the various update rates appropriately and force an update + // + myRootUpdateRate = 0.0; + myNextRootUpdate = current_time; + myNextLegUpdate = current_time; + } + // + // Set the leg update rate based on range (really should be a formulia) + // + if(target_point.z < 500.0f) + myLegUpdateRate = 0.0; + else + myLegUpdateRate = 0.25; + } + } + // + // Flip the trace bit here because I don't want to include the cost of the + // dependant renderables. + // + CLEAR_VIDEO_MECH_CULL_RENDERABLE(); + // + // Use the data already calculated to determine which of the dependant + // renderable groups we should execute. + // + if(myNextLegUpdate <= current_time) + { + myNextLegUpdate = current_time + myLegUpdateRate; + // + // Execute all the leg renderables + // + SChainIteratorOf dependant_iterator(&legRenderableSocket); + while ((dependant = dependant_iterator.ReadAndNext()) != NULL) + { + dependant->Execute(); + } + } + if(myNextRootUpdate <= current_time) + { + myNextRootUpdate = current_time + myRootUpdateRate; + DependantRenderable::Execute(); + } + return; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for InstanceSwitchRenderable +InstanceSwitchRenderable::InstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // instance on when trigger is.... + int *trigger // true if the instance is on, false if off +): + VideoRenderable(entity, execution_type) +{ + // Check incoming data + Check_Pointer(this_instance); + Check_Pointer(trigger); + // Initialize variables + mySense = sense; + myInstance = this_instance; + myTriggerAttribute = trigger; + oldTriggerAttribute = *myTriggerAttribute; + if(mySense == oldTriggerAttribute) + { + dpl_SetInstanceVisibility ( myInstance, 1 ); + } + else + { + dpl_SetInstanceVisibility ( myInstance, 0 ); + } + dpl_FlushInstance ( myInstance ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for InstanceSwitchRenderable +InstanceSwitchRenderable::~InstanceSwitchRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the InstanceSwitchRenderable +Logical + InstanceSwitchRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myInstance); + Check_Pointer(myTriggerAttribute); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the InstanceSwitchRenderable +void + InstanceSwitchRenderable::Execute() +{ + // Check our variables + Check(this); + if(*myTriggerAttribute != oldTriggerAttribute) + { + oldTriggerAttribute = *myTriggerAttribute; + if(mySense == oldTriggerAttribute) + { + dpl_SetInstanceVisibility ( myInstance, 1 ); + } + else + { + dpl_SetInstanceVisibility ( myInstance, 0 ); + } + dpl_FlushInstance ( myInstance ); + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// StateInstanceSwitchRenderable is designed to be a watcher that connects to +// a state dial. Whenever the state dial changes we are called and check to +// see if the trigger state has been entered. If we are in the trigger state +// we will change the instance visibility based on the sense variable passed +// into the constructor. This lets you have an instance on while in a +// certain state or off while in that state and on in others. +// Messages Sent: None +// Messages Received: None +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for StateInstanceSwitchRenderable +// +StateInstanceSwitchRenderable::StateInstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // true to turn on in this state, false for off + StateIndicator *state_dial, // State dial we use to control the on/off + unsigned trigger_state // State that we look for +): + VideoRenderable(entity, execution_type) +{ + // + // Check incoming data for correctness + // + Check_Pointer(this_instance); + Check(state_dial); + // + // Initialize variables + // + myInstance = this_instance; + mySense = sense; + myStateDial = state_dial; + myTriggerState = trigger_state; + // + // Put the instance in the proper state and flush it + // + if(myStateDial->GetState() == myTriggerState) + { + if(mySense == True) + myLastInstanceState = True; + else + myLastInstanceState = False; + } + else + { + if(mySense == True) + myLastInstanceState = False; + else + myLastInstanceState = True; + } + dpl_SetInstanceVisibility ( myInstance, myLastInstanceState ); + dpl_FlushInstance ( myInstance ); + // + // Connect us to the state dial's watcher hook + // + state_dial->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for StateInstanceSwitchRenderable +StateInstanceSwitchRenderable::~StateInstanceSwitchRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the StateInstanceSwitchRenderable +Logical + StateInstanceSwitchRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myInstance); + Check(myStateDial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the StateInstanceSwitchRenderable --- called by the state dial +// watcher hook when the state changes. The state dial won't call us if unless +// the state actually changes so there is no need to filter transitions between +// two identical states. +// +void + StateInstanceSwitchRenderable::Execute() +{ + unsigned + new_state; + // + // Check our variables + // + Check(this); + // + // See what state we should go into + // + if(myStateDial->GetState() == myTriggerState) + { + if(mySense == True) + new_state = True; + else + new_state = False; + } + else + { + if(mySense == True) + new_state = False; + else + new_state = True; + } + if(new_state != myLastInstanceState) + { + myLastInstanceState = new_state; + dpl_SetInstanceVisibility ( myInstance, myLastInstanceState ); + dpl_FlushInstance ( myInstance ); + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for MakeDCSFall +MakeDCSFall::MakeDCSFall( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_DCS *this_DCS, // the DCS to control + Scalar gravity, // Gravity in meters/sec squared + int *trigger // true if the instance is on, false if off +): + VideoRenderable(entity, execution_type) +{ + // Check incoming data + Check_Pointer(this_DCS); + Check_Pointer(trigger); + // + // Was an input trigger provided? + // + if(trigger) + { + // Yes, remember a pointer to it and it's state + myTrigger = trigger; + oldMyTrigger = *myTrigger; + } + else + { + // No, point it at a fake trigger that is turned on + fakeTrigger = 1; + myTrigger = &fakeTrigger; + oldMyTrigger = 0; + } + // + // Initialize other variables + // + myDCS = this_DCS; + myDisplacement = Point3D::Identity; + myHalfAcceleration = gravity/2.0f; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for MakeDCSFall +MakeDCSFall::~MakeDCSFall() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the MakeDCSFall +Logical + MakeDCSFall::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the MakeDCSFall +void + MakeDCSFall::Execute() +{ + // Check our variables + Check(this); + // + // Look for an edge in the trigger input + // + if(*myTrigger != oldMyTrigger) + { + // + // A transition from zero to nonzero resets the DCS position and + // starts us falling again. + // + if(oldMyTrigger == 0) + { + myFallStart = myRenderer->GetCurrentFrameTime(); + myDisplacement = Point3D::Identity; + } + oldMyTrigger = *myTrigger; + } + // + // If the trigger is nonzero and the sweep isn't at 1 yet, update + // the sweep values. + // + if(oldMyTrigger != 0) + { + Scalar + elapsed_time, + current_time; + // Figure displacement do to gravity... 0.5 * a * t^2 + // note that we've already taken a * 0.5 in the constructor + current_time = myRenderer->GetCurrentFrameTime(); + elapsed_time = current_time - myFallStart; + myDisplacement.y = myHalfAcceleration * (elapsed_time * elapsed_time); + float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + Check_Pointer (tempMatrix); + *(Matrix4x4*)tempMatrix = myDisplacement; + DPL_FLUSH_DCS ( myDCS ); + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//============================================================================= +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SquareWaveRenderable +SquareWaveRenderable::SquareWaveRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar time_false, // time to spend in zero state + Scalar time_true, // time to spend in one state + int *trigger // starts square wave when it goes to 1 + int start_state // state we start in + int cycles // number of transitions before we stop +): + VideoRenderable(entity, execution_type) +{ + if(trigger) + { + // Yes, remember a pointer to it and it's state + myTriggerInput = trigger; + oldTriggerInput = *myTrigger; + } + else + { + // No, point it at a fake trigger that is turned on + fakeTrigger = 1; + myTriggerInput = &fakeTrigger; + oldTriggerInput = 0; + } + // Initialize variables + myTriggerInput = trigger; + oldTriggerInput = 0; + myNextStateChange = 0; + myTimeFalse = time_false; + myTimeTrue = time_true; + myTriggerAttribute = start_state; + myCyclesLeft = cycles; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SquareWaveRenderable +SquareWaveRenderable::~SquareWaveRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SquareWaveRenderable +Logical + SquareWaveRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Verify(myTriggerTime > 0.0f); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SquareWaveRenderable +void + SquareWaveRenderable::Execute() +{ + Scalar + current_time; + // Check our variables + Check(this); + + if(*myTriggerInput != oldTriggerInput && oldTriggerInput == 0) + { + if(myStartState) + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeTrue; + myTriggerAttribute = True; + } + else + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeFalse; + myTriggerAttribute = False; + } + myCyclesLeft = myCycles; + } + + if(*myTriggerInput == 1 && myCyclesLeft > 0) + { + current_time = myRenderer->GetCurrentFrameTime(); + if(current_time >= myNextStateChange) + { + myCyclesLeft--; + myTriggerAttribute = (!myTriggerAttribute); + if(myTriggerAttribute) + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeTrue; + } + else + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeFalse; + } + } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +#endif +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for OneShotDelayRenderable +// This renderable delays for a fixed amount after it's creation, then turns on +// a trigger attribute. It is used for the triggering of other renderables a +// fixed time after an object is created. +OneShotDelayRenderable::OneShotDelayRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to wait before raising the trigger + Scalar duration_time // How long trigger is up (0.0 == stay up) +): + VideoRenderable(entity, execution_type) +{ + // Check incoming data + Verify(delay_time >= 0.0f); + Verify(duration_time >= 0.0f); + // Initialize variables + myState = WaitingForTriggerTime; + myEndTimeFlag = !Small_Enough(duration_time); + myTriggerTime = myRenderer->GetCurrentFrameTime(); + myTriggerTime += delay_time; + myTriggerEndTime = myTriggerTime + duration_time; + myTriggerAttribute = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for OneShotDelayRenderable +OneShotDelayRenderable::~OneShotDelayRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the OneShotDelayRenderable +Logical + OneShotDelayRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Verify(myTriggerTime > 0.0f); + Verify(myTriggerEndTime >= myTriggerTime); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the OneShotDelayRenderable +void + OneShotDelayRenderable::Execute() +{ + Scalar + current_time; + // Check our variables + Check(this); + if (myState != WaitingForEternity) + { + current_time = myRenderer->GetCurrentFrameTime(); + // putting this here insures that the one-time will always spend + // at least one frame at True before resetting. + if (myState == WaitingForTriggerTime) + { + if (current_time > myTriggerTime) + { + myTriggerAttribute = 1; + if (myEndTimeFlag) + { + myState = WaitingForTriggerEndTime; + } + else + { + myState = WaitingForEternity; + myRenderer->RemoveDynamicRenderable(this); + } + } + } + else if (myState == WaitingForTriggerEndTime) + { + if (current_time > myTriggerEndTime) + { + myTriggerAttribute = NULL; + myState = WaitingForEternity; + myRenderer->RemoveDynamicRenderable(this); + } + } + else + { + Dump(myState); + Fail("invalid myState"); + } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SweepRenderable +// When triggered this renderable sweeps it's output attribute from 0.0 to 1.0 +// over a preset time interval. Used for controling morphs. +SweepRenderable::SweepRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to take to sweep from 0 to 1 + int cycles, // number of times to cycle before stopping + int *trigger, // When it goes from 0 to 1 it resets the sweep generator + Scalar start_value, // Initial value of sweep (default = 0.0f) + Scalar end_value, // Final value of sweep (default = 1.0f) + SweepFunction sweep_function // Function applied to sweep +): + VideoRenderable(entity, execution_type) +{ + // + // Verify incoming data + // + Verify(delay_time >= 0.0f); + Verify(start_value <= end_value); + if (sweep_function == Y_SQR_X) + { Verify(start_value >= 0.0f); } + // + // Was an input trigger provided? + // + if(trigger) + { + // Yes, remember a pointer to it and it's state + myTrigger = trigger; + oldMyTrigger = *myTrigger; + } + else + { + // No, point it at a fake trigger that is turned on + fakeTrigger = 1; + myTrigger = &fakeTrigger; + oldMyTrigger = 0; + } + // + // Initialize other variables + // + mySweepFunction = sweep_function; + myStartValue = start_value; + myEndValue = end_value; + myCycleCount = cycles; + mySweepTime = delay_time; + mySweepAttribute = myStartValue; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SweepRenderable +SweepRenderable::~SweepRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SweepRenderable +Logical + SweepRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Verify(mySweepTime >= 0.0f) + Verify((mySweepAttribute >= myStartValue) && (mySweepAttribute <= myEndValue)); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SweepRenderable +void + SweepRenderable::Execute() +{ + // Check our variables + Check(this); + // + // Look for an edge in the trigger input + // + if(*myTrigger != oldMyTrigger) + { + // + // A transition from zero to nonzero resets all the sweep parameters + // and starts the process over again. + // + if(oldMyTrigger == 0) + { + // A transition from zero to nonzero causes a reset of sweep timers + // and starts the sweep running. + mySweepStart = myRenderer->GetCurrentFrameTime(); + mySweepAttribute = myStartValue; + myCyclesLeft = myCycleCount; + } + oldMyTrigger = *myTrigger; + } + // + // If the trigger is nonzero and the sweep isn't at 1 yet, update + // the sweep values. + // + if(oldMyTrigger != 0 && myCyclesLeft > 0) + { + Scalar + current_time; + // putting this here insures that the sweep will always spend one frame at + // {EndValue} before resetting. + current_time = myRenderer->GetCurrentFrameTime(); + if(mySweepAttribute >= myEndValue) + { + myCyclesLeft--; + if(myCyclesLeft > 0) + { mySweepStart = current_time; } + } + mySweepAttribute = myStartValue + (myEndValue - myStartValue) * + (current_time - mySweepStart) / mySweepTime; + if (mySweepFunction == Y_SQR_X) + { + mySweepAttribute = Sqrt(mySweepAttribute); + } +// else if (mySweepFunction == Y_ ) +// { +// } + if(mySweepAttribute > myEndValue) + { mySweepAttribute = myEndValue; } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for PullFogRenderable +// This routine handles swapping the fog settings in and out when you +// turn headlight systems on and off. +// +PullFogRenderable::PullFogRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical *light_1, + Logical *light_2 // address containing the trigger +): + VideoRenderable(entity, execution_type) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(light_1); + myLight1 = light_1; + myOldLight1 = !(*myLight1); + if(light_2 == NULL) + { + myLight2 = myLight1; + } + else + { + Check_Pointer(light_2); + myLight2 = light_2; + } + myOldLight2 = !(*myLight2); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for PullFogRenderable +// +PullFogRenderable::~PullFogRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the PullFogRenderable +// +Logical + PullFogRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myLight1); + Check_Pointer(myLight2); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for PullFogRenderable. +// +void + PullFogRenderable::Execute() +{ + Check(this); + if(*myLight1 != myOldLight1 || *myLight2 != myOldLight2) + { + myOldLight1 = *myLight1; + myOldLight2 = *myLight2; + if(myOldLight1 || myOldLight2) + { + myRenderer->SetFogStyle(DPLRenderer::searchLightOnFogStyle); + } + else + { + myRenderer->SetFogStyle(DPLRenderer::searchLightOffFogStyle); + } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLEffectRenderable +// This routine handles the creation of a DPL special effect whenever the +// trigger attribute changes. This is an edge triggered renderable and will +// generate an effect on ANY form of state change. The only way to effect the +// size and speed of the effect is by way of the DPL effect tables. +// +DPLEffectRenderable::DPLEffectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + int effect_type, // DPL effect number to trigger + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) + +): + VideoRenderable(entity, execution_type) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(trigger); + Verify(effect_type >= 0); + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + // + // Initialze the local variables + // + myTrigger = trigger; + oldMyTrigger = *myTrigger; + myEffectType = effect_type; + myEffectDCS = effect_DCS; + myEffectOffset = *offset_point; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLEffectRenderable +// +DPLEffectRenderable::~DPLEffectRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLEffectRenderable +// +Logical + DPLEffectRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myTrigger); + Verify(myEffectType >= 0); + #if DEBUG_LEVEL > 0 + if(myEffectDCS != NULL) + Check_Pointer(myEffectDCS); + #endif + Check(&myEffectOffset); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLEffectRenderable. +// +void + DPLEffectRenderable::Execute() +{ + Check_Pointer(myTrigger); + if(*myTrigger != oldMyTrigger) + { + dpl_EXPLOSION_EFFECT_INFO my_explosion; + oldMyTrigger = *myTrigger; + my_explosion.type = myEffectType; + my_explosion.x = myEffectOffset.x; + my_explosion.y = myEffectOffset.y; + my_explosion.z = myEffectOffset.z; + dpl_Effect ( dpl_effect_type_explosion, myEffectDCS, &my_explosion ); + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLPSFXRenderable +// This routine triggers a pfx whenever the trigger attribute goes true. +// since pfx effects have built-in durations we don't attempt to do any repeats +// or other controls here, we just start one and kill it if the entity dies. +// +DPLPSFXRenderable::DPLPSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) + +): + VideoRenderable(entity, execution_type) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(trigger); + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + if(!psfx_definition) + { + Fail("A pfx was not defined in the .ini file\n"); + } + // + // Initialze the local variables + // + myTrigger = trigger; + myOldTrigger = *myTrigger; + myEffectDCS = effect_DCS; + myEffectOffset = *offset_point; + myPSFXInfo = *psfx_definition; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLPSFXRenderable +// +DPLPSFXRenderable::~DPLPSFXRenderable() +{ + // !!!!HACK Note that because the effect id changes every time we start one, + // the destructor will only stop the last PFX played. We should probably + // be keeping track of all the ID's we've sent down to make sure everything + // attached to the DCS gets properly killed. + Check(this); + dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLPSFXRenderable +// +Logical + DPLPSFXRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myTrigger); + #if DEBUG_LEVEL > 0 + if(myEffectDCS != NULL) + Check_Pointer(myEffectDCS); + #endif + Check(&myEffectOffset); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLPSFXRenderable. +// +void + DPLPSFXRenderable::Execute() +{ + Check_Pointer(myTrigger); + if(*myTrigger != myOldTrigger) + { + myOldTrigger = *myTrigger; + if(myOldTrigger == True) + { + // we put our id into the lower 16 bits because (at least) the upper 8 bits are flags + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + myPSFXInfo.identifier = + (myPSFXInfo.identifier & 0xffff0000) | + l4_application->GetVideoRenderer()->GetUniqueID(); + dpl_Effect ( dpl_effect_type_particlestart, myEffectDCS, &myPSFXInfo ); + } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLPSFXStateRenderable +// This routine triggers a pfx whenever a state dial transitions to a designated +// state. +// NOTE this currently does NOT trigger if the state dial is in the trigger state +// when this renderable is created. +// +DPLPSFXStateRenderable::DPLPSFXStateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + StateIndicator *effect_trigger, // Trigger effect when this state changes + unsigned my_trigger, // The state to edge trigger on + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) +): + VideoRenderable(entity, execution_type) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check(effect_trigger); + Check_Pointer(psfx_definition); + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + if(!psfx_definition) + { + Fail("A pfx was not defined in the .ini file\n"); + } + // + // Initialze the local variables + // + myTriggerState = my_trigger; + myStateDial = effect_trigger; + myEffectDCS = effect_DCS; + myEffectOffset = *offset_point; + myPSFXInfo = *psfx_definition; + // + // Add us to the state's watcher socket + // + effect_trigger->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLPSFXStateRenderable +// +DPLPSFXStateRenderable::~DPLPSFXStateRenderable() +{ + // !!!!HACK Note that because the effect id changes every time we start one, + // the destructor will only stop the last PFX played. We should probably + // be keeping track of all the ID's we've sent down to make sure everything + // attached to the DCS gets properly killed. + Check(this); + dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLPSFXStateRenderable +// +Logical + DPLPSFXStateRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + #if DEBUG_LEVEL > 0 + if(myEffectDCS != NULL) + Check_Pointer(myEffectDCS); + #endif + Check(&myEffectOffset); + Check(myStateDial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLPSFXStateRenderable. +// Note that this will get called by the state dial, not by the renderer +// +void + DPLPSFXStateRenderable::Execute() +{ + Check(myStateDial); + // + // If the state dial is in the right state, trigger + // + if(myStateDial->GetState() == myTriggerState) + { + // we put our id into the lower 16 bits because (at least) the upper 8 bits are flags + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + myPSFXInfo.identifier = + (myPSFXInfo.identifier & 0xffff0000) | + l4_application->GetVideoRenderer()->GetUniqueID(); + dpl_Effect ( dpl_effect_type_particlestart, myEffectDCS, &myPSFXInfo ); + } + // + // Call the next lower execute method + // + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLMaterialRenderable +// This renderable creates a DPL Material structure and encapsulates it so +// it will be properly deleted when the object it's part of gets deleted. +DPLMaterialRenderable::DPLMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red, // Material's ambient component + Scalar ambient_green, + Scalar ambient_blue, + Scalar emissive_red, // Material's emissive component + Scalar emissive_green, + Scalar emissive_blue, + Scalar diffuse_red, // Material's diffuse component + Scalar diffuse_green, + Scalar diffuse_blue, + Scalar specular_red, // Material's specular component + Scalar specular_green, + Scalar specular_blue, + Scalar specular_shininess, + Scalar opacity_red, // Material's opacity + Scalar opacity_green, + Scalar opacity_blue, + dpl_TEXTURE *texture, // Material's texture pointer + Scalar z_dither, // Material's Z dither value + int fog_immune // Material's Fog Imunity value +): + VideoRenderable(entity, execution_type) +{ + // Check input pointers + #if DEBUG_LEVEL > 0 + if(texture) + Check_Pointer(texture); + #endif + // Create and initialize the DPL material + myMaterial = dpl_NewMaterial(); + Check_Pointer(myMaterial); + // + // Materials should be static most of the time, if they are dynamic it means someone + // inheriting from us is going to try and modify the material. So if we are dynamic + // we leave the rest of this stuff for that routine to do + // + if(execution_type == DPLMaterialRenderable::Static) + { + dpl_SetMaterialAmbient (myMaterial, ambient_red, ambient_green, ambient_blue); + dpl_SetMaterialEmissive (myMaterial, emissive_red, emissive_green, emissive_blue); + dpl_SetMaterialDiffuse (myMaterial, diffuse_red, diffuse_green, diffuse_blue); + dpl_SetMaterialSpecular (myMaterial, specular_red, specular_green, specular_blue, specular_shininess); + dpl_SetMaterialOpacity (myMaterial, opacity_red, opacity_green, opacity_blue); + if(texture) + dpl_SetMaterialTexture(myMaterial, texture); + if(z_dither) + dpl_SetMaterialDitherZ(myMaterial, z_dither); + if(fog_immune) + dpl_SetMaterialFogImmunity(myMaterial,fog_immune); + dpl_FlushMaterial(myMaterial); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLMaterialRenderable +DPLMaterialRenderable::~DPLMaterialRenderable() +{ + // Check our structure before we do anything + Check(this); + dpl_DeleteMaterial(myMaterial); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLMaterialRenderable +Logical + DPLMaterialRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myMaterial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLMaterialRenderable +void + DPLMaterialRenderable::Execute() +{ + Check(this); + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for MorphMaterialRenderable +// This renderable takes two material specifications and loads up a third +// material with a morph between the first two. +MorphMaterialRenderable::MorphMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red_1, // Material's ambient component + Scalar ambient_green_1, + Scalar ambient_blue_1, + Scalar emissive_red_1, // Material's emissive component + Scalar emissive_green_1, + Scalar emissive_blue_1, + Scalar diffuse_red_1, // Material's diffuse component + Scalar diffuse_green_1, + Scalar diffuse_blue_1, + Scalar specular_red_1, // Material's specular component + Scalar specular_green_1, + Scalar specular_blue_1, + Scalar specular_shininess_1, + Scalar opacity_red_1, // Material's opacity + Scalar opacity_green_1, + Scalar opacity_blue_1, + dpl_TEXTURE *texture_1, // Material's texture pointer + Scalar z_dither_1, // Material's Z dither value + int fog_immune_1, // Material's Fog Imunity value + Scalar ambient_red_2, // Material's ambient component + Scalar ambient_green_2, + Scalar ambient_blue_2, + Scalar emissive_red_2, // Material's emissive component + Scalar emissive_green_2, + Scalar emissive_blue_2, + Scalar diffuse_red_2, // Material's diffuse component + Scalar diffuse_green_2, + Scalar diffuse_blue_2, + Scalar specular_red_2, // Material's specular component + Scalar specular_green_2, + Scalar specular_blue_2, + Scalar specular_shininess_2, + Scalar opacity_red_2, // Material's opacity + Scalar opacity_green_2, + Scalar opacity_blue_2, + Scalar z_dither_2, // Material's Z dither value + Scalar *morph_control +): +DPLMaterialRenderable( + entity, // Entity to attach the renderable to + execution_type, + ambient_red_1, ambient_green_1, ambient_blue_1, // Material's ambient component + emissive_red_1, emissive_green_1, emissive_blue_1, // Material's emissive component + diffuse_red_1, diffuse_green_1, diffuse_blue_1, // Material's diffuse component + specular_red_1, specular_green_1, specular_blue_1, specular_shininess_1, // Material's specular component + opacity_red_1, opacity_green_1, opacity_blue_1, // Material's opacity + texture_1, // Material's texture pointer + z_dither_1, // Material's Z dither value + fog_immune_1) // Material's Fog Imunity value +{ + Scalar + Weight1, + Weight2; + // + // Remember the parameters of the two materials we are morphing between + // + myAmbientRed1 = ambient_red_1; // Material's ambient component + myAmbientGreen1 = ambient_green_1; + myAmbientBlue1 = ambient_blue_1; + myEmissiveRed1 = emissive_red_1; // Material's emissive component + myEmissiveGreen1 = emissive_green_1; + myEmissiveBlue1 = emissive_blue_1; + myDiffuseRed1 = diffuse_red_1; // Material's diffuse component + myDiffuseGreen1 = diffuse_green_1; + myDiffuseBlue1 = diffuse_blue_1; + mySpecularRed1 = specular_red_1; // Material's specular component + mySpecularGreen1 = specular_green_1; + mySpecularBlue1 = specular_blue_1; + mySpecularShininess1 = specular_shininess_1; + myOpacityRed1 = opacity_red_1; // Material's opacity + myOpacityGreen1 = opacity_green_1; + myOpacityBlue1 = opacity_blue_1; + myTexture1 = texture_1; // Material's texture pointer + myZDither1 = z_dither_1; // Material's Z dither value + myFogImmune1 = fog_immune_1; // Material's Fog Imunity value + myAmbientRed2 = ambient_red_2; // Material's ambient component + myAmbientGreen2 = ambient_green_2; + myAmbientBlue2 = ambient_blue_2; + myEmissiveRed2 = emissive_red_2; // Material's emissive component + myEmissiveGreen2 = emissive_green_2; + myEmissiveBlue2 = emissive_blue_2; + myDiffuseRed2 = diffuse_red_2; // Material's diffuse component + myDiffuseGreen2 = diffuse_green_2; + myDiffuseBlue2 = diffuse_blue_2; + mySpecularRed2 = specular_red_2; // Material's specular component + mySpecularGreen2 = specular_green_2; + mySpecularBlue2 = specular_blue_2; + mySpecularShininess2 = specular_shininess_2; + myOpacityRed2 = opacity_red_2; // Material's opacity + myOpacityGreen2 = opacity_green_2; + myOpacityBlue2 = opacity_blue_2; + myZDither2 = z_dither_2; // Material's Z dither value + myMorphControl = morph_control; + oldMorphControl = *morph_control; + // + // Calculate the target material + // + Weight1 = 1.0 - oldMorphControl; + Weight2 = oldMorphControl; + myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); + myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); + myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); + myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); + myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); + myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); + myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); + myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); + myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); + mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); + mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); + mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); + mySpecularShininess = (mySpecularShininess1*Weight1) + (mySpecularShininess2*Weight2); + myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); + myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); + myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); + myZDither = (myZDither1*Weight1) + (myZDither2*Weight2); + // + // Initialize the target material + // + dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); + dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); + dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); + dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); + dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); + if(myTexture1) + dpl_SetMaterialTexture(myMaterial, myTexture1); + if(myZDither) + dpl_SetMaterialDitherZ(myMaterial,myZDither); + if(myFogImmune1) + dpl_SetMaterialFogImmunity(myMaterial,myFogImmune1); + dpl_FlushMaterial(myMaterial); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for MorphMaterialRenderable +MorphMaterialRenderable::~MorphMaterialRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the MorphMaterialRenderable +Logical + MorphMaterialRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the MorphMaterialRenderable +void + MorphMaterialRenderable::Execute() +{ + Scalar + Weight1, + Weight2; + + Check(this); + // See if the morph control variable has changed + if(oldMorphControl != *myMorphControl) + { + // + // Re-calculate the target material + // + oldMorphControl = *myMorphControl; + Weight1 = 1.0 - oldMorphControl; + Weight2 = oldMorphControl; + myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); + myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); + myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); + myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); + myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); + myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); + myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); + myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); + myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); + mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); + mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); + mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); + mySpecularShininess = (mySpecularShininess1*Weight1) + (mySpecularShininess2*Weight2); + myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); + myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); + myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); + myZDither = (myZDither1*Weight1) + (myZDither2*Weight2); + // + // Reset the target material and flush it + // Note we don't try to morph texture or fog immune + // + dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); + dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); + dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); + dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); + dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); + if(myZDither) + dpl_SetMaterialDitherZ(myMaterial,myZDither); + dpl_FlushMaterial(myMaterial); + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLDamageMaterialRenderable +// This renderable handles modifying a material in response to damage. We +// get the pointer to an existing DPL material on startup and we get out +// color and texture settings from that +DPLDamageMaterialRenderable::DPLDamageMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_MATERIAL *damage_material, // The material we want to control + Scalar *damage_attribute, // The attribute containing the current damage level + Scalar damage_percent // Degradation factor to make damaged material +): + VideoRenderable(entity, execution_type) +{ + Scalar + Weight1, + Weight2; + + Check_Pointer(damage_material); + Check_Pointer(damage_attribute); + Verify(damage_percent >= 0.0f && damage_percent <= 1.0f); + // + // Grab the material's components, remember them and figure the target colors + // + myMaterial = damage_material; + myDamageAttribute = damage_attribute; + oldDamageAttribute = *myDamageAttribute; + dpl_GetMaterialAmbient (myMaterial, &myAmbientRed1, &myAmbientGreen1, &myAmbientBlue1); + dpl_GetMaterialEmissive (myMaterial, &myEmissiveRed1, &myEmissiveGreen1, &myEmissiveBlue1); + dpl_GetMaterialDiffuse (myMaterial, &myDiffuseRed1, &myDiffuseGreen1, &myDiffuseBlue1); + dpl_GetMaterialSpecular (myMaterial, &mySpecularRed1, &mySpecularGreen1, &mySpecularBlue1, &mySpecularShininess1); + dpl_GetMaterialOpacity (myMaterial, &myOpacityRed1, &myOpacityGreen1, &myOpacityBlue1); + myAmbientRed2 = damage_percent * myAmbientRed1; // Material's ambient component + myAmbientGreen2 = damage_percent * myAmbientGreen1; + myAmbientBlue2 = damage_percent * myAmbientBlue1; + myEmissiveRed2 = damage_percent * myEmissiveRed1; // Material's emissive component + myEmissiveGreen2 = damage_percent * myEmissiveGreen1; + myEmissiveBlue2 = damage_percent * myEmissiveBlue1; + myDiffuseRed2 = damage_percent * myDiffuseRed1; // Material's diffuse component + myDiffuseGreen2 = damage_percent * myDiffuseGreen1; + myDiffuseBlue2 = damage_percent * myDiffuseBlue1; + mySpecularRed2 = damage_percent * mySpecularRed1; // Material's specular component + mySpecularGreen2 = damage_percent * mySpecularGreen1; + mySpecularBlue2 = damage_percent * mySpecularBlue1; + mySpecularShininess2 = damage_percent * mySpecularShininess1; + myOpacityRed2 = damage_percent * myOpacityRed1; // Material's opacity + myOpacityGreen2 = damage_percent * myOpacityGreen1; + myOpacityBlue2 = damage_percent * myOpacityBlue1; + // + // Calculate the target material using the current level of damage + // + Weight1 = 1.0f - oldDamageAttribute; + Weight2 = oldDamageAttribute; + myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); + myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); + myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); + myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); + myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); + myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); + myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); + myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); + myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); + mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); + mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); + mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); + mySpecularShininess = (mySpecularShininess1*Weight1)+ (mySpecularShininess2*Weight2); + myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); + myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); + myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); + // + // Set the target material + // + dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); + dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); + dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); + dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); +// dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); + dpl_FlushMaterial(myMaterial); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLDamageMaterialRenderable +DPLDamageMaterialRenderable::~DPLDamageMaterialRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLDamageMaterialRenderable +Logical + DPLDamageMaterialRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myMaterial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLDamageMaterialRenderable +void + DPLDamageMaterialRenderable::Execute() +{ + Scalar + Weight1, + Weight2; + + Check(this); + if(oldDamageAttribute != *myDamageAttribute) + { + // + // Re-calculate the target material + // + oldDamageAttribute = *myDamageAttribute; + Weight1 = 1.0 - oldDamageAttribute; + Weight2 = oldDamageAttribute; + myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); + myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); + myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); + myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); + myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); + myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); + myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); + myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); + myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); + mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); + mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); + mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); + mySpecularShininess = (mySpecularShininess1*Weight1)+ (mySpecularShininess2*Weight2); + myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); + myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); + myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); + // + // Reset the target material and flush it + // + dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); + dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); + dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); + dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); +// dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); + dpl_FlushMaterial(myMaterial); + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~End of the new renderable class hiearchy~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~Dynamic Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~these renderables allow things to change after construction~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//############################################################################# +// This is the DPLEyeRenderable class. This is a DYNAMIC renderable that +// places the renderer's eyepoint relative to some other DCS/renderable. +// At the moment the eyepoint won't actually move in response to an argument +// but this will be changed after we have something to hook the eye to. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLEyeRenderable +// All the arguments are required. +// +DPLEyeRenderable::DPLEyeRenderable( + Entity* This_Entity, + dpl_ZONE* This_Zone, + const LinearMatrix& Offset_Matrix, + dpl_DCS* Parent_DCS, + dpl_VIEW* This_View, + EulerAngles* eyepoint_rotation // Pointer to attribute that contains eye rotations +): + Component(TrivialNodeClassID) +{ + // + // Check the inbound data + // + Check(This_Entity); + Check_Pointer(This_Zone); + Check(&Offset_Matrix); + Check_Pointer(Parent_DCS); + Check_Pointer(This_View); + #if DEBUG_LEVEL > 0 + if(eyepoint_rotation) + Check(eyepoint_rotation); + #endif + // + // Remember the entity that this renderable is attached to and the + // orientation matrix that sets the eye location + // + myEntity = This_Entity; + myParentDCS = Parent_DCS; + myOrientationMatrix = Offset_Matrix; + myEyepointRotation = eyepoint_rotation; + if(myEyepointRotation) + { + oldEyepointRotation = *myEyepointRotation; + } + else + { + oldEyepointRotation = NULL; + } + // + // Create the dpl DCS for this renderable, connect it to it's parent + // and set it into the current zone. + // + myDCS = dpl_NewDCS (); + Check_Pointer(myDCS); + dpl_AddDCSToDCS ( myParentDCS, myDCS ); + dpl_SetDCSZone ( myDCS, This_Zone ); + // + // Load up the DCS matrix with the supplied matrix + // + LinearMatrix rotation_matrix(True); + if(myEyepointRotation) + { + rotation_matrix = *myEyepointRotation; + } + rotation_matrix *= myOrientationMatrix; + float32* dplMatrix = dpl_GetDCSMatrix(myDCS); + Check_Pointer(dplMatrix); + *((Matrix4x4*)dplMatrix) = rotation_matrix; + // + // float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + // Check_Pointer(tempMatrix); + // *(Matrix4x4*)tempMatrix = OrientationMatrix; + // + // Flush out the instance and DCS + // + dpl_SetViewDCS ( This_View, myDCS); + dpl_FlushView ( This_View); + dpl_FlushDCS ( myDCS ); + +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLEyeRenderable +// After calling this the eyepoint must be relocated to another DCS before +// the execute method of the renderer is called. +// +DPLEyeRenderable::~DPLEyeRenderable() +{ + Check(this); +// Below is probably unnecessary as the parent should be destroyed too +// but Phil is making a patch to allow us to check that. +// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); + dpl_DeleteDCS(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLEyeRenderable +// +Logical + DPLEyeRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer(myDCS); + Check_Pointer(myParentDCS); + Check(&myOrientationMatrix); + Check(myEntity); + if(myEyepointRotation) + { + Check(myEyepointRotation); + } + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLEyeRenderable. +// +void + DPLEyeRenderable::Execute() +{ + // + //---------------------------------------------------------------------- + // If we have an eyepoint rotation specified, generate a new matrix each + // time based upon the setting of the eyepoint rotation + //---------------------------------------------------------------------- + // + if (myEyepointRotation) + { + if(*myEyepointRotation != oldEyepointRotation) + { + oldEyepointRotation = *myEyepointRotation; + Check(myEyepointRotation); + LinearMatrix rotation_matrix(True); + rotation_matrix = *myEyepointRotation; + rotation_matrix *= myOrientationMatrix; + float32* dplMatrix = dpl_GetDCSMatrix(myDCS); + Check_Pointer(dplMatrix); + *((Matrix4x4*)dplMatrix) = rotation_matrix; + HACK_DPL_FLUSH_DCS(myDCS); + } + } +} +// +//############################################################################# +// This is the DPLChildPointRenderable class. This is a dynamic renderable that +// lets you build a translating joint between two objects. If you supply a +// NULL Graphic_Object pointer when constructing the renderable it will be +// built without hooking up an instance of a graphical object. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLChildPointRenderable +// +DPLChildPointRenderable::DPLChildPointRenderable( + Entity* This_Entity, + dpl_ZONE* This_Zone, + dpl_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + dpl_DCS *Parent_DCS, + Point3D *my_point +): + Component(TrivialNodeClassID) +{ +// +// Check the inbound data +// + Check(This_Entity); + Check_Pointer(This_Zone); + #if DEBUG_LEVEL > 0 + if(Graphic_Object != NULL) + Check_Pointer(Graphic_Object); + #endif + Check(&Offset_Matrix); + Check_Pointer(Parent_DCS); + Check(my_point); +// +// Remember the entity that this renderable is attached to and the +// orientation matrix that sets the eye location +// + myEntity = This_Entity; + myParentDCS = Parent_DCS; + myPoint = my_point; + OrientationMatrix = Offset_Matrix; + OldPoint = *my_point; +// +// Create the dpl DCS, add it to the parent DCS, set it into the current zone, +// and stuff the orientation matrix into it +// + myOffsetDCS = dpl_NewDCS(); + Check_Pointer ( myOffsetDCS ); + dpl_AddDCSToDCS ( myParentDCS, myOffsetDCS ); + dpl_SetDCSZone ( myOffsetDCS, This_Zone ); + + myDCS = dpl_NewDCS(); + Check_Pointer ( myDCS ); + dpl_AddDCSToDCS ( myOffsetDCS, myDCS ); + dpl_SetDCSZone ( myDCS, This_Zone ); +// +// Setup the offset matrix in the offset DCS +// + float32* tempMatrix = dpl_GetDCSMatrix( myOffsetDCS ); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = OrientationMatrix; +// +// Setup the initial state of the hinge joint +// + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + *(Matrix4x4*)tempMatrix2 = *myPoint; +// +// If there was a graphic, create an instance with that graphic in it and link +// it to the DCS. +// + if(Graphic_Object == NULL) + { + myInstance = NULL; + } + else + { + myInstance = dpl_NewInstance(); + Check_Pointer ( myInstance ); + dpl_SetInstanceObject ( myInstance, Graphic_Object ); + dpl_SetInstanceIntersect ( myInstance, Intersect_Mode ); + dpl_SetInstanceSectMask ( myInstance, Intersect_Mask ); + dpl_SetInstanceVisibility ( myInstance, 1 ); + dpl_AddInstanceToDCS ( myDCS, myInstance ); + dpl_FlushInstance ( myInstance ); + } +// +// Flush out the DCS and add this to the static component list +// + dpl_FlushDCS ( myOffsetDCS ); + dpl_FlushDCS ( myDCS ); +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLChildPointRenderable +// + +DPLChildPointRenderable::~DPLChildPointRenderable() +{ + Check(this); +// Below is probably unnecessary as the parent should be destroyed too +// but Phil is making a patch to allow us to check that. +// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); + + dpl_DeleteDCS(myDCS); + dpl_DeleteDCS(myOffsetDCS); + if(myInstance != NULL) + { + dpl_DeleteInstance(myInstance); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLChildPointRenderable +// This method should really use a watcher to make sure the position of the +// object has changed before updating the DCS matrix. +// +void + DPLChildPointRenderable::Execute() +{ + Check(this); +// +// Load up the DCS matrix with the localToWorld matrix from the entity +// then flush out the new DCS +// + if(OldPoint != *myPoint) + { + OldPoint = *myPoint; + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + *(Matrix4x4*)tempMatrix2 = OldPoint; + HACK_DPL_FLUSH_DCS ( myDCS ); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLChildPointRenderable +// +Logical + DPLChildPointRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer ( myDCS ); + Check_Pointer ( myParentDCS ); + Check_Pointer ( myOffsetDCS ); + Check(myPoint); + if(myInstance != NULL) + { + Check_Pointer(myInstance); + } + Check(&OrientationMatrix); + Check(myEntity); + + return True; +} +// +//############################################################################# +// This is the DPLScaleRenderable class. This is a dynamic renderable that +// lets you scale everything downstream of it in the hiearchy. It is also +// setup to switch it's own instances on and off based on the value in visible. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLScaleRenderable +// +DPLScaleRenderable::DPLScaleRenderable( + Entity* This_Entity, + dpl_ZONE* This_Zone, + dpl_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + dpl_DCS *Parent_DCS, + Vector3D *scale_vector, + Logical *visible +): + Component(TrivialNodeClassID) +{ +// +// Check the inbound data +// + Check(This_Entity); + Check_Pointer(This_Zone); + Check_Pointer(Graphic_Object); + Check(&Offset_Matrix); + Check_Pointer(Parent_DCS); + Check(scale_vector); + Check_Pointer(visible); +// +// Remember the entity that this renderable is attached to and the +// orientation matrix that offsets it to the correct position. +// + myEntity = This_Entity; + myParentDCS = Parent_DCS; + myScaleVector = scale_vector; + myVisible = visible; + OffsetMatrix = Offset_Matrix; + OldScaleVector = *scale_vector; + OldVisible = *visible; +// +// Create the dpl DCS, add it to the parent DCS, set it into the current zone, +// and stuff the orientation matrix into it +// + myDCS = dpl_NewDCS(); + Check_Pointer ( myDCS ); + dpl_AddDCSToDCS ( myParentDCS, myDCS ); + dpl_SetDCSZone ( myDCS, This_Zone ); +// +// Setup the dcs matrix to it's initial state +// + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= OldScaleVector; + tempAffine *= OffsetMatrix; + *(Matrix4x4*)tempMatrix = tempAffine; +// +// If there was a graphic, create an instance with that graphic in it and link +// it to the DCS. +// + myInstance = dpl_NewInstance(); + Check_Pointer ( myInstance ); + dpl_SetInstanceObject ( myInstance, Graphic_Object ); + dpl_SetInstanceIntersect ( myInstance, Intersect_Mode ); + dpl_SetInstanceSectMask ( myInstance, Intersect_Mask ); + dpl_SetInstanceVisibility ( myInstance, OldVisible ); + dpl_AddInstanceToDCS ( myDCS, myInstance ); + dpl_FlushInstance ( myInstance ); +// +// Flush out the DCS and add this to the static component list +// + dpl_FlushDCS ( myDCS ); +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLScaleRenderable +// + +DPLScaleRenderable::~DPLScaleRenderable() +{ + Check(this); +// Below is probably unnecessary as the parent should be destroyed too +// but Phil is making a patch to allow us to check that. +// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); + + dpl_DeleteDCS(myDCS); + dpl_DeleteInstance(myInstance); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLScaleRenderable +// This method should really use a watcher to make sure the position of the +// object has changed before updating the DCS matrix. +// +void + DPLScaleRenderable::Execute() +{ + Check(this); +// +// Load up the DCS matrix with the localToWorld matrix from the entity +// then flush out the new DCS +// + if(OldVisible != *myVisible) + { + OldVisible = *myVisible; + dpl_SetInstanceVisibility ( myInstance, OldVisible ); + dpl_FlushInstance ( myInstance ); + } + + if(OldScaleVector != *myScaleVector) + { + OldScaleVector = *myScaleVector; + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine *= OldScaleVector; + tempAffine *= OffsetMatrix; + *(Matrix4x4*)tempMatrix2 = tempAffine; + HACK_DPL_FLUSH_DCS ( myDCS ); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLChildRenderable +// +Logical + DPLScaleRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer ( myDCS ); + Check_Pointer ( myParentDCS ); + Check_Pointer(myInstance); + Check(&OffsetMatrix); + Check(myEntity); + Check(myScaleVector); + + return True; +} +// +//############################################################################# +// This is the DPLScaleQuatRenderable class. This is a dynamic renderable that +// lets you control joint position with a Quaternion, Scale with a vector and +// switch the instance on and off with a logical. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLScaleQuatRenderable +// +DPLScaleQuatRenderable::DPLScaleQuatRenderable( + Entity* This_Entity, + dpl_ZONE* This_Zone, + dpl_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + dpl_DCS *Parent_DCS, + Quaternion *rotation_quaternion, + Vector3D *scale_vector, + Logical *visible +): + Component(TrivialNodeClassID) +{ + Quaternion my_quat; +// +// Check the inbound data +// + Check(This_Entity); + Check_Pointer(This_Zone); + Check_Pointer(Graphic_Object); + Check(&Offset_Matrix); + Check_Pointer(Parent_DCS); + Check(rotation_quaternion); + Check(scale_vector); + Check_Pointer(visible); +// +// Remember the entity that this renderable is attached to and the +// orientation matrix that offsets it to the correct position. +// + myEntity = This_Entity; + myParentDCS = Parent_DCS; + myRotationQuaternion = rotation_quaternion; + myScaleVector = scale_vector; + myVisible = visible; + OffsetMatrix = Offset_Matrix; + OldRotationQuaternion = *rotation_quaternion; + OldScaleVector = *scale_vector; + OldVisible = *visible; +// +// Create the dpl DCS, add it to the parent DCS, set it into the current zone, +// and stuff the orientation matrix into it +// + myDCS = dpl_NewDCS(); + Check_Pointer ( myDCS ); + dpl_AddDCSToDCS ( myParentDCS, myDCS ); + dpl_SetDCSZone ( myDCS, This_Zone ); +// +// Setup the dcs matrix to it's initial state +// + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); +// tempAffine.Multiply(OldRotationQuaternion,OffsetMatrix); + tempAffine *= OldScaleVector; + tempAffine *= OldRotationQuaternion; + tempAffine *= OffsetMatrix; + *(Matrix4x4*)tempMatrix = tempAffine; +// +// If there was a graphic, create an instance with that graphic in it and link +// it to the DCS. +// + myInstance = dpl_NewInstance(); + Check_Pointer ( myInstance ); + dpl_SetInstanceObject ( myInstance, Graphic_Object ); + dpl_SetInstanceIntersect ( myInstance, Intersect_Mode ); + dpl_SetInstanceSectMask ( myInstance, Intersect_Mask ); + dpl_SetInstanceVisibility ( myInstance, OldVisible ); + dpl_AddInstanceToDCS ( myDCS, myInstance ); + dpl_FlushInstance ( myInstance ); +// +// Flush out the DCS and add this to the static component list +// + dpl_FlushDCS ( myDCS ); +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLScaleQuatRenderable +// + +DPLScaleQuatRenderable::~DPLScaleQuatRenderable() +{ + Check(this); +// Below is probably unnecessary as the parent should be destroyed too +// but Phil is making a patch to allow us to check that. +// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); + + dpl_DeleteDCS(myDCS); + dpl_DeleteInstance(myInstance); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLScaleQuatRenderable +// This method should really use a watcher to make sure the position of the +// object has changed before updating the DCS matrix. +// +void + DPLScaleQuatRenderable::Execute() +{ + Check(this); +// +// Load up the DCS matrix with the localToWorld matrix from the entity +// then flush out the new DCS +// + if(OldVisible != *myVisible) + { + OldVisible = *myVisible; + dpl_SetInstanceVisibility ( myInstance, OldVisible ); + dpl_FlushInstance ( myInstance ); + } + + // + // The memcmp below is sort of a HACK but all I really care about is if the + // value in the quaternion has been changed since last time I saw it, this + // seems to be the easiest way to find out as JM hasn't written an == operator + // + if((OldScaleVector != *myScaleVector) || + (memcmp(&OldRotationQuaternion,myRotationQuaternion, sizeof(Quaternion)) != 0)) + { + OldScaleVector = *myScaleVector; + OldRotationQuaternion = *myRotationQuaternion; + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); +// tempAffine.Multiply(OldRotationQuaternion,OffsetMatrix); + tempAffine *= OldScaleVector; + tempAffine *= OldRotationQuaternion; + tempAffine *= OffsetMatrix; + *(Matrix4x4*)tempMatrix2 = tempAffine; + HACK_DPL_FLUSH_DCS ( myDCS ); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLScaleQuatRenderable +// +Logical + DPLScaleQuatRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer ( myDCS ); + Check_Pointer ( myParentDCS ); + Check_Pointer(myInstance); + Check(&OffsetMatrix); + Check(myEntity); + Check(myRotationQuaternion); + Check(myScaleVector); + Check_Pointer(myVisible); + + return True; +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~Static Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~these renderables remain constant after construction~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// +//############################################################################# +// This is the DPLStaticChildRenderable class. This is a STATIC renderable that +// lets you build a DCS that is a child of a pre-existing DCS. If you supply a +// NULL Graphic_Object pointer when constructing the renderable it will be +// built without hooking up an instance of a graphical object. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLStaticChildRenderable +// +DPLStaticChildRenderable::DPLStaticChildRenderable( + Entity* This_Entity, + dpl_ZONE* This_Zone, + dpl_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix& Offset_Matrix, + dpl_DCS* Parent_DCS +): + Component(TrivialNodeClassID) +{ +// +// Check the inbound data +// + Check(This_Entity); + Check_Pointer(This_Zone); + Check(&Offset_Matrix); + Check_Pointer(Parent_DCS); + #if DEBUG_LEVEL > 0 + if(Graphic_Object != NULL) + Check_Pointer(Graphic_Object); + #endif +// +// Remember the entity that this renderable is attached to and the +// orientation matrix that sets the eye location +// + myEntity = This_Entity; + myParentDCS = Parent_DCS; + OrientationMatrix = Offset_Matrix; +// +// Create the dpl DCS, add it to the parent DCS, set it into the current zone, +// and stuff the orientation matrix into it +// + myDCS = dpl_NewDCS (); + Check_Pointer ( myDCS ); + dpl_AddDCSToDCS ( myParentDCS, myDCS ); + dpl_SetDCSZone ( myDCS, This_Zone ); + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + *(Matrix4x4*)tempMatrix = OrientationMatrix; +// +// If there was a graphic, create an instance with that graphic in it and link +// it to the DCS. +// + if(Graphic_Object == NULL) + { + myInstance = NULL; + } + else + { + myInstance = dpl_NewInstance(); + Check_Pointer ( myInstance ); + dpl_SetInstanceObject ( myInstance, Graphic_Object ); + dpl_SetInstanceIntersect ( myInstance, Intersect_Mode ); + dpl_SetInstanceSectMask ( myInstance, Intersect_Mask ); + dpl_SetInstanceVisibility ( myInstance, 1 ); + dpl_AddInstanceToDCS ( myDCS, myInstance ); + dpl_FlushInstance ( myInstance ); + } +// +// Flush out the DCS and add this to the static component list +// + dpl_FlushDCS ( myDCS ); + myEntity->AddStaticVideoComponent(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLStaticChildRenderable +// + +DPLStaticChildRenderable::~DPLStaticChildRenderable() +{ + Check(this); +// Below is probably unnecessary as the parent should be destroyed too +// but Phil is making a patch to allow us to check that. +// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); + + dpl_DeleteDCS(myDCS); + if(myInstance != NULL) + { + dpl_DeleteInstance(myInstance); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLStaticChildRenderable +// +Logical + DPLStaticChildRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer(myDCS); + Check_Pointer(myParentDCS); + if(myInstance != NULL) + { + Check_Pointer(myInstance); + } + Check(&OrientationMatrix); + Check(myEntity); + + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~Special Effects Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//############################################################################# +// This is the DPLSFXRenderable class. This renderable is used to trigger a +// special effect in the world. The effect can be relative to a DCS or can be +// positioned in world coordinants by passing NULL as Parent_DCS. The trigger +// is a specific attribute entering a specific state. The effect will be +// generated repeatedly till the trigger changes state. +// +// This renderable is useful for triggering one-shot effects like puffs of smoke +// from guns or for triggering effects that the renderer will automatically +// repeat on it's own. +//############################################################################# +#define DPLSFXRenderable_MAX_RATE 28.0 // Repeat rate when speed = 1.0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLSFXRenderable +// +DPLSFXRenderable::DPLSFXRenderable( + Entity *This_Entity, // Entity to attach the effect to + dpl_ZONE* , //*This_Zone, // DPL zone everything will be in + const Point3D &Offset_Point, // Point offset from the parent DCS + dpl_DCS *Parent_DCS, // Parent DCS (can be NULL for world) + StateIndicator *Effect_Trigger, // Trigger effect when this state changes + int Trigger_State, // Trigger effect when in this state + int Effect_Type, // Type of effect to trigger + Scalar Repeat_Speed // Effect repeat speed. +): + Component(TrivialNodeClassID) +{ +// +// Check the inbound data, note that the parent DCS could be a null pointer +// + Check(This_Entity); +// Check_Pointer(This_Zone); + Check(&Offset_Point); + #if DEBUG_LEVEL > 0 + if(Parent_DCS != NULL) + Check_Pointer(Parent_DCS); + #endif + Check(Effect_Trigger); +// +// Remember the entity and DCS this renderable is attached to +// + myEntity = This_Entity; + myParentDCS = Parent_DCS; + myOffsetPoint = Offset_Point; + myEffectTrigger = Effect_Trigger; + myEffectTriggerOld = myEffectTrigger->GetState(); + myEffectTriggerState = Trigger_State; + myEffectType = Effect_Type; + myRepeatSpeed = 1.0/(Repeat_Speed * DPLSFXRenderable_MAX_RATE); + myLastEffect = 0.0; +// +// Register this effect as a dynamic renderable of the entity +// +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLSFXRenderable +// +DPLSFXRenderable::~DPLSFXRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLSFXRenderable +// +Logical + DPLSFXRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEntity); + #if DEBUG_LEVEL > 0 + if(myParentDCS != NULL) + Check_Pointer(myParentDCS); + #endif + Check(&myOffsetPoint) + Check_Pointer(myEffectTrigger); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLSFXRenderable. +// This watches the pre-assigned attribute pointer and triggers a special effect +// whenever that attribute changes. +// +void + DPLSFXRenderable::Execute() +{ + Scalar + current_time; + // + // Check data we're going to use. + // + #if DEBUG_LEVEL > 0 + if(myParentDCS != NULL) + Check_Pointer(myParentDCS); + #endif + Check_Pointer(myEffectTrigger); + // + // Is the attribute in the trigger state? + // + if(myEffectTrigger->GetState() == myEffectTriggerState) + { + // + // The effect is on, see if this is an edge + // + if(myEffectTriggerOld != myEffectTrigger->GetState()) + { + // + // An edge, reset the repeat timers so we will get an effect right now. + // + myLastEffect = 0.0; + } + // + // Is it time for another effect yet? + // + current_time = Now(); + if((myLastEffect + myRepeatSpeed) < current_time) + { + // + // Trigger the effect + // + dpl_EXPLOSION_EFFECT_INFO my_explosion; + my_explosion.type = myEffectType; + my_explosion.x = myOffsetPoint.x; + my_explosion.y = myOffsetPoint.y; + my_explosion.z = myOffsetPoint.z; + dpl_Effect ( dpl_effect_type_explosion, myParentDCS, &my_explosion ); + myLastEffect = current_time; + } + } + myEffectTriggerOld = myEffectTrigger->GetState(); +} +//############################################################################# +// This is the DPLRepeatSFXRenderable class. This renderable is used to trigger +// a special effect that repeats periodically with the repeat rate under program +// control. The most common use will probably be generating smoke trails. If +// the density argument is set to zero, no smoke will be generated. +//############################################################################# +#define DPLRepeatSFXRenderable_MAX_RATE 5.0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLRepeatSFXRenderable +// +DPLRepeatSFXRenderable::DPLRepeatSFXRenderable( + Entity *This_Entity, + dpl_ZONE* , //*This_Zone, + const Point3D &Offset_Point, + dpl_DCS *Parent_DCS, // offset is relative to this + int Effect_Type, // type code for the effect + Scalar *Speed +): + Component(TrivialNodeClassID) +{ +// +// Check the inbound data +// + Check(This_Entity); +// Check_Pointer(This_Zone); + Check(&Offset_Point); + #if DEBUG_LEVEL > 0 + if(Parent_DCS != NULL) + Check_Pointer(Parent_DCS); // it is allowed to be null + #endif + Check_Pointer(Speed); +// +// Remember the entity and DCS this renderable is attached to +// + myEntity = This_Entity; + myParentDCS = Parent_DCS; + myOffsetPoint = Offset_Point; + myEffectType = Effect_Type; + mySpeed = Speed; + myLastSmoke = 0.0; +// +// Setup as a dynamic renderable +// +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLRepeatSFXRenderable +// +DPLRepeatSFXRenderable::~DPLRepeatSFXRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLRepeatSFXRenderable +// +Logical + DPLRepeatSFXRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEntity); + #if DEBUG_LEVEL > 0 + if(myParentDCS != NULL) + Check_Pointer(myParentDCS); // it is allowed to be null + #endif + Check(&myOffsetPoint); + Check_Pointer(mySpeed); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLRepeatSFXRenderable. +// This watches the pre-assigned attribute pointer and triggers a special effect +// whenever that attribute changes. +// +void + DPLRepeatSFXRenderable::Execute() +{ +#define MAX_REPEAT_RATE 5.0 + Scalar + current_time; + // + // If speed is zero, the effect is turned off so we do nothing + // + if(*mySpeed == 0.0) + { + myLastSmoke = 0.0; + return; + } + // + // Figure how often we should generate smoke, speed ranges from 0 to 1, with + // 1 being the fastest + // + current_time = Now(); + if((myLastSmoke + (1.0/((*mySpeed) * DPLRepeatSFXRenderable_MAX_RATE))) < current_time) + { + dpl_EXPLOSION_EFFECT_INFO my_explosion; + myLastSmoke = current_time; + my_explosion.type = myEffectType; + my_explosion.x = myOffsetPoint.x; + my_explosion.y = myOffsetPoint.y; + my_explosion.z = myOffsetPoint.z; + dpl_Effect ( dpl_effect_type_explosion, myParentDCS, &my_explosion ); + } +} +//############################################################################# +// This is the DPLTranslocationRenderable class. This renderable handles the +// entire process of doing a UFT translocation effect from the perspective of +// people watching the player. This renderable is connected to the player object +// and manages positioning itself in the world based on information from that +// object. HACK HACK HACK (this will be obsolete when RP is fixed) +//############################################################################# +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLTranslocationRenderable +// +DPLTranslocationRenderable::DPLTranslocationRenderable( + Entity *This_Entity, // Entity to attach the effect to + dpl_ZONE *This_Zone, // DPL zone everything will be in + StateIndicator *Effect_Trigger, // Trigger effects off of this state dial + Point3D *Drop_Zone_Location, // Attribute that holds where the new drop will be + unsigned Drop_Zone_State +): + Component(TrivialNodeClassID) +{ +// +// Check the inbound data, note that the parent DCS could be a null pointer +// + Check(This_Entity); + Check_Pointer(This_Zone); + Check(Effect_Trigger); + Check(Drop_Zone_Location); +// +// Remember the entity and DCS this renderable is attached to +// + myEntity = This_Entity; + myZone = This_Zone; + myEffectTrigger = Effect_Trigger; + myEffectTriggerOld = myEffectTrigger->GetState(); + myDropZoneLocation = Drop_Zone_Location; + myDropZoneState = Drop_Zone_State; + myState = IdleState; +// +// Load up the object we're going to use for the translocation +// + dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere", dpl_load_normal ); + Check_Pointer(myTranslocateSphere); +// +// Setup a DCS that we can put the effect on so it can be rotated, scaled and +// placed anywhere we want in the world. +// + myInstance = dpl_NewInstance(); + myDCS = dpl_NewDCS(); + Check_Pointer (myInstance); + Check_Pointer (myDCS); + dpl_AddDCSToScene (myDCS); + dpl_SetDCSZone (myDCS, myZone); + dpl_SetInstanceObject (myInstance, myTranslocateSphere); + dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj); + dpl_SetInstanceSectMask (myInstance, NULL); + dpl_SetInstanceVisibility (myInstance, False); + dpl_AddInstanceToDCS (myDCS, myInstance); + dpl_FlushInstance (myInstance); + dpl_FlushDCS (myDCS); +// +// Register this effect as a dynamic renderable of the entity +// +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLTranslocationRenderable +// +DPLTranslocationRenderable::~DPLTranslocationRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLTranslocationRenderable +// +Logical + DPLTranslocationRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEntity); + Check(myEffectTrigger); + Check_Pointer(myZone); + Check(myDropZoneLocation); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLTranslocationRenderable. +// Note that the states listed here are temporary for testing and will be changed +// to player based effects as things are finalized. +// +void + DPLTranslocationRenderable::Execute() +{ + Scalar + current_time, + scale_factor; + unsigned + current_trigger_state; + // + // Check data we're going to use and get our current state to a local variable + // + Check_Pointer(myEffectTrigger); + current_trigger_state = myEffectTrigger->GetState(); + // HACK, because this renderable doesn't know what renderer it's on yet. + {L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + current_time = l4_application->GetVideoRenderer()->GetCurrentFrameTime();} +// current_time = myRenderer->GetCurrentFrameTime(); + // + // Simple state engine to manage the death/translocation effect + // + switch(myState) + { + case IdleState: + { + // + // Watch for transition to the dropzone acquired state + // + if(current_trigger_state == myDropZoneState) + { + myState = InitialExpandState; + myEffectTimer = current_time; + scale_factor = current_time - myEffectTimer; + if(scale_factor < 0.05f) + scale_factor = 0.05f; + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + *(Matrix4x4*)tempMatrix = tempAffine; + dpl_SetInstanceVisibility (myInstance, True); + dpl_FlushInstance (myInstance); + HACK_DPL_FLUSH_DCS (myDCS); + } + break; + } + case InitialExpandState: + { + scale_factor = current_time - myEffectTimer; + if(scale_factor < 0.05f) + scale_factor = 0.05f; + if(scale_factor >= 1.0) + { + scale_factor = 1.0; + myState = HoldAtSizeState; + } + // Below is a hack to build a scaling identity matrix + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + *(Matrix4x4*)tempMatrix2 = tempAffine; + HACK_DPL_FLUSH_DCS (myDCS); + break; + } + case HoldAtSizeState: + { + if((current_time - myEffectTimer) >= 3.0) + { + myState = ColapseState; + myEffectTimer = current_time + 1.0; + } + break; + } + case ColapseState: + { + scale_factor = myEffectTimer - current_time; + if(scale_factor < 0.05f) + { + scale_factor = 0.05f; + dpl_SetInstanceVisibility (myInstance, False); + dpl_FlushInstance (myInstance); + myState = IdleState; + } + // Below is a hack to build a scaling identity matrix + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + *(Matrix4x4*)tempMatrix2 = tempAffine; + HACK_DPL_FLUSH_DCS (myDCS); + break; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This is brand new stuff as of 5/12/96 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for OnePSFXRenderable +// This renderable triggers off a single PSFX effect and then hangs around and +// kills the effect when the renderable goes away. This is useful for things +// like missiles which you want to leave a smoke trail that stops if the object +// is destroyed. You REALLY want to do this whenever you attach an effect to +// a DCS since if the DCS goes away the DPL renderer will go wackey. +// +OnePSFXRenderable::OnePSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) +): + VideoRenderable(entity, execution_type) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + if(!psfx_definition) + { + Fail("A pfx was not defined in the .ini file\n"); + } + // + // Initialze the local variables + // + myPSFXInfo = *psfx_definition; + // + // Start the PFX immediately + // + myPSFXInfo.identifier = (myPSFXInfo.identifier & 0xffff0000) | myRenderer->GetUniqueID(); + dpl_Effect ( dpl_effect_type_particlestart, effect_DCS, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for OnePSFXRenderable +// +OnePSFXRenderable::~OnePSFXRenderable() +{ + // + // Since this renderable only sends one PSFX ID down, we only have to kill + // one PSFX, no need to track how many are spawned. + // + Check(this); + dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the OnePSFXRenderable +// +Logical + OnePSFXRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for OnePSFXRenderable. +// +void + OnePSFXRenderable::Execute() +{ + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for TranslocationRenderable +// This renderable does the UFT translocation effect from the perspective of +// someone else watching the person translocating. We connect this to the +// player object and uses information from that object to position itself. +// +TranslocationRenderable::TranslocationRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL zone everything will be in + StateIndicator *effect_trigger, // Trigger effects off of this state dial + Point3D *drop_zone_location, // Attribute that holds where the new drop will be + unsigned drop_zone_state // State that indicates drop zone is valid (starts effect) +): + VideoRenderable(entity, execution_type) +{ +// +// Check the inbound data, note that the parent DCS could be a null pointer +// + Check_Pointer(this_zone); + Check(effect_trigger); + Check(drop_zone_location); +// +// Remember the entity and DCS this renderable is attached to +// + myZone = this_zone; + myEffectTrigger = effect_trigger; + myDropZoneLocation = drop_zone_location; + myDropZoneState = drop_zone_state; + myState = IdleState; +// +// Load up the object we're going to use for the translocation +// + dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere", dpl_load_normal ); + Check_Pointer(myTranslocateSphere); +// +// Setup a DCS that we can put the effect on so it can be rotated, scaled and +// placed anywhere we want in the world. +// + myInstance = dpl_NewInstance(); + myDCS = dpl_NewDCS(); + Check_Pointer (myInstance); + Check_Pointer (myDCS); + dpl_AddDCSToScene (myDCS); + dpl_SetDCSZone (myDCS, myZone); + dpl_SetInstanceObject (myInstance, myTranslocateSphere); + dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj); + dpl_SetInstanceSectMask (myInstance, NULL); + dpl_SetInstanceVisibility (myInstance, False); + dpl_AddInstanceToDCS (myDCS, myInstance); + dpl_FlushInstance (myInstance); + dpl_FlushDCS (myDCS); +// +// Plug us into the watcher hook of the effect trigger state dial +// + myEffectTrigger->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for TranslocationRenderable +// +TranslocationRenderable::~TranslocationRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the TranslocationRenderable +// +Logical + TranslocationRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEffectTrigger); + Check_Pointer(myZone); + Check(myDropZoneLocation); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for TranslocationRenderable. +// Note that the states listed here are temporary for testing and will be changed +// to player based effects as things are finalized. +// +void + TranslocationRenderable::Execute() +{ + Scalar + current_time, + scale_factor; + unsigned + current_trigger_state; + // + // Check data we're going to use and get our current state to a local variable + // + Check(myEffectTrigger); + current_trigger_state = myEffectTrigger->GetState(); + current_time = myRenderer->GetCurrentFrameTime(); + // + // Simple state engine to manage the death/translocation effect + // +// cout<<"TranslocationRenderable::Execute\n"; + switch(myState) + { + case IdleState: + { + // + // Watch for transition to the dropzone acquired state + // + if(current_trigger_state == myDropZoneState) + { + myState = InitialExpandState; + myEffectTimer = current_time; + scale_factor = current_time - myEffectTimer; + if(scale_factor < 0.05f) + scale_factor = 0.05f; + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + *(Matrix4x4*)tempMatrix = tempAffine; + dpl_SetInstanceVisibility (myInstance, True); + dpl_FlushInstance (myInstance); + DPL_FLUSH_DCS (myDCS); + myRenderer->AddDynamicRenderable(this); +// cout<<"TranslocationRenderable Going Dynamic\n"; + } + break; + } + case InitialExpandState: + { + scale_factor = current_time - myEffectTimer; + if(scale_factor < 0.05f) + scale_factor = 0.05f; + if(scale_factor >= 1.0) + { + scale_factor = 1.0; + myState = HoldAtSizeState; + } + // Below is a hack to build a scaling identity matrix + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + *(Matrix4x4*)tempMatrix2 = tempAffine; + DPL_FLUSH_DCS (myDCS); + break; + } + case HoldAtSizeState: + { + if((current_time - myEffectTimer) >= 3.0) + { + myState = ColapseState; + myEffectTimer = current_time + 1.0; + } + break; + } + case ColapseState: + { + scale_factor = myEffectTimer - current_time; + if(scale_factor < 0.05f) + { + scale_factor = 0.05f; + dpl_SetInstanceVisibility (myInstance, False); + dpl_FlushInstance (myInstance); + myState = IdleState; + myRenderer->RemoveDynamicRenderable(this); +// cout<<"TranslocationRenderable Going Static\n"; + } + // Below is a hack to build a scaling identity matrix + float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + *(Matrix4x4*)tempMatrix2 = tempAffine; + DPL_FLUSH_DCS (myDCS); + break; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SpinScaleQuatWatcherRenderable +// +SpinScaleQuatWatcherRenderable::SpinScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Scalar z_spin_rate // spins the object about z (radians/frame) + ): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + // + // Check the inbound data + // + Check(control); + Check(rotation_quaternion); + Check(scale_vector); + // + // Remember the entity that this renderable is attached to and the + // orientation matrix that offsets it to the correct position. + // + myControl = control; + myTriggerState = effect_trigger_state; + myVisible = False; + myRotationQuaternion = rotation_quaternion; + myScaleVector = scale_vector; + myZSpinRate = z_spin_rate; + OldZSpin = 0; + // + // Setup the dcs matrix to it's initial state + // + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= (*myScaleVector); + tempAffine *= (*myRotationQuaternion); + *(Matrix4x4*)tempMatrix = tempAffine; + dpl_FlushDCS ( myDCS ); + // + // Set the instance visibility correctly + // + dpl_SetInstanceVisibility ( myInstance, myVisible ); + dpl_FlushInstance ( myInstance ); +// +// Plug us into the watcher hook of the effect trigger state dial +// + myControl->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SpinScaleQuatWatcherRenderable +// +SpinScaleQuatWatcherRenderable::~SpinScaleQuatWatcherRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SpinScaleQuatWatcherRenderable +// +Logical + SpinScaleQuatWatcherRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + Check(myControl); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SpinScaleQuatWatcherRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + SpinScaleQuatWatcherRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Check data we're going to use and get our current state to a local variable + // +// cout<<"SpinScaleQuatWatcherRenderable::Execute "<GetState()<<"\n"; + if(myControl->GetState() == myTriggerState) + { + // + // We're in the trigger state, if we aren't already visible, make us + // visible and dynamic now. + // + if(!myVisible) + { + myVisible = True; + dpl_SetInstanceVisibility ( myInstance, True ); + dpl_FlushInstance ( myInstance ); + myRenderer->AddDynamicRenderable(this); +// cout<<"SpinScaleQuatWatcherRenderable Going Dynamic\n"; + } + // + // Now update the beam + // + OldZSpin += myZSpinRate; + if(OldZSpin > TWO_PI) + OldZSpin -= TWO_PI; + Hinge temp_hinge(Z_Axis, OldZSpin); + + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + + AffineMatrix tempAffine(True); + Quaternion temp_quaternion; + temp_quaternion = temp_hinge; + tempAffine = temp_quaternion; + tempAffine *= (*myScaleVector); + tempAffine *= (*myRotationQuaternion); + *(Matrix4x4*)tempMatrix = tempAffine; + DPL_FLUSH_DCS ( myDCS ); + } + else + { + // + // We've left the trigger state, so if we're visible we make the beam + // invisible and go static. + // + if(myVisible) + { + myVisible = False; + dpl_SetInstanceVisibility ( myInstance, False ); + dpl_FlushInstance ( myInstance ); + myRenderer->RemoveDynamicRenderable(this); +// cout<<"SpinScaleQuatWatcherRenderable Going Static\n"; + } + } + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ScaleQuatWatcherRenderable +// +ScaleQuatWatcherRenderable::ScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector // Scales the object +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + this_zone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + // + // Check the inbound data + // + Check(control); + Check(rotation_quaternion); + Check(scale_vector); + // + // Remember the entity that this renderable is attached to and the + // orientation matrix that offsets it to the correct position. + // + myControl = control; + myTriggerState = effect_trigger_state; + myVisible = False; + myRotationQuaternion = rotation_quaternion; + myScaleVector = scale_vector; + // + // Setup the dcs matrix to it's initial state + // + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= (*myScaleVector); + tempAffine *= (*myRotationQuaternion); + *(Matrix4x4*)tempMatrix = tempAffine; + dpl_FlushDCS ( myDCS ); + // + // Set the instance visibility correctly + // + dpl_SetInstanceVisibility ( myInstance, myVisible ); + dpl_FlushInstance ( myInstance ); +// +// Plug us into the watcher hook of the effect trigger state dial +// + myControl->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ScaleQuatWatcherRenderable +// +ScaleQuatWatcherRenderable::~ScaleQuatWatcherRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ScaleQuatWatcherRenderable +// +Logical + ScaleQuatWatcherRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + Check(myControl); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ScaleQuatWatcherRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ScaleQuatWatcherRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Check data we're going to use and get our current state to a local variable + // + //cout<<"ScaleQuatWatcherRenderable::Execute "<GetState()<<"\n"; + if(myControl->GetState() == myTriggerState) + { + // + // We're in the trigger state, if we aren't already visible, make us + // visible and dynamic now. + // + if(!myVisible) + { + myVisible = True; + dpl_SetInstanceVisibility ( myInstance, True ); + dpl_FlushInstance ( myInstance ); + myRenderer->AddDynamicRenderable(this); +// cout<<"ScaleQuatWatcherRenderable Going Dynamic\n"; + } + // + // Now update the beam + // + float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= (*myScaleVector); + tempAffine *= (*myRotationQuaternion); + *(Matrix4x4*)tempMatrix = tempAffine; + DPL_FLUSH_DCS ( myDCS ); + } + else + { + // + // We've left the trigger state, so if we're visible we make the beam + // invisible and go static. + // + if(myVisible) + { + myVisible = False; + dpl_SetInstanceVisibility ( myInstance, False ); + dpl_FlushInstance ( myInstance ); + myRenderer->RemoveDynamicRenderable(this); +// cout<<"ScaleQuatWatcherRenderable Going Static\n"; + } + } +// if(*myTest != myVisible) +// { +// cout<<"myTest="<<*myTest<<" myVisible="< +# endif + +# if !defined(RETICLE_HPP) +# include +# endif + +# if !defined(SIMULATE_HPP) +# include +# endif + +# if !defined(LINMTRX_HPP) +# include +# endif + +# if !defined(CSTR_HPP) +# include +# endif + +# if !defined(SLOT_HPP) +# include +# endif + +#include +#include +#include +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +// All the stuff between these big ugly bars is the new video component stuff// + + typedef enum + { + NullVideoControlID = 0, + StartVideoControlID = 1, + StopVideoControlID = 2, + } VideoControlID; + + typedef enum + { + StaticVideoExecutionType = 0, + DynamicVideoExecutionType = 1, + WatcherVideoExecutionType = 2, + } VideoExecutionType; + + typedef enum + { + NotDPLComponentType = 0, + } DPLComponentType; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Video component base class +// + class VideoComponent: + public Component + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + VideoComponent( + Entity *entity, // Entity to attach the renderable to + VideoExecutionType execution_type); // How/when to execute the renderable + + ~VideoComponent(); + + Logical + TestInstance() const; + // + //-------------------------------------------------------------------- + // Add, handles establishing graphical hiearchal links between + // things like DCS's, Instances, geometry and so on. This does not + // establish a control path, only a graphical hiearchy. For each + // target type that something can be added to there is also an + // AddMeToTYPE(component) virtual (ie: AddMeToDCS) + //-------------------------------------------------------------------- + // + virtual void + Add( + VideoComponent *component_to_add); + virtual void + AddMeToDCS( + VideoComponent *component_to_add) + {Fail("Don't know how to add this component to a DCS\n");}; + virtual void + AddMeToInstance( + VideoComponent *component_to_add) + {Fail("Don't know how to add this component to an Instance\n");}; + virtual void + AddMeToScene( + VideoComponent *component_to_add) + {Fail("Don't know how to add this component to a Scene\n");}; + // + //-------------------------------------------------------------------- + // Connect, connects a control path between us and the component + // in the argument. The path goes from us to that element. + //-------------------------------------------------------------------- + // + virtual void + Connect( + VideoComponent *component_to_connect); + // + //-------------------------------------------------------------------- + // ReceiveControl, called by people connected to us to send control + // inputs to us. For the moment we will have several virtuals that + // accept different control types. + //-------------------------------------------------------------------- + // + virtual void + ReceiveControl( + VideoControlID control_ID, + Scalar control_value + ); + // + //-------------------------------------------------------------------- + // Execute + //-------------------------------------------------------------------- + // + void + Execute(); + + protected: + #if DEBUG_LEVEL > 0 + VideoExecutionType + myExecutionType; // We use this to test if the component is in the wrong list + #endif + + SlotOf + videoComponentSocket; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLDCSWrapper class +// + class DPLDCSWrapper: + public VideoComponent + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + DPLDCSWrapper( + Entity *entity, // Entity to attach the renderable to + VideoExecutionType execution_type, // How/when to execute the renderable + LinearMatrix initial_matrix); // Initial value to put into the matrix + + ~DPLDCSWrapper(); + + Logical + TestInstance() const; + + void + Add( + VideoComponent *component_to_add); + void + Connect( + VideoComponent *component_to_connect); + void + ReceiveControl( + VideoControlID control_ID, + Scalar control_value + ); + void + Execute(); + + protected: + dpl_DCS + *my_DCS; + }; + +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~New Class Hiearchy for Renderables~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Video renderable base class +// + class VideoRenderable: + public Component + { + public: + enum ExecutionType + { + Static = 0, + Dynamic, + Watcher, + Dependant, + NextExecutionType + }; + + VideoRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type); // How/when to execute the renderable + + ~VideoRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + DPLRenderer + *myRenderer; // The renderer that owns this renderable + + Entity + *myEntity; // The entity we are linked to + + ExecutionType + myExecutionType; // How/when to execute the renderable + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~This is a special class to speed up projectiles~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class InnerProjectileRenderable: + public Component + { + public: + InnerProjectileRenderable( + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone); // DPL Zone this stuff will live in (for culling) + + ~InnerProjectileRenderable(); + + Logical + TestInstance() const; + + dpl_DCS* + GetDCS() + {return myDCS;} + + dpl_INSTANCE* + GetInstance() + {return myInstance;} + + protected: + dpl_DCS + *myDCS; + dpl_INSTANCE + *myInstance; + }; + + class ProjectileRootRenderable: + public VideoRenderable + { + public: + ProjectileRootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone); // DPL Zone this stuff will live in (for culling) + + ~ProjectileRootRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + protected: + InnerProjectileRenderable + *myInnerProjectile; + LinearMatrix + oldLocalToWorld; // The value of this matrix the last time through + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ChildLightRenderable +// This renderable is used to connect a light as a child of an existing DCS +// the light isn't setup to move on it's own and creates a DCS only for the +// purpose of offsetting it from it's parent. +// + class ChildLightRenderable: + public VideoRenderable + { + public: + + ChildLightRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Scalar red, // light color + Scalar green, + Scalar blue, + Scalar inner_radius, + Scalar outer_radius, + dpl_LIGHT_TYPE light_type, + int light_mask); + + ~ChildLightRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_LIGHT + *myLight; + dpl_DCS + *myDCS, + *myParentDCS; + dpl_ZONE + *myZone; + LinearMatrix + myOffsetMatrix; + }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLObjectWrapper is a wrapper class that holds on to one of DPL's objects +// so it can be deleted properly at a later time. +// + class DPLObjectWrapper: + public VideoRenderable + { + public: + DPLObjectWrapper( + Entity *entity, // Entity to attach the renderable to + const CString &name, // Name of the DPL object to load into the wrapper + dpl_LOAD_MODE cache_mode); // DPL Zone this stuff will live in (for culling) + + ~DPLObjectWrapper(); + + Logical + TestInstance() const; + + dpl_OBJECT* + GetDPLObject() + {return myDPLObject;} + + CString* + GetDPLObjectName() + {return &myDPLObjectName;} + + void + Execute(); + + protected: + CString + myDPLObjectName; + dpl_LOAD_MODE + myCacheMode; + dpl_OBJECT + *myDPLObject; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DCSObjectRenderable a subclass not intended to be used on it's own, it +// encapsulates the information that follows a DCS node around. Parameters +// marked with are allowed to be passed in as NULL values. +// + class DCSObjectRenderable: + public VideoRenderable + { + public: + DCSObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask); // intersection mask for the object + + ~DCSObjectRenderable(); + + Logical + TestInstance() const; + + dpl_DCS* + GetDCS() + {return myDCS;} + dpl_INSTANCE* + GetInstance() + {return myInstance;} + + void + Execute(); + + protected: + dpl_OBJECT + *myDPLObject; + dpl_ZONE + *myDPLZone; + dpl_ISECT_MODE + myIntersectMode; + uint32 + myIntersectMask; + dpl_DCS + *myDCS; // The dpl DCS we create to hold the instance of this object + dpl_INSTANCE + *myInstance; // Instance that we hang on the DCS + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DCSInstanceRenderable Creates a DPL instance and binds it to a DCS. This +// is mainly used to insure these instances will be deleted properly when the +// object goes away. +// + class DCSInstanceRenderable: + public VideoRenderable + { + public: + DCSInstanceRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to connect to the instance + dpl_DCS *parent_DCS, // the DCS to add the instance to + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + Logical visible); // initial visibility setting + + ~DCSInstanceRenderable(); + + Logical + TestInstance() const; + + dpl_INSTANCE* + GetInstance() + {return myInstance;} + + void + Execute(); + + protected: + dpl_OBJECT + *myDPLObject; + dpl_ISECT_MODE + myIntersectMode; + uint32 + myIntersectMask; + dpl_DCS + *myDCS; // The dpl DCS we create to hold the instance of this object + dpl_INSTANCE + *myInstance; // Instance that we hang on the DCS + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RootRenderable handles an entity that is assumed to be attached at the root +// of the DCS hiearchy. That is, it's connected to the scene rather than to +// another DCS. The root automatically connects up to entity->localToWorld +// + class RootRenderable: + public DCSObjectRenderable + { + public: + RootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask); // intersection mask for the object + + ~RootRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + LinearMatrix + oldLocalToWorld; // The value of this matrix the last time through + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ChildOffsetRenderable is an intermediate layer that establishes a DCS to handle +// a static offset matrix to be applied prior to the DCS that actually carries +// joint and geometry information. This is not intended to ever be used +// directly. +// + class ChildOffsetRenderable: + public DCSObjectRenderable + { + public: + ChildOffsetRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix); // offset matrix to be applied prior to joint DCS + + ~ChildOffsetRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + LinearMatrix + myOffsetMatrix; // The offset to apply prior to the joint DCS + dpl_DCS + *myParentDCS, // Pointer to our parent DCS + *myOffsetDCS; // The dpl DCS we create to hold the offset from our parent. + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HingeRenderable Handles controlling a joint by way of a munga HINGE class +// attribute. +// + class HingeRenderable: + public ChildOffsetRenderable + { + public: + HingeRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const Hinge *my_hinge); // Hinge attribute we will use to control the joint + + ~HingeRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + const Hinge + *myHinge; // Pointer to the hinge attribute we use to modify the DCS + Hinge + oldHinge; // Copy of the last value of hinge + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// SpinScaleQuatRenderable Handles creates a spinning scaled quaternion controlled +// effect. +// + class SpinScaleQuatRenderable: + public ChildOffsetRenderable + { + public: + SpinScaleQuatRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Logical *visible, // turns the object on and off + Scalar z_spin_rate); // spins the object about z (radians/frame) + + ~SpinScaleQuatRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Quaternion + *myRotationQuaternion; + Vector3D + *myScaleVector; + Logical + *myVisible, + OldVisible; + Scalar + myZSpinRate, + OldZSpin; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// BallJointRenderable Handles controlling a joint by way of a munga eulers +// + class BallJointRenderable: + public ChildOffsetRenderable + { + public: + BallJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler); // Euler angles to control rotation of the ball joint + + ~BallJointRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + const EulerAngles + *myEuler; // Pointer to the hinge attribute we use to modify the DCS + EulerAngles + oldEuler; // Copy of the last value of hinge + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// BallTranslateJointRenderable Handles controlling a joint by way of a munga eulers +// + class BallTranslateJointRenderable: + public ChildOffsetRenderable + { + public: + BallTranslateJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler, // Euler angles to control rotation of the ball joint + const Point3D *my_translation); // offset for the translation part of the joint + + ~BallTranslateJointRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + const Point3D + *myTranslation; + Point3D + oldTranslation; + + const EulerAngles + *myEuler; // Pointer to the hinge attribute we use to modify the DCS + EulerAngles + oldEuler; // Copy of the last value of hinge + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// POVTranslocateRenderable generates a translocation effect from the point of +// view of a player. + class POVTranslocateRenderable: + public VideoRenderable // from the POV of the player + { + public: + POVTranslocateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + StateIndicator *effect_trigger, // State dial we use to control the translocation + unsigned effect_control_state); // State that controls start/end of the effect + + ~POVTranslocateRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + enum TranslocateState + { + IdleState, + FlashScreenState, + InitialCollapseState, + WaitForReincarnateState, + ExpandRevealState + }; + + TranslocateState + myState; + + int + myEffectControlState; + + Scalar + myRotateY, + myRotateYSpeed, + myCollapseEnd; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_INSTANCE + *myInstance; + + dpl_DCS + *myParentDCS, // Pointer to our parent DCS + *myDCS; + + dpl_ZONE + *myDeathZone, + *myZone; + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// POVStartEndRenderable generates a translocation effect from the point of +// view of a player. + class POVStartEndRenderable: + public VideoRenderable // from the POV of the player + { + public: + POVStartEndRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + dpl_VIEW *this_view, // The view containing our eye + StateIndicator *effect_trigger, // State dial we use to control the translocation + float red_fog, // Fog color + float green_fog, + float blue_fog, + float near_fog, // The near fog plane + float far_fog, // The far fog plane + unsigned start_mission_state, // State that signals start of mission + unsigned end_mission_state); // State that signals end of mission + + ~POVStartEndRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + enum StartEndState + { + WaitForStartState, + FlashScreenState, + FadeInState, + MissionRunningState, + FadeOutState + }; + + StartEndState + myState; + + int + myStartMissionState, // Signals mission is starting but player can't move yet + myEndMissionState; // Signals mission is ending + + float + myFogRed, + myFogGreen, + myFogBlue, + myFogNear, + myFogFar; + + Scalar + myStateTimer; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_ZONE + *myDeathZone, + *myZone; + + dpl_VIEW + *myView; + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ReticleRenderable drawing a static or dynamic reticle in the 2D layer of the +// screen. +// + class ReticleRenderable: + public VideoRenderable + { + public: + ReticleRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Reticle **my_reticle, // points to renderable reticle pointer that points to entity's reticle + dpl_VIEW *this_view); // the view associated with our eye + + ~ReticleRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + + Vector2DOf + myOldReticlePosition; // Last known position of the reticle + + Reticle::ReticleState + myOldReticleState; // Last known state of the reticle + + Reticle + **rendererReticle, // Points to renderer's reticle pointer + *myReticle; // Points directly to reticle in entity + + dpl_VIEW + *myView; + + dpl2d_DISPLAY + *myReticleDisplayList, + *myPositionDisplayList; + + }; +#define MAX_PLAYER_NAMES 12 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shows Player bitmap for the CameraShip +// +// + class CameraShipHUDRenderable : + public VideoRenderable + { + public: + + CameraShipHUDRenderable( + Entity *entity, + ExecutionType execution_type, + int *player_index, + Logical *display_ranking_window + ); + + ~CameraShipHUDRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + + int + playerCount; + + int + oldFollowedPlayerIndex, + *followedPlayerIndex; + + int + **playerRank, + *oldPlayerRank; + + Logical + *displayRankingWindow, + oldDisplayRankingWindow; + + dpl_OBJECT + *playerNameObject[MAX_PLAYER_NAMES], + *ordinalObject[MAX_PLAYER_NAMES]; + + dpl_DCS + *followedNameDCS, + *followedOrdinalDCS; + + dpl_INSTANCE + *followedNameInstance, + *followedOrdinalInstance; + + dpl_DCS + *rankingWindowDCS, + **nameDCS, + **rankDCS; + + dpl_INSTANCE + **nameInstance, + **rankInstance; + }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This class is used to store a stack of threat vectors +// + class VectorStackElement: + public Plug + { + public: + VectorStackElement( + float add_time, // Time when this threat was added + Vector2DOf *vector_to_stack) // The vector to stack up + {myAddTime = add_time; myVector = *vector_to_stack;myRecent=True;} + + ~VectorStackElement(){}; + + Logical + TestInstance() const + {Check(&myVector);return(True);} + + Vector2DOf + myVector; + float + myAddTime; + Logical + myRecent; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DCSMorphObjectRenderable a subclass not intended to be used on it's own, it +// encapsulates the information that needed to construct a destination dpl_Object +// by morphing two existing objects into it. +// + class DCSMorphObjectRenderable: + public VideoRenderable + { + public: + DCSMorphObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask); // intersection mask for the object + + ~DCSMorphObjectRenderable(); + + Logical + TestInstance() const; + + dpl_DCS* + GetDCS() + {return myDCS;} + + void + Execute(); + + protected: + int32 + myMorphMode; + Scalar + oldMorphControl, + *myMorphControl; + dpl_OBJECT + *myStartObject, + *myEndObject, + *myDPLObject; + dpl_ZONE + *myDPLZone; + dpl_ISECT_MODE + myIntersectMode; + uint32 + myIntersectMask; + dpl_DCS + *myDCS; // The dpl DCS we create to hold the instance of this object + dpl_INSTANCE + *myInstance; // Instance that we hang on the DCS + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ScalingExplosionRenderable Handles controlling a joint by way of a munga HINGE class +// attribute. +// + class ScalingExplosionRenderable: + public ChildOffsetRenderable + { + public: + ScalingExplosionRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // This will be the scaling explosion object + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Vector3D *control_vector, // Effect control vector, Y is acceleration, X, Z are velocity + Vector3D *accel_vector, // rate of change of control vector + Scalar gravity, + int *trigger); + + ~ScalingExplosionRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + int + *myTrigger; + Scalar + myVelocity, + myGravity; + Point3D + myTranslation; + Vector3D + myVelocityChange, + myScalingVector, // Controls scaling of the explosion + myVelocityVector; // Scaling velocity (rate of change) + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RootMorphRenderable handles an entity that is assumed to be attached at the root +// of the DCS hiearchy. That is, it's connected to the scene rather than to +// another DCS. The root automatically connects up to entity->localToWorld +// + class RootMorphRenderable: + public DCSMorphObjectRenderable + { + public: + RootMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask); // intersection mask for the object + + ~RootMorphRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + LinearMatrix + oldLocalToWorld; // The value of this matrix the last time through + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ChildMorphRenderable +// + class ChildMorphRenderable: + public DCSMorphObjectRenderable + { + public: + ChildMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS); // the parent DCS we will be offsetting from + + ~ChildMorphRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// OneShotDelayRenderable +// This renderable delays for a fixed amount after it's creation, then turns on +// a trigger attribute. It is used for the triggering of other renderables a +// fixed time after an object is created. + + class OneShotDelayRenderable: + public VideoRenderable + { + public: + OneShotDelayRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to wait before raising the trigger + Scalar duration_time = 0.0f // How long trigger is up (0.0 == stay up) + ); + + ~OneShotDelayRenderable(); + + Logical + TestInstance() const; + + int* + GetTriggerAttribute() + {return &myTriggerAttribute;} + + void + Execute(); + + protected: + enum + { + WaitingForTriggerTime, + WaitingForTriggerEndTime, + WaitingForEternity + } myState; + Logical + myEndTimeFlag; + Scalar + myTriggerTime, + myTriggerEndTime; + int + myTriggerAttribute; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// SweepRenderable +// When triggered this renderable sweeps it's output attribute from 0.0 to 1.0 +// over a preset time interval. Used for controling morphs. + class SweepRenderable: + public VideoRenderable + { + public: + enum SweepFunction + { + Y_EQUALS_X = 0, + Y_SQR_X + }; + + SweepRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to take to sweep from 0 to 1 + int cycles, // number of times to cycle before stopping + int *trigger, // Starts the sweep generator when it goes 1 + Scalar start_value = 0.0f, // Initial value of sweep + Scalar end_value = 1.0f, // Final value of sweep + SweepFunction sweep_function = Y_EQUALS_X // function applied to sweep + ); + + ~SweepRenderable(); + + Logical + TestInstance() const; + + Scalar* + GetSweepAttribute() + {return &mySweepAttribute;} + + void + Execute(); + + protected: + int + fakeTrigger, + oldMyTrigger, + *myTrigger, + myCycleCount, + myCyclesLeft; + SweepFunction + mySweepFunction; + Scalar + myStartValue, + myEndValue, + mySweepStart, + mySweepTime, + mySweepAttribute; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLEffectRenderable +// This routine handles the creation of a DPL special effect whenever the +// trigger attribute changes. This is an edge triggered renderable and will +// generate an effect on ANY form of state change. The only way to effect the +// size and speed of the effect is by way of the DPL effect tables. + + class DPLEffectRenderable: + public VideoRenderable + { + public: + DPLEffectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + int effect_type, // DPL effect number to trigger + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~DPLEffectRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + int + *myTrigger, + oldMyTrigger, + myEffectType; + dpl_DCS + *myEffectDCS; + Point3D + myEffectOffset; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class PullFogRenderable: + public VideoRenderable + { + public: + PullFogRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical *light_1, + Logical *light_2); // address containing the trigger + ~PullFogRenderable(); + Logical + TestInstance() const; + void + Execute(); + protected: + Logical + *myLight1, + *myLight2, + myOldLight1, + myOldLight2; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLPSFXRenderable +// This routine handles the creation of a DPL special effect whenever the +// trigger attribute changes. This is an edge triggered renderable and will +// generate an effect on ANY form of state change. The only way to effect the +// size and speed of the effect is by way of the DPL effect tables. + + class DPLPSFXRenderable: + public VideoRenderable + { + public: + DPLPSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~DPLPSFXRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_PARTICLESTART_EFFECT_INFO + myPSFXInfo; + int + *myTrigger, + myOldTrigger; + dpl_DCS + *myEffectDCS; + Point3D + myEffectOffset; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLPSFXStateRenderable +// This routine triggers a pfx whenever a state dial transitions to a designated +// state. +// NOTE this currently does NOT trigger if the state dial is in the trigger state +// when this renderable is created. +// + + class DPLPSFXStateRenderable: + public VideoRenderable + { + public: + + DPLPSFXStateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + StateIndicator *effect_trigger, // Trigger effect when this state changes + unsigned my_trigger, // The state to edge trigger on + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~DPLPSFXStateRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_PARTICLESTART_EFFECT_INFO + myPSFXInfo; + unsigned + myTriggerState; + StateIndicator + *myStateDial; + dpl_DCS + *myEffectDCS; + Point3D + myEffectOffset; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLMaterialRenderable +// This renderable creates a DPL Material structure and encapsulates it so +// it will be properly deleted when the object it's part of gets deleted. + class DPLMaterialRenderable: + public VideoRenderable + { + public: + DPLMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red, // Material's ambient component + Scalar ambient_green, + Scalar ambient_blue, + Scalar emissive_red, // Material's emissive component + Scalar emissive_green, + Scalar emissive_blue, + Scalar diffuse_red, // Material's diffuse component + Scalar diffuse_green, + Scalar diffuse_blue, + Scalar specular_red, // Material's specular component + Scalar specular_green, + Scalar specular_blue, + Scalar specular_shininess, + Scalar opacity_red, // Material's opacity + Scalar opacity_green, + Scalar opacity_blue, + dpl_TEXTURE *texture, // Material's texture pointer + Scalar z_dither, // Material's Z dither value + int fog_immune); // Material's Fog Imunity value + + ~DPLMaterialRenderable(); + + dpl_MATERIAL* + GetMaterial() + {return myMaterial;} + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_MATERIAL + *myMaterial; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for MorphMaterialRenderable +// This renderable takes two material specifications and loads up a third +// material with a morph between the first two. + class MorphMaterialRenderable: + public DPLMaterialRenderable + { + public: + MorphMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red_1, // Material's ambient component + Scalar ambient_green_1, + Scalar ambient_blue_1, + Scalar emissive_red_1, // Material's emissive component + Scalar emissive_green_1, + Scalar emissive_blue_1, + Scalar diffuse_red_1, // Material's diffuse component + Scalar diffuse_green_1, + Scalar diffuse_blue_1, + Scalar specular_red_1, // Material's specular component + Scalar specular_green_1, + Scalar specular_blue_1, + Scalar specular_shininess_1, + Scalar opacity_red_1, // Material's opacity + Scalar opacity_green_1, + Scalar opacity_blue_1, + dpl_TEXTURE *texture_1, // Material's texture pointer + Scalar z_dither_1, // Material's Z dither value + int fog_immune_1, // Material's Fog Imunity value + Scalar ambient_red_2, // Material's ambient component + Scalar ambient_green_2, + Scalar ambient_blue_2, + Scalar emissive_red_2, // Material's emissive component + Scalar emissive_green_2, + Scalar emissive_blue_2, + Scalar diffuse_red_2, // Material's diffuse component + Scalar diffuse_green_2, + Scalar diffuse_blue_2, + Scalar specular_red_2, // Material's specular component + Scalar specular_green_2, + Scalar specular_blue_2, + Scalar specular_shininess_2, + Scalar opacity_red_2, // Material's opacity + Scalar opacity_green_2, + Scalar opacity_blue_2, + Scalar z_dither_2, // Material's Z dither value + Scalar *morph_control); + + ~MorphMaterialRenderable(); + + dpl_MATERIAL* + GetMaterial() + {return myMaterial;} + + Logical + TestInstance() const; + + void + Execute(); + + protected: + int + myFogImmune1; + dpl_TEXTURE + *myTexture1; + + Scalar + myAmbientRed1, + myAmbientGreen1, + myAmbientBlue1, + myEmissiveRed1, + myEmissiveGreen1, + myEmissiveBlue1, + myDiffuseRed1, + myDiffuseGreen1, + myDiffuseBlue1, + mySpecularRed1, + mySpecularGreen1, + mySpecularBlue1, + mySpecularShininess1, + myOpacityRed1, + myOpacityGreen1, + myOpacityBlue1, + myZDither1, + myAmbientRed2, + myAmbientGreen2, + myAmbientBlue2, + myEmissiveRed2, + myEmissiveGreen2, + myEmissiveBlue2, + myDiffuseRed2, + myDiffuseGreen2, + myDiffuseBlue2, + mySpecularRed2, + mySpecularGreen2, + mySpecularBlue2, + mySpecularShininess2, + myOpacityRed2, + myOpacityGreen2, + myOpacityBlue2, + myZDither2, + *myMorphControl, + oldMorphControl, + myAmbientRed, + myAmbientGreen, + myAmbientBlue, + myEmissiveRed, + myEmissiveGreen, + myEmissiveBlue, + myDiffuseRed, + myDiffuseGreen, + myDiffuseBlue, + mySpecularRed, + mySpecularGreen, + mySpecularBlue, + mySpecularShininess, + myOpacityRed, + myOpacityGreen, + myOpacityBlue, + myZDither; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLDamageMaterialRenderable +// This renderable handles modifying a material in response to damage. We +// get the pointer to an existing DPL material on startup and we get out +// color and texture settings from that + class DPLDamageMaterialRenderable: + public VideoRenderable + { + public: + DPLDamageMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_MATERIAL *damage_material, // The material we want to control + Scalar *damage_attribute, // The attribute containing the current damage level + Scalar damage_percent); // Degradation factor to make damaged material + + ~DPLDamageMaterialRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_MATERIAL + *myMaterial; + Scalar + *myDamageAttribute, + oldDamageAttribute, + myAmbientRed1, + myAmbientGreen1, + myAmbientBlue1, + myEmissiveRed1, + myEmissiveGreen1, + myEmissiveBlue1, + myDiffuseRed1, + myDiffuseGreen1, + myDiffuseBlue1, + mySpecularRed1, + mySpecularGreen1, + mySpecularBlue1, + mySpecularShininess1, + myOpacityRed1, + myOpacityGreen1, + myOpacityBlue1, + myAmbientRed2, + myAmbientGreen2, + myAmbientBlue2, + myEmissiveRed2, + myEmissiveGreen2, + myEmissiveBlue2, + myDiffuseRed2, + myDiffuseGreen2, + myDiffuseBlue2, + mySpecularRed2, + mySpecularGreen2, + mySpecularBlue2, + mySpecularShininess2, + myOpacityRed2, + myOpacityGreen2, + myOpacityBlue2, + myAmbientRed, + myAmbientGreen, + myAmbientBlue, + myEmissiveRed, + myEmissiveGreen, + myEmissiveBlue, + myDiffuseRed, + myDiffuseGreen, + myDiffuseBlue, + mySpecularRed, + mySpecularGreen, + mySpecularBlue, + mySpecularShininess, + myOpacityRed, + myOpacityGreen, + myOpacityBlue; + }; +// From here to the row of ### is pretty kludgy stuff to allow dave to prototype +// some explosion stuff. +// I expect to replace most of it within a week with the all-new micro +// renderable system. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// InstanceSwitchRenderable + class InstanceSwitchRenderable: + public VideoRenderable + { + public: + InstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // instance on when trigger is.... + int *trigger); // true if the instance is on, false if off + + ~InstanceSwitchRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Logical + mySense; + dpl_INSTANCE + *myInstance; + int + *myTriggerAttribute, + oldTriggerAttribute; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// StateInstanceSwitchRenderable + class StateInstanceSwitchRenderable: + public VideoRenderable + { + public: + StateInstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // true to turn on in this state, false for off + StateIndicator *state_dial, // State dial we use to control the on/off + unsigned trigger_state); // State that we look for + + ~StateInstanceSwitchRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Logical + myLastInstanceState, + mySense; + dpl_INSTANCE + *myInstance; + unsigned + myTriggerState; + StateIndicator + *myStateDial; + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// MakeDCSFall + class MakeDCSFall: + public VideoRenderable + { + public: + MakeDCSFall( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_DCS *this_DCS, // the DCS to control + Scalar gravity, // Gravity in meters/sec squared + int *trigger); // true if the instance is on, false if off + + ~MakeDCSFall(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_DCS + *myDCS; + int + *myTrigger, + fakeTrigger, + oldMyTrigger; + Point3D + myDisplacement; + Scalar + myFallStart, + myHalfAcceleration; + }; + + +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~End of the new renderable class hiearchy~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~Dynamic Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + //########################################################################## + class DPLEyeRenderable: // this renderable handles a dynamic eyepoint + public Component + { + public: + DPLEyeRenderable( + Entity* This_Entity, + dpl_ZONE* This_Zone, + const LinearMatrix& Offset_Matrix, + dpl_DCS* Parent_DCS, + dpl_VIEW* This_View, + EulerAngles* eyepoint_rotation + ); + ~DPLEyeRenderable(); + + dpl_DCS* + GetDCS() + {return myDCS;} + + Logical + TestInstance() const; + + protected: + + void + Execute(); + + dpl_DCS + *myDCS, + *myParentDCS; + + LinearMatrix + myOrientationMatrix; + + EulerAngles + *myEyepointRotation, + oldEyepointRotation; + + Entity + *myEntity; + }; + + //########################################################################## + class DPLChildPointRenderable: // this is a child DCS carrying an instance + public Component + { + public: + DPLChildPointRenderable( + Entity *This_Entity, + dpl_ZONE *This_Zone, + dpl_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + dpl_DCS *Parent_DCS, + Point3D *my_point + ); + ~DPLChildPointRenderable(); + + dpl_DCS* + GetDCS() + {return myDCS;} + + Logical + TestInstance() const; + + protected: + + void + Execute(); + + dpl_DCS + *myOffsetDCS, + *myDCS, + *myParentDCS; + + dpl_INSTANCE + *myInstance; + + LinearMatrix + OrientationMatrix; + + Entity + *myEntity; + Point3D + *myPoint, + OldPoint; + }; + //########################################################################## + class DPLScaleRenderable: // This is a DCS that responds to scaling + public Component + { + public: + DPLScaleRenderable( + Entity *This_Entity, + dpl_ZONE *This_Zone, + dpl_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + dpl_DCS *Parent_DCS, + Vector3D *my_scale_vector, + Logical *visible + ); + ~DPLScaleRenderable(); + +// dpl_DCS* // we don't allow this (yet) because it prevents +// GetDCS() // people from hooking up children to this renderable +// {return myDCS;} + + Logical + TestInstance() const; + + protected: + + void + Execute(); + Logical + *myVisible, + OldVisible; + dpl_DCS + *myDCS, + *myParentDCS; + + dpl_INSTANCE + *myInstance; + + AffineMatrix + OffsetMatrix; + + Entity + *myEntity; + + Vector3D + *myScaleVector, + OldScaleVector; + }; + //########################################################################## + class DPLScaleQuatRenderable: // This is a DCS that responds to scaling and quaterninons + public Component + { + public: + DPLScaleQuatRenderable( + Entity *This_Entity, + dpl_ZONE *This_Zone, + dpl_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + dpl_DCS *Parent_DCS, + Quaternion *rotation_quaternion, + Vector3D *my_scale_vector, + Logical *visible + ); + ~DPLScaleQuatRenderable(); + +// dpl_DCS* // we don't allow this (yet) because it prevents +// GetDCS() // people from hooking up children to this renderable +// {return myDCS;} + + Logical + TestInstance() const; + + protected: + + void + Execute(); + + Logical + *myVisible, + OldVisible; + + dpl_DCS + *myDCS, + *myParentDCS; + + dpl_INSTANCE + *myInstance; + + AffineMatrix + OffsetMatrix; + + Entity + *myEntity; + + Quaternion + *myRotationQuaternion, + OldRotationQuaternion; + + Vector3D + *myScaleVector, + OldScaleVector; + }; +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~Static Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~these renderables remain constant after construction~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + //########################################################################## + class DPLStaticChildRenderable: // this is a child DCS carrying an instance + public Component + { + public: + DPLStaticChildRenderable( + Entity *This_Entity, + dpl_ZONE *This_Zone, + dpl_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + dpl_DCS *Parent_DCS + ); + ~DPLStaticChildRenderable(); + + dpl_DCS* + GetDCS() + {return myDCS;} + + dpl_INSTANCE* + GetInstance() + {return myInstance;} + + Logical + TestInstance() const; + + protected: + + void + Execute(){}; + + dpl_DCS + *myDCS, + *myParentDCS; + + dpl_INSTANCE + *myInstance; + + LinearMatrix + OrientationMatrix; + + Entity + *myEntity; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~Special Effects Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class DPLSFXRenderable: // A renderable that spawns special effects + public Component + { + public: + DPLSFXRenderable( + Entity *This_Entity, // Entity to attach the effect to + dpl_ZONE *This_Zone, // DPL zone everything will be in + const Point3D &Offset_Point, // Point offset from the parent DCS + dpl_DCS *Parent_DCS, // Parent DCS (can be NULL for world) + StateIndicator *Effect_Trigger, // Trigger effect when this attribute changes + int Trigger_State, // Trigger effect when in this state + int Effect_Type, // Type of effect to trigger + Scalar Repeat_Speed // Effect repeat speed. + ); + + ~DPLSFXRenderable(); + + dpl_DCS* + GetDCS() + {return myParentDCS;} + + Logical + TestInstance() const; + + protected: + + void + Execute(); + + int + myEffectType, + myEffectTriggerState, + myEffectTriggerOld; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_DCS + *myParentDCS; + + Point3D + myOffsetPoint; + + Scalar + myRepeatSpeed, + myLastEffect; + + Entity + *myEntity; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class DPLRepeatSFXRenderable: // A renderable that spawns special effects + public Component + { + public: + DPLRepeatSFXRenderable( + Entity *This_Entity, + dpl_ZONE *This_Zone, + const Point3D &Offset_Point, + dpl_DCS *Parent_DCS, // offset is relative to this + int Effect_Type, // type code for the effect + Scalar *Speed + ); + + ~DPLRepeatSFXRenderable(); + + dpl_DCS* + GetDCS() + {return myParentDCS;} + + Logical + TestInstance() const; + + protected: + + void + Execute(); + + Entity + *myEntity; + + dpl_DCS + *myParentDCS; + + Point3D + myOffsetPoint; + + int + myEffectType; + + Scalar + *mySpeed, + myLastSmoke; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class DPLTranslocationRenderable: // A renderable for the UFT translocation efffec + public Component // from the POV of the player + { + public: + DPLTranslocationRenderable( + Entity *This_Entity, // Entity to attach the effect to + dpl_ZONE *This_Zone, // DPL zone everything will be in + StateIndicator *Effect_Trigger, // Trigger effects off of this state dial + Point3D *Drop_Zone_Location, // Attribute that holds where the new drop will be + unsigned Drop_Zone_State + ); + + ~DPLTranslocationRenderable(); + +// dpl_DCS* +// GetDCS() +// {return myParentDCS;} + + Logical + TestInstance() const; + + protected: + enum TranslocateState + { + IdleState, + InitialExpandState, + HoldAtSizeState, + ColapseState + }; + + TranslocateState + myState; + + void + Execute(); + + int + myDropZoneState, + myEffectType, + myEffectTriggerOld; + + Scalar + myEffectTimer; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_INSTANCE + *myInstance; + + dpl_DCS + *myDCS; + + dpl_ZONE + *myZone; + + Entity + *myEntity; + + Point3D + *myDropZoneLocation; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This is brand new stuff as of 5/12/96 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DependantRenderable +// This is a class of renderable that has other dependant renderables which it +// will execute on command. This is a base for this type of renderable and is +// not ment to be used by itself. +// + class DependantRenderable: + public VideoRenderable + { + public: + DependantRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type // How/when to execute the renderable + ); + + ~DependantRenderable(); + + void + AddDependantRenderable(Component *dependant); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + SChainOf + dependantRenderableSocket; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ScalarTriggerRenderable +// This renderable will run all it's dependants whenever a scalar value that +// it's watching changes. +// + class ScalarTriggerRenderable: + public DependantRenderable + { + public: + ScalarTriggerRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar *watched_value, // we run dependants when this changes + Scalar watched_precision // watched_value must change by this much + ); + + ~ScalarTriggerRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Scalar + *myWatchedValue, // Pointer to the Scalar we're watching + myOldWatchedValue, // The last value of that scalar we saw + myPrecision; // Change must be at least this big to register + + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TimeCullRenderable +// This renderable will run all it's dependants at a set frequency based on +// a clock value supplied by the culling system. +// + class TimeCullRenderable: + public DependantRenderable + { + public: + TimeCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_between_runs // Time delay between executions of dependants + ); + + ~TimeCullRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Scalar + nextRunTime, + delayBetweenRuns; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// MechCullRenderable +// + class MechCullRenderable: + public DependantRenderable + { + public: + MechCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical always_run_all, // If true, disable culling and run everything + dpl_ZONE *my_zone // Switch off this zone when the mech goes off screen + ); + + ~MechCullRenderable(); + + Logical + TestInstance() const; + void + AddDependantLegRenderable(Component *dependant); + void + Execute(); + + protected: + Logical + myMechWasVisible, + myAlwaysRunAll; + dpl_ZONE + *myZone; + Scalar + myNextRootUpdate, + myRootUpdateRate, + myNextLegUpdate, + myLegUpdateRate; + SChainOf + legRenderableSocket; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for OnePSFXRenderable +// This renderable triggers off a single PSFX effect and then hangs around and +// kills the effect when the renderable goes away. This is useful for things +// like missiles which you want to leave a smoke trail that stops if the object +// is destroyed. You REALLY want to do this whenever you attach an effect to +// a DCS since if the DCS goes away the DPL renderer will go wackey. +// + + class OnePSFXRenderable: + public VideoRenderable + { + public: + OnePSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~OnePSFXRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_PARTICLESTART_EFFECT_INFO + myPSFXInfo; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for TranslocationRenderable +// This renderable does the UFT translocation effect from the perspective of +// someone else watching the person translocating. We connect this to the +// player object and uses information from that object to position itself. +// + class TranslocationRenderable: + public VideoRenderable + { + public: + TranslocationRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_ZONE *this_zone, // DPL zone everything will be in + StateIndicator *effect_trigger, // Trigger effects off of this state dial + Point3D *drop_zone_location, // Attribute that holds where the new drop will be + unsigned drop_zone_state // State that indicates drop zone is valid (starts effect) + ); + + ~TranslocationRenderable(); + + Logical + TestInstance() const; + + protected: + enum TranslocateState + { + IdleState, + InitialExpandState, + HoldAtSizeState, + ColapseState + }; + + TranslocateState + myState; + + void + Execute(); + + int + myDropZoneState, + myEffectType; + + Scalar + myEffectTimer; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_INSTANCE + *myInstance; + + dpl_DCS + *myDCS; + + dpl_ZONE + *myZone; + + Point3D + *myDropZoneLocation; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// SpinScaleQuatWatcherRenderable This is used to create a laser style effect +// that has a directional control, scale and an axial spin at a pre-set speed +// (used for PPC's) +// + class SpinScaleQuatWatcherRenderable: + public ChildOffsetRenderable + { + public: + SpinScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Scalar z_spin_rate); // spins the object about z (radians/frame) + + ~SpinScaleQuatWatcherRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + StateIndicator + *myControl; + unsigned + myTriggerState; + Quaternion + *myRotationQuaternion; + Vector3D + *myScaleVector; + Logical + myVisible; + Scalar + myZSpinRate, + OldZSpin; + }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ScaleQuatWatcherRenderable This is used to create a laser style effect +// that has a directional control and scaling +// + class ScaleQuatWatcherRenderable: + public ChildOffsetRenderable + { + public: + ScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector); // Scales the object + + ~ScaleQuatWatcherRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + StateIndicator + *myControl; + unsigned + myTriggerState; + Quaternion + *myRotationQuaternion; + Vector3D + *myScaleVector; + Logical + myVisible; + }; + + +#endif diff --git a/CODE/RP/MUNGA_L4/L4VIDTUL.CPP b/CODE/RP/MUNGA_L4/L4VIDTUL.CPP new file mode 100644 index 0000000..edd5607 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4VIDTUL.CPP @@ -0,0 +1,43 @@ +//===========================================================================// +// File: l4video.cpp // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Interface specification Video Renderer Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/11/95 GAC Initial coding. // +// 07/11/95 KEO Modify video resource format. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4VIDEO_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +ResourceDescription::ResourceID + L4Tool::CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + return + DPLRenderer::CreateModelVideoStreamResource( + resource_file, + model_name, + model_file, + directories + ); +} + diff --git a/CODE/RP/MUNGA_L4/L4WRHOUS.CPP b/CODE/RP/MUNGA_L4/L4WRHOUS.CPP new file mode 100644 index 0000000..7f283a3 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4WRHOUS.CPP @@ -0,0 +1,63 @@ +//===========================================================================// +// File: wrhous.cc // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +// This object manages creation and deletion of dynamically-created objects // +// of which only on instantiation should exist. It is currently used // +// only by the gauge renderer. // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/01/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include + +#if !defined(L4WRHOUS_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//####################################################################### +// Warehouse +//####################################################################### +L4Warehouse::L4Warehouse() : + Warehouse() +{ + Check_Pointer(this); + Check_Fpu(); +} + +L4Warehouse::~L4Warehouse() +{ + Check(this); + Check_Fpu(); +} + +void + L4Warehouse::Purge() +{ + Check(this); + + gaugeImageBin.Purge(); + Warehouse::Purge(); + + Check_Fpu(); +} + +Logical + L4Warehouse::TestInstance() const +{ + return Warehouse::TestInstance(); +} + diff --git a/CODE/RP/MUNGA_L4/L4WRHOUS.HPP b/CODE/RP/MUNGA_L4/L4WRHOUS.HPP new file mode 100644 index 0000000..15905d3 --- /dev/null +++ b/CODE/RP/MUNGA_L4/L4WRHOUS.HPP @@ -0,0 +1,42 @@ +//===========================================================================// +// File: wrhous.hh // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 08/01/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(L4WRHOUS_HPP) +# define L4WRHOUS_HPP + +# if !defined(WRHOUS_HPP) +# include "wrhous.hpp" +# endif + +# if !defined(L4GAUIMA_HPP) +# include "l4gauima.hpp" +# endif + + //####################################################################### + // L4Warehouse + //####################################################################### + class L4Warehouse : + public Warehouse + { + public: + L4Warehouse(); + ~L4Warehouse(); + Logical + TestInstance() const; + void + Purge(); + + WarehouseBinOf + gaugeImageBin; + }; +#endif diff --git a/CODE/RP/MUNGA_L4/MUNGAL4.HPP b/CODE/RP/MUNGA_L4/MUNGAL4.HPP new file mode 100644 index 0000000..0a00c84 --- /dev/null +++ b/CODE/RP/MUNGA_L4/MUNGAL4.HPP @@ -0,0 +1,28 @@ +#if !defined(MUNGAL4_HPP) +# define MUNGAL4_HPP + +# if !defined(MUNGA_HPP) +# include +# endif + +# define __DPMI32__ +# include + +# if !defined(NO_PRECOMPILED_HEADERS) + +# if !defined(GRAPH2D_HPP) +# include +# endif + +# if !defined(L4HOST_HPP) +# include +# endif + +# if !defined(L4APP_HPP) +# include +# endif + +# endif + +#endif + diff --git a/CODE/RP/MUNGA_L4/NETSHARE.ASM b/CODE/RP/MUNGA_L4/NETSHARE.ASM new file mode 100644 index 0000000..138c308 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NETSHARE.ASM @@ -0,0 +1,138 @@ +;=========================================================================== +; Data segment +;=========================================================================== +.386p +.MODEL flat + +_DATA SEGMENT DWORD USE32 + Selector dw 0000 ;got from _mapRMBuff + +; EXTRN C Shared_Memory_Buffer :DATAPTR + EXTRN C Function_Ptr :DATAPTR + EXTRN C Buffer_Length_Ptr :DATAPTR + EXTRN C Net_Common_Ptr :DATAPTR + + EXTRN C baseadr:WORD ;real mode segment of structure + EXTRN C offs:WORD ;real mode offset of structure + +; EXTRN C RMShared_Memory_Buffer_Off :WORD + EXTRN C RMBuffer_Length_Off :WORD + EXTRN C RMFunction_Off :WORD + + +_DATA ENDS + +;=========================================================================== +; Code segment +;=========================================================================== +_TEXT SEGMENT DWORD USE32 + +;########################################################################### +_mapRMBuff PROC CPP NEAR USES EAX EBX ECX EDX es +PUBLIC _mapRMBuff + +;-------------------------------------------------------------------------- +; Map descriptor (i.e selector) to real mode memory +;-------------------------------------------------------------------------- + mov ax, 0002h + mov bx, baseadr + INT 31h + mov Selector, ax +;-------------------------------------------------------------------------- +; Examine everything +;-------------------------------------------------------------------------- +;Check base address in cx:edx +; mov ax, 0006h +; mov bx, Selector +; INT 31h + +;Check segment limit in ax +; lsl ax, Selector + +;Examine Access Rights in ax +; lar ax, Selector + + + ret +ENDP _mapRMBuff + + +;########################################################################### +_getRMBuff PROC CPP NEAR USES EAX EBX ECX EDX edi esi es +PUBLIC _getRMBuff + + +;get counter for Block copy from real mode address + mov es, Selector + mov di, RMBuffer_Length_Off + xor ecx, ecx + mov cx, WORD PTR es:[di] + add cx, 6 ;include Function,Status,Buffer_Length to Block + +;get Block address + mov di, RMFunction_Off ;real mode Block + mov esi, Function_Ptr ;protected mode Block +CopyBlock: + xor eax, eax + mov al, es:[di] ;BYTE PTR es:[edi] + mov BYTE PTR [esi], al ;copy to protected mode + inc di + inc esi + loopnz CopyBlock + + + ret +ENDP _getRMBuff + +;########################################################################### +_setRMBuff PROC CPP NEAR USES EAX EBX ECX EDX edi esi es +PUBLIC _setRMBuff + +;Copy from protected mode address + mov es, Selector + mov di, RMFunction_Off + mov esi, Function_Ptr + xor ecx, ecx + mov ebx, [Buffer_Length_Ptr];counter + mov cx, [ebx] + add cx, 6 ;include Function,Status,Buffer_Length to Block +CopyBlk: + xor eax, eax + mov al, [esi] + mov es:[di], eax ;copy to real mode + inc di + inc esi + loopnz CopyBlk + + + ret +ENDP _setRMBuff + +;########################################################################### +_getRMNumbers PROC CPP NEAR USES EAX EBX ECX EDX edi esi es +PUBLIC _getRMNumbers + +;Copy from protected mode address + mov es, Selector +;get counter for Block copy from real mode address + xor ecx, ecx + mov cx, 6 ;sizeof long Version_Number and short Interrupt_Number + +;get Block address + mov di, offs ;real mode Block + mov esi, Net_Common_Ptr ;protected mode Block +CopyBl: + xor eax, eax + mov al, es:[di] + mov BYTE PTR [esi], al ;copy to protected mode + inc di + inc esi + loopnz CopyBl + + + ret +ENDP _getRMNumbers + +_TEXT ENDS +END + diff --git a/CODE/RP/MUNGA_L4/NetNub/ANALYSIS.CPP b/CODE/RP/MUNGA_L4/NetNub/ANALYSIS.CPP new file mode 100644 index 0000000..760e0e7 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/ANALYSIS.CPP @@ -0,0 +1,239 @@ +//===========================================================================// +// File: analysis.cpp // +// Project: MUNGA Brick: none // +// Contents: Utilities for using logic analyzer with parallel port dongle // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/19/94 WGR Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(PROFILE_HPP) +# include "analysis.hpp" +#endif + +#if defined(USE_PROFILE_ANALYSIS) +# if defined(USE_TIME_ANALYSIS) +# error NETNUB may not use time analysis! +# endif + +# include +# include + +// +// these macros must be undefined for Borland to access the inp & outportb functions +// +# undef inportb +# undef outportb + +# define TRACE_COUNT 12 + +# if defined(USE_PROFILE_ANALYSIS) + + // + // table of data representing bits on the parallel port at 0x378 (usually LPT1) + // DO NOT ALTER THIS DATA - IT REQUIRES LOTS OF SCHEMATIC TRACING TO DUPLICATE + // + const struct parallelbit + { + unsigned int port; + unsigned char mask; + int sense; + } + bitTable[12] = + { + {0x378, 0x80, 0x00}, + {0x378, 0x40, 0x00}, + {0x378, 0x20, 0x00}, + {0x378, 0x10, 0x00}, + {0x37a, 0x08, 0x01}, + {0x37a, 0x04, 0x00}, + {0x37a, 0x02, 0x01}, + {0x37a, 0x01, 0x01}, + {0x378, 0x08, 0x00}, + {0x378, 0x04, 0x00}, + {0x378, 0x02, 0x00}, + {0x378, 0x01, 0x00} + }; + + // + //############################################################################# + //############################################################################# + // + void + Analysis_Status() + { + int i; + printf("Active traces:"); + for (i=0; i<12; ++i) + { + if (Read_Analysis(i)) + { + printf(" %i", i); + } + } + printf("\n"); + } + + // + //############################################################################# + // Set one of the 12 outputable bits of the parallel port at 0x378 (usually + // LPT1), taking into account the hardware sense of the bit + //############################################################################# + // + void + Set_Analysis(int bit) + { + // + //------------------------------------------------------------------ + // read the current value of the appropriate port + //------------------------------------------------------------------ + // + int port_value; + port_value = inportb(bitTable[bit].port); + + // + //------------------------------------------------------------------ + // set the appropriate bit, taking into account the hardware sense + //------------------------------------------------------------------ + // + if (bitTable[bit].sense == 0) + { + port_value |= bitTable[bit].mask; + } + else + { + port_value &= ~(bitTable[bit].mask); + } + + // + //------------------------------------------------------------------ + // put the modified value into the appropriate port + //------------------------------------------------------------------ + // + outportb(bitTable[bit].port,(unsigned char)port_value); + } + + // + //############################################################################# + // Clear one of the 12 outputable bits of the parallel port at 0x378 (usually + // LPT1, taking into account the hardware sense of the bit. + //############################################################################# + // + void + Clear_Analysis(int bit) + { + // + //------------------------------------------------------------------ + // read the current value of the appropriate port + //------------------------------------------------------------------ + // + int port_value; + port_value = inportb(bitTable[bit].port); + + // + //------------------------------------------------------------------ + // clear the appropriate bit, taking into account the hardware sense + //------------------------------------------------------------------ + // + if (bitTable[bit].sense == 0) + { + port_value &= ~(bitTable[bit].mask); + } + else + { + port_value |= bitTable[bit].mask; + } + + // + //------------------------------------------------------------------ + // put the modified value into the appropriate port + //------------------------------------------------------------------ + // + outportb(bitTable[bit].port,(unsigned char)port_value); + } + + // + //############################################################################# + // Toggle one of the 12 outputable bits of the parallel port at 0x378 (usually + // LPT1, taking into account the hardware sense of the bit. + //############################################################################# + // + int + Read_Analysis(int bit) + { + // + //------------------------------------------------------------------ + // read the current value of the appropriate port + //------------------------------------------------------------------ + // + int port_value; + port_value = inportb(bitTable[bit].port); + + // + //--------------------------- + // Read the bit appropriately + //--------------------------- + // + port_value &= bitTable[bit].mask; + if (bitTable[bit].sense) + { + port_value ^= bitTable[bit].mask; + } + + // + //------------------------------------------------------------------ + // return the bit's state + //------------------------------------------------------------------ + // + return port_value != 0; + } + + // + //############################################################################# + // Clear all of the 12 outputable bits of the parallel port at 0x378. + //############################################################################# + // + void + Reset_Analysis(void) + { + // + //------------------------------------------------------------------ + // clear all 12 outputable bits of the parallel port + // at 0x378 (usually LPT1) + //------------------------------------------------------------------ + // + int i; + for (i = 0; i < 12; i++) + { + Clear_Analysis(i); + } + } + + // + //############################################################################# + // Test all of the 12 outputable bits of the parallel port at 0x378. + //############################################################################# + // + void + Test_Analysis(void) + { + // + //------------------------------------------------------------------ + // toggle (twice) all 12 outputable bits of the parallel port + // at 0x378 (usually LPT1) + //------------------------------------------------------------------ + // + int i; + for (i = 0; i < 12; i++) Clear_Analysis(i); + for (i = 0; i < 12; i++) Set_Analysis(i); + for (i = 0; i < 12; i++) Clear_Analysis(i); + } + +# endif + +#endif + diff --git a/CODE/RP/MUNGA_L4/NetNub/ANALYSIS.HPP b/CODE/RP/MUNGA_L4/NetNub/ANALYSIS.HPP new file mode 100644 index 0000000..fa4d71f --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/ANALYSIS.HPP @@ -0,0 +1,58 @@ +#if !defined(ANALYSIS_HPP) +# define ANALYSIS_HPP + + // + //############################################################################# + // Set one of the 12 outputable bits of the parallel port at 0x378 (usually + // LPT1), taking into account the hardware sense of the bit + //############################################################################# + // + void + Set_Analysis(int bit); + + // + //############################################################################# + // Clear one of the 12 outputable bits of the parallel port at 0x378 (usually + // LPT1, taking into account the hardware sense of the bit. + //############################################################################# + // + void + Clear_Analysis(int bit); + + // + //############################################################################# + // Read the state of one of the 12 outputable bits of the parallel port at + // 0x378 (usually LPT1, taking into account the hardware sense of the bit. + //############################################################################# + // + int + Read_Analysis(int bit); + + // + //############################################################################# + // Clear all of the 12 outputable bits of the parallel port at 0x378. + //############################################################################# + // + + void + Reset_Analysis(void); + + // + //############################################################################# + // Test all of the 12 outputable bits of the parallel port at 0x378. + //############################################################################# + // + void + Test_Analysis(void); + + // + //############################################################################# + // Print the bit numbers of any active bit of the 12 outputable bits of the + // parallel port at 0x378 + //############################################################################# + // + void + Analysis_Status(void); + +#endif + diff --git a/CODE/RP/MUNGA_L4/NetNub/NETNUB.HPP b/CODE/RP/MUNGA_L4/NetNub/NETNUB.HPP new file mode 100644 index 0000000..23a3fc8 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/NETNUB.HPP @@ -0,0 +1,387 @@ +//===========================================================================// +// File: netnub.hpp // +// Project: MUNGA real mode network nub // +// Contents: Implementation details for the Affine matrices // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/27/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(NETNUB_HPP) +# define NETNUB_HPP + +// Version number of the netcom common block + +#define NETCOM_VERSION 11 + +// Maximum size of send and receive buffers (one ethernet packet) + +#define MAX_TRANSFER_SIZE 0xFF00U +#define SHARED_MEMORY_SIZE (MAX_TRANSFER_SIZE+4) + +// Function codes (set by protected mode app before calling our interrupt) + +#define NETNUB_UNDEFINED (-1) // Netnub sets this function code after each operation is done +#define NETNUB_STATUS 0 // Lets the netnub run and return status +#define NETNUB_SEND_PACKET 1 // Send the packet in the buffer +#define NETNUB_RECEIVE_PACKET 2 // Return a packet in the buffer +#define NETNUB_TCP_OPEN 3 // Opens a TCP stream to another computer +#define NETNUB_TCP_LISTEN 4 // Queue's a TCP listen that we can accept a connection on +#define NETNUB_TCP_CLOSE 5 // Closes a TCP stream +#define NETNUB_RESOLVE_ADDRESS 6 // Resolves a text IP address into a 32 bit number +#define NETNUB_CHECK_SOCKET 7 // Checks a socket to see if anyone has connected yet +#define NETNUB_UDP_OPEN 8 // Opens a UDP socket +#define NETNUB_UDP_READ 9 // Returns a UDP record +#define NETNUB_UDP_SEND 10 // Returns a UDP record +#define NETNUB_MARKER_TEXT 11 // Writes the text supplied to standard out +#define NETNUB_OPEN_FILE 12 +#define NETNUB_WRITE_FILE 13 +#define NETNUB_CLOSE_FILE 14 +#define NETNUB_MULTIPLE_SEND 15 // The has a request to send to multiple streams +#define NETNUB_MULTIPLE_RECEIVE 16 // Request to receive from several streams at once +#define NETNUB_SET_SWITCHES 17 // Set the netnub runtime switches +#define NETNUB_READ_FILE 18 +#define NETNUB_SEEK_FILE 19 +#define NETNUB_TCP_TICK 20 + +// Status returns from the netnub + +#define NETNUB_PARTIAL_TRANSMIT (-5) // Some part of a packet was not sent (very fatal) +#define NETNUB_DATA_DUMPED (-4) // Data was dumped on the floor to avoid blocking +#define NETNUB_STREAM_DISCONNECTED (-3) // Stream has been disconnected at the remote end +#define NETNUB_RESOLVE_ERROR (-2) // Unable to resolve an internet address +#define NETNUB_ERROR (-1) // Unspecified error (something broke) +#define NETNUB_OK 0 // No error (everything ok) +#define NETNUB_RECEIVED_PACKET 1 // A packet has been received and is in the buffer +#define NETNUB_TCP_CONNECTED 2 // Notifys us that someone connected to the socket + +// Netcom shared memory structure, used to pass commands and packets between the +// real and protected mode part of the application. This structure should be +// allocated in the real mode application. +// +// IMPORTANT: The Version Number field must stay in the same place and should be +// checked by the protected mode app to make sure it was spawned by a real mode +// server with a matching Version Number. This prevents the real and protected +// mode applications from accidentally getting out of sync. +// +// NOTE: More data will eventually be added, but it will be at the END of the +// structure so as not to mess up any machine code. + +struct Netcom + { + long + Version_Number; // Version number of real mode netnub + short + Interrupt_Number, // Interrupt number to use for communcations + Function, // * Function code (from protected mode app) + Status; // * Current status of the netnub + unsigned short + Buffer_Length; // * Length of data in shared memory buffer + char + Shared_Memory_Buffer[SHARED_MEMORY_SIZE]; // * Data to send (from protected mode app) + }; + +// NOTE: Fields marked with a * should be copied from real to protected mode, +// the interrupt called, then on return they should be copied back. It is never +// necessary to copy more than "Buffer_Length" bytes of the Shared_Memory_Buffer. +// +// Typedef for a pointer to the netcom structure + +typedef Netcom *Netcom_Ptr; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Description of operations +// +// Regardless of what function is being sent, the machine code procedure +// should always copy to real mode all the fields marked with a * before +// calling the interrupt. On return from the interrupt all these fields should +// be copied back from real to protected mode. It is never necessary to copy +// more than "Buffer_Length" bytes of the Shared_Memory_Buffer. If "Buffer_Length" +// is zero, the copy of shared memory should be skipped. +// +// For each function code there can be two structures. One will be the format +// of data in the Shared_Memory_Buffer for a "request" and the other for a reply +// to that request. Either may be omitted if not necessary. When Shared_Memory_Buffer +// is received by either the protected mode or real mode part of the application +// it will be "cast" into the proper structure based on the function code. +// Note that some of these structures have only one data entry in them, they were +// made structures to allow for future expansion. +// +// After processing each function the real mode netnub will set the Function +// code to NETNUB_UNDEFINED so it can detect if the protected mode program +// has forgotten to set the function code for any reason. +// +// A Function of NETNUB_RECEIVE_PACKET can result in either a packet or a connect +// being returned. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +struct SetSwitchesRequest +{ + int + blocking_switch; // Setting of the blocking/non blocking mode +}; +typedef SetSwitchesRequest *SetSwitchesRequestPtr; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +struct StatusReturn +{ + unsigned long + My_Net_Address; +}; + +typedef StatusReturn *StatusReturnPtr; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Structure in Shared_Memory_Buffer for a receive data packet + +struct ReceivePacketRequest + { + unsigned long + Socket_Ptr; // Socket pointer, see note above + }; + +typedef ReceivePacketRequest *ReceivePacketRequestPtr; + +#define MAX_RECEIVE_DATA_SIZE 1600 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#define MULTIPLE_RECEIVE_PACKET_MAX 10 + +struct MultipleReceivePacketRequest + { + unsigned long // It's a long to insure structure alignment is predictable + Socket_Count; // Number of sockets in the list below + unsigned long + Socket_Ptrs[MULTIPLE_RECEIVE_PACKET_MAX]; // Contains socket pointers + }; + +typedef MultipleReceivePacketRequest *MultipleReceivePacketRequestPtr; + +struct MultipleReceivePacketReturn + { + unsigned long // It's a long to insure structure alignment is predictable + Socket_Count; // Number of sockets in the list below + unsigned long // long so it matches the format of MultipleSendPacketRequest + Status[MULTIPLE_RECEIVE_PACKET_MAX]; // length or error code for this socket + char + Received_Data[4]; + }; +typedef MultipleReceivePacketReturn *MultipleReceivePacketReturnPtr; + +#define MULTIPLE_RECEIVE_BUFFER_SIZE(data_size) (data_size + sizeof(MultipleReceivePacketReturn)-4) +#define MULTIPLE_RECEIVE_DATA_SIZE(buffer_size) (buffer_size - sizeof(MultipleReceivePacketReturn)+4) + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +struct SendPacketRequest + { + unsigned long + Socket_Ptr; // Socket pointer, see note above + char + Send_Data[4]; // !!! set to 4 to insure word alignment + }; + +#define SEND_BUFFER_SIZE(data_size) ((data_size) + sizeof(SendPacketRequest) - 4) +#define SEND_DATA_SIZE(buffer_size) ((buffer_size) - sizeof(SendPacketRequest) + 4) +#define MAX_SEND_DATA_SIZE (1604 - sizeof(SendPacketRequest)) + +struct SendPacketReturn + { + unsigned long + Send_Buffer_Used; // Number of bytes in the send buffer + }; + +typedef SendPacketReturn *SendPacketReturnPtr; +typedef SendPacketRequest *SendPacketRequestPtr; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This command sends the same data to multiple destinations +// +#define MULTIPLE_SEND_PACKET_MAX 10 + +struct MultipleSendPacketRequest + { + unsigned long // It's a long to insure structure alignment is predictable + Socket_Count; // Number of sockets to send to + unsigned long + Socket_Ptrs[MULTIPLE_SEND_PACKET_MAX]; // Contains socket pointers + char + Send_Data[4]; // !!! set to 4 to insure word alignment + }; + +struct MultipleSendPacketReturn + { + unsigned long // It's a long to insure structure alignment is predictable + Socket_Count; // Number of sockets to send to + unsigned long // long so it matches the format of MultipleSendPacketRequest + Errors[MULTIPLE_SEND_PACKET_MAX]; // Contains socket pointers + unsigned long + Send_Buffer_Used[MULTIPLE_SEND_PACKET_MAX]; // Number of bytes in the send buffer + }; + +#define MULTIPLE_SEND_BUFFER_SIZE(data_size) (data_size + sizeof(MultipleSendPacketRequest) - 4) +#define MULTIPLE_SEND_DATA_SIZE(buffer_size) (buffer_size - sizeof(MultipleSendPacketRequest) + 4) +#define MAX_MULTIPLE_SEND_DATA_SIZE (MAX_TRANSFER_SIZE - sizeof(MultipleSendPacketRequest) + 4) + +typedef MultipleSendPacketRequest *MultipleSendPacketRequestPtr; +typedef MultipleSendPacketReturn *MultipleSendPacketReturnPtr; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +struct ResolveReturn + { + unsigned long + Internet_Address; // 32 bit internet address (if no error) + }; + +typedef ResolveReturn *ResolveReturnPtr; + +struct TCPOpenRequest + { + short + Local_Port, // Local port number + Remote_Port; // Remote port number + unsigned long + Internet_Address; // Internet address to connect with + unsigned long + Socket_Ptr; // tcp_Socket address (at least 4300 bytes) if 0 netnub will try to allocate one + }; + +struct TCPOpenReturn + { + unsigned long + Socket_Ptr; // pointer to the socket opened or error number + }; + +typedef TCPOpenRequest *TCPOpenRequestPtr; +typedef TCPOpenReturn *TCPOpenReturnPtr; + +struct TCPCloseRequest + { + unsigned long + Socket_Ptr; // pointer to the socket to be closed + }; +typedef TCPCloseRequest *TCPCloseRequestPtr; + +struct TCPCheckSocketRequest + { + unsigned long + Socket_Ptr; // pointer to the socket to be checked + }; + +struct TCPCheckSocketReturn + { + unsigned long + Socket_Net_Address; // Net address of the person who connected + }; + +typedef TCPCheckSocketRequest *TCPCheckSocketRequestPtr; +typedef TCPCheckSocketReturn *TCPCheckSocketReturnPtr; + +struct UDPOpenRequest + { + short + Local_Port, // Local port number + Remote_Port; // Remote port number + unsigned long + Internet_Address; // Internet address to connect with + unsigned long + Socket_Ptr; // UDP_Socket address (at least 2200 bytes) if 0 netnub will try to allocate one + }; + +struct UDPOpenReturn + { + unsigned long + Socket_Ptr; // pointer to the socket opened or error number + }; + +typedef UDPOpenRequest *UDPOpenRequestPtr; +typedef UDPOpenReturn *UDPOpenReturnPtr; + +struct OpenFileRequest + { + char + File_Name[80]; + short + Access; + unsigned short + Model; + }; + +struct OpenFileReturn + { + short + File_Handle; + }; + +typedef OpenFileRequest *OpenFileRequestPtr; +typedef OpenFileReturn *OpenFileReturnPtr; + +struct CloseFileRequest + { + short + File_Handle; + }; + +typedef CloseFileRequest *CloseFileRequestPtr; + +struct WriteFileRequest + { + short + File_Handle; + unsigned short + Write_Length; + char + Write_Data[4]; + }; + +struct WriteFileReturn + { + unsigned short + Bytes_Written; + }; + +typedef WriteFileRequest *WriteFileRequestPtr; +typedef WriteFileReturn *WriteFileReturnPtr; + +struct ReadFileRequest + { + short + File_Handle; + unsigned short + Read_Length; + }; + +struct ReadFileReturn + { + char + Read_Data[4]; + }; + +typedef ReadFileRequest *ReadFileRequestPtr; +typedef ReadFileReturn *ReadFileReturnPtr; + +struct SeekFileRequest + { + short + File_Handle; + short + Seek_Mode; + long + Seek_Offset; + }; + +struct SeekFileReturn + { + long + Seek_Position; + }; + +typedef SeekFileRequest *SeekFileRequestPtr; +typedef SeekFileReturn *SeekFileReturnPtr; + +#endif diff --git a/CODE/RP/MUNGA_L4/NetNub/NOPAUSE.CPP b/CODE/RP/MUNGA_L4/NetNub/NOPAUSE.CPP new file mode 100644 index 0000000..54c325d --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/NOPAUSE.CPP @@ -0,0 +1,72 @@ +/* NOPAUSE.CPP - Disable Pause. + (C) Copyright 1991 + By Thomas Astin CIS: 73407,3427 Prodigy: RNVN08A + All rights reserved. */ + +/* Disable pause by intercepting interrupt 9 and blocking pause scan codes.*/ + +/* NOTE: This program worked fine on the machine upon which it was + developed and tested. Use at your own risk. The author is + not responsible for any damage, system failure, or the like + as a result of executing this code. + + Compiles under Borland C++. Code may require modifications for + use with other compilers. +*/ + + +#include +#include + +/* Protos */ +void interrupt NewInt9(...); +void ExitFunc(void); + +/* exit func in case ^C */ +#pragma exit ExitFunc + +/* Defines */ +#define KbdIn 0x60 +#define KbdCtl 0x61 +#define MaxChkIdx 3 + +/* Globals */ +unsigned char ChkArray[MaxChkIdx] = {0xE1,0x1D,0x45}; +unsigned char ChkIdx=0; +unsigned char CurScan=0; +void interrupt (*OldInt9)(...)=NULL; + +void interrupt NewInt9(...) // int 9 handler +{ + CurScan=inportb(KbdIn); // get scan code + if (CurScan==ChkArray[ChkIdx++]) { // check scan code array + if (ChkIdx>=MaxChkIdx) { // last match? + ChkIdx=0; // get ready for next time + + asm in al,KbdCtl // restore keyboard + asm mov ah,al + asm or al,80h + asm jmp temp1 + temp1: + asm out KbdCtl,al + asm xchg ah,al + asm jmp temp2 + temp2: + asm out KbdCtl,al + asm mov al,20h // Issue EOI + asm out 20h,al + + return; + } + } + else + ChkIdx=0; // start over + + OldInt9(); // call original int 9 +} + +void ExitFunc(void) +{ + if (OldInt9!=NULL) + setvect(9,OldInt9); // restore int 9 +} \ No newline at end of file diff --git a/CODE/RP/MUNGA_L4/NetNub/PROFILE.HPP b/CODE/RP/MUNGA_L4/NetNub/PROFILE.HPP new file mode 100644 index 0000000..f311d3f --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/PROFILE.HPP @@ -0,0 +1,715 @@ +//===========================================================================// +// File: profile .hpp // +// Project: MUNGA Brick: none // +// Contents: Bit definitions for logic analyser profiling of routines // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 06/01/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(PROFILE_HPP) +# define PROFILE_HPP + +# if !defined(CLEAN_BUILD) +# define CLEAN_BUILD 0 +# endif + +# if DEBUG_LEVEL>=3 +# define USE_PROFILE_ANALYSIS // Enables trace activity +//# define USE_TIME_ANALYSIS // Enables trace time statistics +//# define USE_TIME_LOG // Enables logging functions +//# define USE_FPU_ANALYSIS // Enables entity FPU checks +//# define USE_MEMORY_ANALYSIS // Enables heap statistics +# elif DEBUG_LEVEL==2 +# define USE_PROFILE_ANALYSIS // Enables trace activity +//# define USE_TIME_ANALYSIS // Enables trace time statistics +//# define USE_TIME_LOG // Enables logging functions +//# define USE_FPU_ANALYSIS // Enables entity FPU checks +# define USE_MEMORY_ANALYSIS // Enables heap statistics +# elif CLEAN_BUILD==0 +//# define USE_PROFILE_ANALYSIS // Enables trace activity +# define USE_TIME_ANALYSIS // Enables trace time statistics +//# define USE_TIME_LOG // Enables logging functions +# define USE_FPU_ANALYSIS // Enables entity FPU checks +# define USE_MEMORY_ANALYSIS // Enables heap statistics +# endif + +# if !defined(ANALYSIS_HPP) +# include "analysis.hpp" +# endif + + //*******************************************************************// + //*******************************************************************// + // IMPORTANT!!! // + // Remember that trace numbers go from 0 to 11, that's all you get. // + //*******************************************************************// + //*******************************************************************// + + // + // ---Place enabled defines below ---- + // + +# if defined(USE_PROFILE_ANALYSIS) || defined(USE_TIME_ANALYSIS) + #define ANALYSIS_FOREGROUND_PROCESSING 0 + #define TRACE_0 "Foreground Processing" + + #define ANALYSIS_UPDATE_MANAGER 1 + #define TRACE_1 "Update Manager" + + #define ANALYSIS_UPDATE_REPLICANTS 2 + #define TRACE_2 "Update Replicants" + + #define ANALYSIS_SEND_PACKET 3 + #define TRACE_3 "Send Packet" + + #define ANALYSIS_RENDERER_MANAGER 4 + #define TRACE_4 "Renderer Manager" + + #define ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION 5 + #define ANALYSIS_VIDEO_FIRST_FRAME_DONE 5 + #define ANALYSIS_VIDEO_RENDERER_FRAME_DONE 5 + #define ANALYSIS_VIDEO_BECOME_UNINTERESTING 5 + #define TRACE_5 "Video Renderer" + + #define ANALYSIS_VIDEO_BATCH_FLUSH 6 + #define TRACE_6 "Video Batch Flush" + + #define ANALYSIS_AUDIO_RENDERER 7 + #define TRACE_7 "Audio Renderer" + + #define ANALYSIS_GAUGE_RENDERER 8 + #define TRACE_8 "Gauge Renderer" + + #define ANALYSIS_SCREEN_COPY 9 + #define TRACE_9 "Gauge Screen Copy" + + #define ANALYSIS_PROCESS_EVENT 10 + #define TRACE_10 "Process Event" + + #define ANALYSIS_ROUTE_PACKET 11 + #define TRACE_11 "Route Packet" + + // + // Unused definitions + // +/* + #define ANALYSIS_UPDATE_MASTERS 3 + #define ANALYSIS_EXECUTE_ENTITY 4 + #define ANALYSIS_PERFORM_ENTITY 5 + #define ANALYSIS_PERFORM_SUBSYSTEMS 6 + #define ANALYSIS_EXECUTE_WATCHERS 7 + #define ANALYSIS_JOINT_PERFORMANCE 8 + #define ANALYSIS_CHECK_BUFFERS 11 + #define ANALYSIS_CALL_NETNUB 6 + #define ANALYSIS_APP_MGR 11 + #define ANALYSIS_COMPLETE_CYCLES 3 + #define ANALYSIS_DEATH_ROW 4 + #define ANALYSIS_APP_INITIALIZE 7 + #define ANALYSIS_INTEREST_MANAGER 8 + #define ANALYSIS_LOAD_SOUNDBANK 9 + #define ANALYSIS_WAIT_FOR_DROP 9 + + // + // Defines for profiling the video system + // If you want to see all video activity on the same trace, put all the + // defines marked with a * on the same trace and turn the rest off. + // The indenting below shows how the calls are nested, to get sensable output never + // put a call and one of it's nested children on the same trace. + // + #define ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION 9 // * Video renderer execute implimentation running. + #define ANALYSIS_VIDEO_PICKPOINT 9 // Call to the RapidSectPixel or SectPixel + #define ANALYSIS_VIDEO_RENDERERABLES 9 // All calls to video renderable execute methods + #define ANALYSIS_VIDEO_MORPH_SEND 9 // A call to MorphObject in ChildMorphRenderable + #define ANALYSIS_VIDEO_FIRST_FRAME_DONE 9 // * A call to dpl_DrawSceneComplete at the end of Video execute loop + #define ANALYSIS_VIDEO_BATCH_FLUSH 9 // * Set whenever dpl_FlushArticulations is called + #define ANALYSIS_VIDEO_RENDERER_FRAME_DONE 9 // * Set whenever we check to see if a frame is done + #define ANALYSIS_VIDEO_BECOME_INTERESTING 9 // * video renderer become interesting processes. + #define ANALYSIS_VIDEO_LOAD_OBJECT 9 // load object in default MakeEntityRenderables + #define ANALYSIS_VIDEO_CONSTRUCT_ROOT 9 // root renderable in default MakeEntityRenderables + #define ANALYSIS_VIDEO_NEW_DCS 9 // dpl_NewDCS call in RootRenderable constructor + #define ANALYSIS_VIDEO_NEW_INSTANCE 9 // dpl_NewINSTANCE call in RootRenderable constructor + #define ANALYSIS_VIDEO_FLUSH_INSTANCE 9 // dpl_FlushInstance call in RootRenderable constructor + #define ANALYSIS_VIDEO_ADD_DCS_TO_SCENE 9 // dpl_AddDCSToScene call in RootRenderable constructor + #define ANALYSIS_VIDEO_FLUSH_DCS 9 // dpl_FlushDCS call in RootRenderable constructor + #define ANALYSIS_VIDEO_BECOME_UNINTERESTING 9 // * Marks video renderer become uninteresting processes. +*/ + // without changes to asmpkt.asm! +# endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Macro definitions ... these make sure that profile.hpp is not forgotten +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~ Application Profiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(ANALYSIS_FOREGROUND_PROCESSING) +# define SET_ANALYSIS_FOREGROUND_PROCESSING()\ + Set_Analysis(ANALYSIS_FOREGROUND_PROCESSING) +# define CLEAR_ANALYSIS_FOREGROUND_PROCESSING()\ + Clear_Analysis(ANALYSIS_FOREGROUND_PROCESSING) +#else +# define SET_ANALYSIS_FOREGROUND_PROCESSING() +# define CLEAR_ANALYSIS_FOREGROUND_PROCESSING() +#endif + +#if defined(ANALYSIS_RENDERER_MANAGER) +# define SET_ANALYSIS_RENDERER_MANAGER()\ + Set_Analysis(ANALYSIS_RENDERER_MANAGER) +# define CLEAR_ANALYSIS_RENDERER_MANAGER()\ + Clear_Analysis(ANALYSIS_RENDERER_MANAGER) +#else +# define SET_ANALYSIS_RENDERER_MANAGER() +# define CLEAR_ANALYSIS_RENDERER_MANAGER() +#endif + +#if defined(ANALYSIS_PROCESS_EVENT) +# define SET_ANALYSIS_PROCESS_EVENT()\ + Set_Analysis(ANALYSIS_PROCESS_EVENT) +# define CLEAR_ANALYSIS_PROCESS_EVENT()\ + Clear_Analysis(ANALYSIS_PROCESS_EVENT) +#else +# define SET_ANALYSIS_PROCESS_EVENT() +# define CLEAR_ANALYSIS_PROCESS_EVENT() +#endif + +#if defined(ANALYSIS_COMPLETE_CYCLES) +# define SET_ANALYSIS_COMPLETE_CYCLES()\ + Set_Analysis(ANALYSIS_COMPLETE_CYCLES) +# define CLEAR_ANALYSIS_COMPLETE_CYCLES()\ + Clear_Analysis(ANALYSIS_COMPLETE_CYCLES) +#else +# define SET_ANALYSIS_COMPLETE_CYCLES() +# define CLEAR_ANALYSIS_COMPLETE_CYCLES() +#endif + +#if defined(ANALYSIS_DEATH_ROW) +# define SET_ANALYSIS_DEATH_ROW()\ + Set_Analysis(ANALYSIS_DEATH_ROW) +# define CLEAR_ANALYSIS_DEATH_ROW()\ + Clear_Analysis(ANALYSIS_DEATH_ROW) +#else +# define SET_ANALYSIS_DEATH_ROW() +# define CLEAR_ANALYSIS_DEATH_ROW() +#endif + +#if defined(ANALYSIS_APP_MGR) +# define SET_ANALYSIS_APP_MGR()\ + Set_Analysis(ANALYSIS_APP_MGR) +# define CLEAR_ANALYSIS_APP_MGR()\ + Clear_Analysis(ANALYSIS_APP_MGR) +#else +# define SET_ANALYSIS_APP_MGR() +# define CLEAR_ANALYSIS_APP_MGR() +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Network Profiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(ANALYSIS_ROUTE_PACKET) +# define SET_ANALYSIS_ROUTE_PACKET()\ + Set_Analysis(ANALYSIS_ROUTE_PACKET) +# define CLEAR_ANALYSIS_ROUTE_PACKET()\ + Clear_Analysis(ANALYSIS_ROUTE_PACKET) +#else +# define SET_ANALYSIS_ROUTE_PACKET() +# define CLEAR_ANALYSIS_ROUTE_PACKET() +#endif + +#if defined(ANALYSIS_SEND_PACKET) +# define SET_ANALYSIS_SEND_PACKET()\ + Set_Analysis(ANALYSIS_SEND_PACKET) +# define CLEAR_ANALYSIS_SEND_PACKET()\ + Clear_Analysis(ANALYSIS_SEND_PACKET) +#else +# define SET_ANALYSIS_SEND_PACKET() +# define CLEAR_ANALYSIS_SEND_PACKET() +#endif + +#if defined(ANALYSIS_CHECK_BUFFERS) +# define SET_ANALYSIS_CHECK_BUFFERS()\ + Set_Analysis(ANALYSIS_CHECK_BUFFERS) +# define CLEAR_ANALYSIS_CHECK_BUFFERS()\ + Clear_Analysis(ANALYSIS_CHECK_BUFFERS) +#else +# define SET_ANALYSIS_CHECK_BUFFERS() +# define CLEAR_ANALYSIS_CHECK_BUFFERS() +#endif + +#if defined(ANALYSIS_CALL_NETNUB) +# define SET_ANALYSIS_CALL_NETNUB()\ + Set_Analysis(ANALYSIS_CALL_NETNUB) +# define CLEAR_ANALYSIS_CALL_NETNUB()\ + Clear_Analysis(ANALYSIS_CALL_NETNUB) +#else +# define SET_ANALYSIS_CALL_NETNUB() +# define CLEAR_ANALYSIS_CALL_NETNUB() +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Entity Profiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(ANALYSIS_UPDATE_MANAGER) +# define SET_ANALYSIS_UPDATE_MANAGER()\ + Set_Analysis(ANALYSIS_UPDATE_MANAGER) +# define CLEAR_ANALYSIS_UPDATE_MANAGER()\ + Clear_Analysis(ANALYSIS_UPDATE_MANAGER) +#else +# define SET_ANALYSIS_UPDATE_MANAGER() +# define CLEAR_ANALYSIS_UPDATE_MANAGER() +#endif + +#if defined(ANALYSIS_UPDATE_REPLICANTS) +# define SET_ANALYSIS_UPDATE_REPLICANTS()\ + Set_Analysis(ANALYSIS_UPDATE_REPLICANTS) +# define CLEAR_ANALYSIS_UPDATE_REPLICANTS()\ + Clear_Analysis(ANALYSIS_UPDATE_REPLICANTS) +#else +# define SET_ANALYSIS_UPDATE_REPLICANTS() +# define CLEAR_ANALYSIS_UPDATE_REPLICANTS() +#endif + +#if defined(ANALYSIS_UPDATE_MASTERS) +# define SET_ANALYSIS_UPDATE_MASTERS()\ + Set_Analysis(ANALYSIS_UPDATE_MASTERS) +# define CLEAR_ANALYSIS_UPDATE_MASTERS()\ + Clear_Analysis(ANALYSIS_UPDATE_MASTERS) +#else +# define SET_ANALYSIS_UPDATE_MASTERS() +# define CLEAR_ANALYSIS_UPDATE_MASTERS() +#endif + +#if defined(ANALYSIS_EXECUTE_ENTITY) +# define SET_ANALYSIS_EXECUTE_ENTITY()\ + Set_Analysis(ANALYSIS_EXECUTE_ENTITY) +# define CLEAR_ANALYSIS_EXECUTE_ENTITY()\ + Clear_Analysis(ANALYSIS_EXECUTE_ENTITY) +#else +# define SET_ANALYSIS_EXECUTE_ENTITY() +# define CLEAR_ANALYSIS_EXECUTE_ENTITY() +#endif + +#if defined(ANALYSIS_PERFORM_ENTITY) +# define SET_ANALYSIS_PERFORM_ENTITY()\ + Set_Analysis(ANALYSIS_PERFORM_ENTITY) +# define CLEAR_ANALYSIS_PERFORM_ENTITY()\ + Clear_Analysis(ANALYSIS_PERFORM_ENTITY) +#else +# define SET_ANALYSIS_PERFORM_ENTITY() +# define CLEAR_ANALYSIS_PERFORM_ENTITY() +#endif + +#if defined(ANALYSIS_PERFORM_SUBSYSTEMS) +# define SET_ANALYSIS_PERFORM_SUBSYSTEMS()\ + Set_Analysis(ANALYSIS_PERFORM_SUBSYSTEMS) +# define CLEAR_ANALYSIS_PERFORM_SUBSYSTEMS()\ + Clear_Analysis(ANALYSIS_PERFORM_SUBSYSTEMS) +#else +# define SET_ANALYSIS_PERFORM_SUBSYSTEMS() +# define CLEAR_ANALYSIS_PERFORM_SUBSYSTEMS() +#endif + +#if defined(ANALYSIS_EXECUTE_WATCHERS) +# define SET_ANALYSIS_EXECUTE_WATCHERS()\ + Set_Analysis(ANALYSIS_EXECUTE_WATCHERS) +# define CLEAR_ANALYSIS_EXECUTE_WATCHERS()\ + Clear_Analysis(ANALYSIS_EXECUTE_WATCHERS) +#else +# define SET_ANALYSIS_EXECUTE_WATCHERS() +# define CLEAR_ANALYSIS_EXECUTE_WATCHERS() +#endif + +#if defined(ANALYSIS_JOINT_PERFORMANCE) +# define SET_ANALYSIS_JOINT_PERFORMANCE()\ + Set_Analysis(ANALYSIS_JOINT_PERFORMANCE) +# define CLEAR_ANALYSIS_JOINT_PERFORMANCE()\ + Clear_Analysis(ANALYSIS_JOINT_PERFORMANCE) +#else +# define SET_ANALYSIS_JOINT_PERFORMANCE() +# define CLEAR_ANALYSIS_JOINT_PERFORMANCE() +#endif + +//~~~~~~~~~~~~~~~~~~~~~~ Video Renderer Profiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(ANALYSIS_VIDEO_NEW_INSTANCE) +# define SET_ANALYSIS_VIDEO_NEW_INSTANCE()\ + Set_Analysis(ANALYSIS_VIDEO_NEW_INSTANCE) +# define CLEAR_ANALYSIS_VIDEO_NEW_INSTANCE()\ + Clear_Analysis(ANALYSIS_VIDEO_NEW_INSTANCE) +#else +# define SET_ANALYSIS_VIDEO_NEW_INSTANCE() +# define CLEAR_ANALYSIS_VIDEO_NEW_INSTANCE() +#endif + +#if defined(ANALYSIS_VIDEO_NEW_DCS) +# define SET_ANALYSIS_VIDEO_NEW_DCS()\ + Set_Analysis(ANALYSIS_VIDEO_NEW_DCS) +# define CLEAR_ANALYSIS_VIDEO_NEW_DCS()\ + Clear_Analysis(ANALYSIS_VIDEO_NEW_DCS) +#else +# define SET_ANALYSIS_VIDEO_NEW_DCS() +# define CLEAR_ANALYSIS_VIDEO_NEW_DCS() +#endif + +#if defined(ANALYSIS_VIDEO_FLUSH_INSTANCE) +# define SET_ANALYSIS_VIDEO_FLUSH_INSTANCE()\ + Set_Analysis(ANALYSIS_VIDEO_FLUSH_INSTANCE) +# define CLEAR_ANALYSIS_VIDEO_FLUSH_INSTANCE()\ + Clear_Analysis(ANALYSIS_VIDEO_FLUSH_INSTANCE) +#else +# define SET_ANALYSIS_VIDEO_FLUSH_INSTANCE() +# define CLEAR_ANALYSIS_VIDEO_FLUSH_INSTANCE() +#endif + +#if defined(ANALYSIS_VIDEO_ADD_DCS_TO_SCENE) +# define SET_ANALYSIS_VIDEO_ADD_DCS_TO_SCENE()\ + Set_Analysis(ANALYSIS_VIDEO_ADD_DCS_TO_SCENE) +# define CLEAR_ANALYSIS_VIDEO_ADD_DCS_TO_SCENE()\ + Clear_Analysis(ANALYSIS_VIDEO_ADD_DCS_TO_SCENE) +#else +# define SET_ANALYSIS_VIDEO_ADD_DCS_TO_SCENE() +# define CLEAR_ANALYSIS_VIDEO_ADD_DCS_TO_SCENE() +#endif + +#if defined(ANALYSIS_VIDEO_FLUSH_DCS) +# define SET_ANALYSIS_VIDEO_FLUSH_DCS()\ + Set_Analysis(ANALYSIS_VIDEO_FLUSH_DCS) +# define CLEAR_ANALYSIS_VIDEO_FLUSH_DCS()\ + Clear_Analysis(ANALYSIS_VIDEO_FLUSH_DCS) +#else +# define SET_ANALYSIS_VIDEO_FLUSH_DCS() +# define CLEAR_ANALYSIS_VIDEO_FLUSH_DCS() +#endif + +#if defined(ANALYSIS_VIDEO_CONSTRUCT_ROOT) +# define SET_ANALYSIS_VIDEO_CONSTRUCT_ROOT()\ + Set_Analysis(ANALYSIS_VIDEO_CONSTRUCT_ROOT) +# define CLEAR_ANALYSIS_VIDEO_CONSTRUCT_ROOT()\ + Clear_Analysis(ANALYSIS_VIDEO_CONSTRUCT_ROOT) +#else +# define SET_ANALYSIS_VIDEO_CONSTRUCT_ROOT() +# define CLEAR_ANALYSIS_VIDEO_CONSTRUCT_ROOT() +#endif + +#if defined(ANALYSIS_VIDEO_LOAD_OBJECT) +# define SET_ANALYSIS_VIDEO_LOAD_OBJECT()\ + Set_Analysis(ANALYSIS_VIDEO_LOAD_OBJECT) +# define CLEAR_ANALYSIS_VIDEO_LOAD_OBJECT()\ + Clear_Analysis(ANALYSIS_VIDEO_LOAD_OBJECT) +#else +# define SET_ANALYSIS_VIDEO_LOAD_OBJECT() +# define CLEAR_ANALYSIS_VIDEO_LOAD_OBJECT() +#endif + +#if defined(ANALYSIS_VIDEO_FIRST_FRAME_DONE) +# define SET_ANALYSIS_VIDEO_FIRST_FRAME_DONE()\ + Set_Analysis(ANALYSIS_VIDEO_FIRST_FRAME_DONE) +# define CLEAR_ANALYSIS_VIDEO_FIRST_FRAME_DONE()\ + Clear_Analysis(ANALYSIS_VIDEO_FIRST_FRAME_DONE) +#else +# define SET_ANALYSIS_VIDEO_FIRST_FRAME_DONE() +# define CLEAR_ANALYSIS_VIDEO_FIRST_FRAME_DONE() +#endif + +#if defined(ANALYSIS_VIDEO_MORPH_SEND) +# define SET_ANALYSIS_VIDEO_MORPH_SEND()\ + Set_Analysis(ANALYSIS_VIDEO_MORPH_SEND) +# define CLEAR_ANALYSIS_VIDEO_MORPH_SEND()\ + Clear_Analysis(ANALYSIS_VIDEO_MORPH_SEND) +#else +# define SET_ANALYSIS_VIDEO_MORPH_SEND() +# define CLEAR_ANALYSIS_VIDEO_MORPH_SEND() +#endif + +#if defined(ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION) +# define SET_ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION()\ + Set_Analysis(ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION) +# define CLEAR_ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION()\ + Clear_Analysis(ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION) +#else +# define SET_ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION() +# define CLEAR_ANALYSIS_VIDEO_EXECUTE_IMPLEMENTATION() +#endif + +#if defined(ANALYSIS_VIDEO_RENDERER_FRAME_DONE) +# define SET_ANALYSIS_VIDEO_RENDERER_FRAME_DONE()\ + Set_Analysis(ANALYSIS_VIDEO_RENDERER_FRAME_DONE) +# define CLEAR_ANALYSIS_VIDEO_RENDERER_FRAME_DONE()\ + Clear_Analysis(ANALYSIS_VIDEO_RENDERER_FRAME_DONE) +#else +# define SET_ANALYSIS_VIDEO_RENDERER_FRAME_DONE() +# define CLEAR_ANALYSIS_VIDEO_RENDERER_FRAME_DONE() +#endif + +#if defined(ANALYSIS_VIDEO_BECOME_INTERESTING) +# define SET_ANALYSIS_VIDEO_BECOME_INTERESTING()\ + Set_Analysis(ANALYSIS_VIDEO_BECOME_INTERESTING) +# define CLEAR_ANALYSIS_VIDEO_BECOME_INTERESTING()\ + Clear_Analysis(ANALYSIS_VIDEO_BECOME_INTERESTING) +#else +# define SET_ANALYSIS_VIDEO_BECOME_INTERESTING() +# define CLEAR_ANALYSIS_VIDEO_BECOME_INTERESTING() +#endif + +#if defined(ANALYSIS_VIDEO_BECOME_UNINTERESTING) +# define SET_ANALYSIS_VIDEO_BECOME_UNINTERESTING()\ + Set_Analysis(ANALYSIS_VIDEO_BECOME_UNINTERESTING) +# define CLEAR_ANALYSIS_VIDEO_BECOME_UNINTERESTING()\ + Clear_Analysis(ANALYSIS_VIDEO_BECOME_UNINTERESTING) +#else +# define SET_ANALYSIS_VIDEO_BECOME_UNINTERESTING() +# define CLEAR_ANALYSIS_VIDEO_BECOME_UNINTERESTING() +#endif + +#if defined(ANALYSIS_VIDEO_RENDERERABLES) +# define SET_ANALYSIS_VIDEO_RENDERERABLES()\ + Set_Analysis(ANALYSIS_VIDEO_RENDERERABLES) +# define CLEAR_ANALYSIS_VIDEO_RENDERERABLES()\ + Clear_Analysis(ANALYSIS_VIDEO_RENDERERABLES) +#else +# define SET_ANALYSIS_VIDEO_RENDERERABLES() +# define CLEAR_ANALYSIS_VIDEO_RENDERERABLES() +#endif + +#if defined(ANALYSIS_VIDEO_BATCH_FLUSH) +# define SET_ANALYSIS_VIDEO_BATCH_FLUSH()\ + Set_Analysis(ANALYSIS_VIDEO_BATCH_FLUSH) +# define CLEAR_ANALYSIS_VIDEO_BATCH_FLUSH()\ + Clear_Analysis(ANALYSIS_VIDEO_BATCH_FLUSH) +#else +# define SET_ANALYSIS_VIDEO_BATCH_FLUSH() +# define CLEAR_ANALYSIS_VIDEO_BATCH_FLUSH() +#endif + +#if defined(ANALYSIS_VIDEO_PICKPOINT) +# define SET_ANALYSIS_VIDEO_PICKPOINT()\ + Set_Analysis(ANALYSIS_VIDEO_PICKPOINT) +# define CLEAR_ANALYSIS_VIDEO_PICKPOINT()\ + Clear_Analysis(ANALYSIS_VIDEO_PICKPOINT) +#else +# define SET_ANALYSIS_VIDEO_PICKPOINT() +# define CLEAR_ANALYSIS_VIDEO_PICKPOINT() +#endif + +//~~~~~~~~~~~~~~~~~~~~~~ Audio Renderer Profiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(ANALYSIS_AUDIO_RENDERER) +# define SET_ANALYSIS_AUDIO_RENDERER()\ + Set_Analysis(ANALYSIS_AUDIO_RENDERER) +# define CLEAR_ANALYSIS_AUDIO_RENDERER()\ + Clear_Analysis(ANALYSIS_AUDIO_RENDERER) +#else +# define SET_ANALYSIS_AUDIO_RENDERER() +# define CLEAR_ANALYSIS_AUDIO_RENDERER() +#endif + +#if defined(ANALYSIS_AUDIO_RENDERER_MIDI) +# define SET_ANALYSIS_AUDIO_RENDERER_MIDI()\ + Set_Analysis(ANALYSIS_AUDIO_RENDERER_MIDI) +# define CLEAR_ANALYSIS_AUDIO_RENDERER_MIDI()\ + Clear_Analysis(ANALYSIS_AUDIO_RENDERER_MIDI) +#else +# define SET_ANALYSIS_AUDIO_RENDERER_MIDI() +# define CLEAR_ANALYSIS_AUDIO_RENDERER_MIDI() +#endif + +//~~~~~~~~~~~~~~~~~~~~~~ Controls Manager Profiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(ANALYSIS_RIO_ANALOG_REQUEST) +# define SET_ANALYSIS_RIO_ANALOG_REQUEST()\ + Set_Analysis(ANALYSIS_RIO_ANALOG_REQUEST) +# define CLEAR_ANALYSIS_RIO_ANALOG_REQUEST()\ + Clear_Analysis(ANALYSIS_RIO_ANALOG_REQUEST) +#else +# define SET_ANALYSIS_RIO_ANALOG_REQUEST() +# define CLEAR_ANALYSIS_RIO_ANALOG_REQUEST() +#endif + +#if defined(ANALYSIS_RIO_PROCESS_EVENT) +# define SET_ANALYSIS_RIO_PROCESS_EVENT()\ + Set_Analysis(ANALYSIS_RIO_PROCESS_EVENT) +# define CLEAR_ANALYSIS_RIO_PROCESS_EVENT()\ + Clear_Analysis(ANALYSIS_RIO_PROCESS_EVENT) +#else +# define SET_ANALYSIS_RIO_PROCESS_EVENT() +# define CLEAR_ANALYSIS_RIO_PROCESS_EVENT() +#endif + +#if defined(ANALYSIS_JOYSTICK) +# define SET_ANALYSIS_JOYSTICK() Set_Analysis(ANALYSIS_JOYSTICK) +# define CLEAR_ANALYSIS_JOYSTICK() Clear_Analysis(ANALYSIS_JOYSTICK) +#else +# define SET_ANALYSIS_JOYSTICK() +# define CLEAR_ANALYSIS_JOYSTICK() +#endif + +#if defined(ANALYSIS_MOUSE) +# define SET_ANALYSIS_MOUSE() Set_Analysis(ANALYSIS_MOUSE) +# define CLEAR_ANALYSIS_MOUSE() Clear_Analysis(ANALYSIS_MOUSE) +#else +# define SET_ANALYSIS_MOUSE() +# define CLEAR_ANALYSIS_MOUSE() +#endif + +#if defined(ANALYSIS_SCALAR_UPDATE) +# define SET_ANALYSIS_SCALAR_UPDATE() Set_Analysis(ANALYSIS_SCALAR_UPDATE) +# define CLEAR_ANALYSIS_SCALAR_UPDATE() Clear_Analysis(ANALYSIS_SCALAR_UPDATE) +#else +# define SET_ANALYSIS_SCALAR_UPDATE() +# define CLEAR_ANALYSIS_SCALAR_UPDATE() +#endif + +#if defined(ANALYSIS_JOYSTICK_UPDATE) +# define SET_ANALYSIS_JOYSTICK_UPDATE() Set_Analysis(ANALYSIS_JOYSTICK_UPDATE) +# define CLEAR_ANALYSIS_JOYSTICK_UPDATE()\ + Clear_Analysis(ANALYSIS_JOYSTICK_UPDATE) +#else +# define SET_ANALYSIS_JOYSTICK_UPDATE() +# define CLEAR_ANALYSIS_JOYSTICK_UPDATE() +#endif + +#if defined(ANALYSIS_KEYBOARD_UPDATE) +# define SET_ANALYSIS_KEYBOARD_UPDATE() Set_Analysis(ANALYSIS_KEYBOARD_UPDATE) +# define CLEAR_ANALYSIS_KEYBOARD_UPDATE()\ + Clear_Analysis(ANALYSIS_KEYBOARD_UPDATE) +#else +# define SET_ANALYSIS_KEYBOARD_UPDATE() +# define CLEAR_ANALYSIS_KEYBOARD_UPDATE() +#endif + +#if defined(ANALYSIS_JOYSTICK_BUTTON_UPDATE) +# define SET_ANALYSIS_JOYSTICK_BUTTON_UPDATE()\ + Set_Analysis(ANALYSIS_JOYSTICK_BUTTON_UPDATE) +# define CLEAR_ANALYSIS_JOYSTICK_BUTTON_UPDATE()\ + Clear_Analysis(ANALYSIS_JOYSTICK_BUTTON_UPDATE) +#else +# define SET_ANALYSIS_JOYSTICK_BUTTON_UPDATE() +# define CLEAR_ANALYSIS_JOYSTICK_BUTTON_UPDATE() +#endif + +#if defined(ANALYSIS_MOUSE_BUTTON_UPDATE) +# define SET_ANALYSIS_MOUSE_BUTTON_UPDATE()\ + Set_Analysis(ANALYSIS_MOUSE_BUTTON_UPDATE) +# define CLEAR_ANALYSIS_MOUSE_BUTTON_UPDATE()\ + Clear_Analysis(ANALYSIS_MOUSE_BUTTON_UPDATE) +#else +# define SET_ANALYSIS_MOUSE_BUTTON_UPDATE() +# define CLEAR_ANALYSIS_MOUSE_BUTTON_UPDATE() +#endif + +#if defined(ANALYSIS_BACKGROUND_ROUTE_PACKET) +# define SET_ANALYSIS_BACKGROUND_ROUTE_PACKET()\ + Set_Analysis(ANALYSIS_BACKGROUND_ROUTE_PACKET) +# define CLEAR_ANALYSIS_BACKGROUND_ROUTE_PACKET()\ + Clear_Analysis(ANALYSIS_BACKGROUND_ROUTE_PACKET) +#else +# define SET_ANALYSIS_BACKGROUND_ROUTE_PACKET() +# define CLEAR_ANALYSIS_BACKGROUND_ROUTE_PACKET() +#endif + +#if defined(ANALYSIS_RIO_DELETE_RIO) +# define SET_ANALYSIS_RIO_DELETE_RIO()\ + Set_Analysis(ANALYSIS_RIO_DELETE_RIO) +# define CLEAR_ANALYSIS_RIO_DELETE_RIO()\ + Clear_Analysis(ANALYSIS_RIO_DELETE_RIO) +#else +# define SET_ANALYSIS_RIO_DELETE_RIO() +# define CLEAR_ANALYSIS_RIO_DELETE_RIO() +#endif + +#if defined(ANALYSIS_RIO_SEND_PACKET) +# define SET_ANALYSIS_RIO_SEND_PACKET()\ + Set_Analysis(ANALYSIS_RIO_SEND_PACKET) +# define CLEAR_ANALYSIS_RIO_SEND_PACKET()\ + Clear_Analysis(ANALYSIS_RIO_SEND_PACKET) +#else +# define SET_ANALYSIS_RIO_SEND_PACKET() +# define CLEAR_ANALYSIS_RIO_SEND_PACKET() +#endif + +#if defined(ANALYSIS_RIO_RECEIVE_PACKET) +# define SET_ANALYSIS_RIO_RECEIVE_PACKET()\ + Set_Analysis(ANALYSIS_RIO_RECEIVE_PACKET) +# define CLEAR_ANALYSIS_RIO_RECEIVE_PACKET()\ + Clear_Analysis(ANALYSIS_RIO_RECEIVE_PACKET) +#else +# define SET_ANALYSIS_RIO_RECEIVE_PACKET() +# define CLEAR_ANALYSIS_RIO_RECEIVE_PACKET() +#endif + +#if defined(ANALYSIS_RIO_ANALOG_UPDATE) +# define SET_ANALYSIS_RIO_ANALOG_UPDATE()\ + Set_Analysis(ANALYSIS_RIO_ANALOG_UPDATE) +# define CLEAR_ANALYSIS_RIO_ANALOG_UPDATE()\ + Clear_Analysis(ANALYSIS_RIO_ANALOG_UPDATE) +#else +# define SET_ANALYSIS_RIO_ANALOG_UPDATE() +# define CLEAR_ANALYSIS_RIO_ANALOG_UPDATE() +#endif + +#if defined(ANALYSIS_RIO_MISC_REQUEST) +# define SET_ANALYSIS_RIO_MISC_REQUEST()\ + Set_Analysis(ANALYSIS_RIO_MISC_REQUEST) +# define CLEAR_ANALYSIS_RIO_MISC_REQUEST()\ + Clear_Analysis(ANALYSIS_RIO_MISC_REQUEST) +#else +# define SET_ANALYSIS_RIO_MISC_REQUEST() +# define CLEAR_ANALYSIS_RIO_MISC_REQUEST() +#endif + +#if defined(ANALYSIS_RIO_RESET_STICK) +# define SET_ANALYSIS_RIO_RESET_STICK()\ + Set_Analysis(ANALYSIS_RIO_RESET_STICK) +# define CLEAR_ANALYSIS_RIO_RESET_STICK()\ + Clear_Analysis(ANALYSIS_RIO_RESET_STICK) +#else +# define SET_ANALYSIS_RIO_RESET_STICK() +# define CLEAR_ANALYSIS_RIO_RESET_STICK() +#endif + +#if defined(ANALYSIS_PERFORM) +# define SET_ANALYSIS_PERFORM() Set_Analysis(ANALYSIS_PERFORM) +# define CLEAR_ANALYSIS_PERFORM() Clear_Analysis(ANALYSIS_PERFORM) +#else +# define SET_ANALYSIS_PERFORM() +# define CLEAR_ANALYSIS_PERFORM() +#endif + +#if defined(ANALYSIS_APP_INITIALIZE) +# define SET_ANALYSIS_APP_INITIALIZE() Set_Analysis(ANALYSIS_APP_INITIALIZE) +# define CLEAR_ANALYSIS_APP_INITIALIZE() Clear_Analysis(ANALYSIS_APP_INITIALIZE) +#else +# define SET_ANALYSIS_APP_INITIALIZE() +# define CLEAR_ANALYSIS_APP_INITIALIZE() +#endif + + +#if defined(ANALYSIS_WAIT_FOR_DROP) +# define SET_ANALYSIS_WAIT_FOR_DROP() Set_Analysis(ANALYSIS_WAIT_FOR_DROP) +# define CLEAR_ANALYSIS_WAIT_FOR_DROP() Clear_Analysis(ANALYSIS_WAIT_FOR_DROP) +#else +# define SET_ANALYSIS_WAIT_FOR_DROP() +# define CLEAR_ANALYSIS_WAIT_FOR_DROP() +#endif + +#if defined(ANALYSIS_GAUGE_RENDERER) +# define SET_ANALYSIS_GAUGE_RENDERER() Set_Analysis(ANALYSIS_GAUGE_RENDERER) +# define CLEAR_ANALYSIS_GAUGE_RENDERER()\ + Clear_Analysis(ANALYSIS_GAUGE_RENDERER) +#else +# define SET_ANALYSIS_GAUGE_RENDERER() +# define CLEAR_ANALYSIS_GAUGE_RENDERER() +#endif + +#if defined(ANALYSIS_SCREEN_COPY) +# define SET_ANALYSIS_SCREEN_COPY() Set_Analysis(ANALYSIS_SCREEN_COPY) +# define CLEAR_ANALYSIS_SCREEN_COPY() Clear_Analysis(ANALYSIS_SCREEN_COPY) +#else +# define SET_ANALYSIS_SCREEN_COPY() +# define CLEAR_ANALYSIS_SCREEN_COPY() +#endif + +#endif diff --git a/CODE/RP/MUNGA_L4/NetNub/include/BOOTP.H b/CODE/RP/MUNGA_L4/NetNub/include/BOOTP.H new file mode 100644 index 0000000..081580a --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/BOOTP.H @@ -0,0 +1,73 @@ + +/* + * Bootstrap Protocol (BOOTP) + * Based on RFC 951. + */ + + +#define BOOTREQUEST 1 /* bootp.bp_op */ +#define BOOTREPLY 2 + +/* + * structure for send and receives + */ +typedef struct bootp { + byte bp_op; /* packet op code / message type. */ + byte bp_htype; /* hardware address type, 1 = 10 mb ethernet */ + byte bp_hlen; /* hardware address len, eg '6' for 10mb eth */ + byte bp_hops; /* client sets to zero, optionally used by + gateways in cross-gateway booting. */ + longword bp_xid; /* transaction ID, a random number */ + word bp_secs; /* filled in by client, seconds elapsed since + client started trying to boot. */ + word bp_spare; + longword bp_ciaddr; /* client IP address filled in by client if known*/ + longword bp_yiaddr; /* 'your' (client) IP address + filled by server if client doesn't know */ + longword bp_siaddr; /* server IP address returned in bootreply */ + longword bp_giaddr; /* gateway IP address, + used in optional cross-gateway booting. */ + byte bp_chaddr[16]; /* client hardware address, filled by client */ + byte bp_sname[64]; /* optional server host name, null terminated*/ + + byte bp_file[128]; /* boot file name, null terminated string + 'generic' name or null in bootrequest, + fully qualified directory-path + name in bootreply. */ + byte bp_vend[ 64]; /* optional vendor-specific area */ +}; + + +extern struct bootp _bootp; +extern word sock_inactive; + +/* + * UDP port numbers, server and client. + */ +#define IPPORT_BOOTPS 67 +#define IPPORT_BOOTPC 68 + + +/******** the following is stolen from NCSA which came from CUTCP *********/ +/* I have not implemented these, but someone may wish to in the future so */ +/* I kept them around. */ +/**************************************************************************/ + +/* + * "vendor" data permitted for Stanford boot clients. + */ +struct vend { + byte v_magic[4]; /* magic number */ + longword v_flags; /* flags/opcodes, etc. */ + byte v_unused[56]; /* currently unused */ +}; + +#define VM_STANFORD "STAN" /* v_magic for Stanford */ +/*#define VM_RFC1048 "\143\202\123\143" /* 94.11.20 */ + +/* v_flags values */ +#define VF_PCBOOT 1 /* an IBMPC or Mac wants environment info */ +#define VF_HELP 2 /* help me, I'm not registered */ +#define TAG_BOOTFILE_SIZE 13 /* tag used by vend fields rfc 1048 */ + + diff --git a/CODE/RP/MUNGA_L4/NetNub/include/COPYRIGH.H b/CODE/RP/MUNGA_L4/NetNub/include/COPYRIGH.H new file mode 100644 index 0000000..01877e9 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/COPYRIGH.H @@ -0,0 +1,110 @@ +/* + * WATTCP - TCP/IP library routines + * + * Copyright (c) 1990, 1991, 1992, 1993 Erick Engelke + * + * Portions Copyright (c) 1993 Quentin Smart + * Portions Copyright (c) 1991 University of Waterloo + * Portions Copyright (c) 1990 National Center for Supercomputer Applications + * Portions Copyright (c) 1990 Clarkson University + * Portions Copyright (c) 1983, 1986, Imagen Corporation + * + * This software is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. + * + * RESTRICTIONS + * ------------ + * You may freely use this library to produce programs which you may give + * away or sell in source format, or as compiled executables, or both. + * + * You may not sell this library or a portion thereof or distribute modified + * versions the library code in either source or OBJect or LIBrary format + * without written permission from the author. The author still maintains + * copyright privileges and will assert the privileges of ownership for + * purposes of royalties such distributions. + * + * Portions of this code were written or enhanced by others and offerred + * to me for distribution in WATTCP under my copyright. To my knowledge, + * all copyrights exercised are listed at the top of this file. If this + * is incorrect, please contact me so I can rectify the situation. + * + * + * OFFICIAL SITE + * ------------- + * The official distribution site for WATTCP (and many other TCP goodies) + * is dorm.rutgers.edu in pub/msdos/wattcp (thanks Jim!) + * + * That is where I upload the latest libraries, my own free applications + * and other applications I have collected and find useful. + * + * + * DOCUMENTATION + * ------------- + * A programmer's reference manual I wrote is now available from the + * publisher. They provide no additional support and cannot help + * you with any aspect of the software. But they do pay a royalty + * to me which has been used to compensate my costs for developing + * this software and extending it, so I am very appreciative. + * + * That manual is copyrighted and protected by international law. + * It may not be copied without the authors permission. And its + * sale does not constitute a warranty or an automatic license to + * use WATTCP beyond the terms described in this file. + * + * For payment they accept credit cards, cheques, checks, money orders + * and P.O.s. Credit card orders can be processed over the telephone. + * + * Note that they are located in Canada and mail to them MAY REQUIRE + * additional postage depending on where you live. Also, be sure to + * use the entire address, including the last line. Canada is a heck + * of a large country and that line really makes a difference. + * + * Prices are listed in US dollars for convienence to our many + * international readers. The value charged on credit card items + * will be the equivalent in Canadian dollars at the exchange rate + * of the day. + * + * WATTCP Manual $ 40 US funds for each manual orderred + * ---------- + * Shipping + Handling $ 5 US funds to North America + * (Air Mail) or $ 10 US funds to anywhere else in the world + * + * ADD $ 20 US funds IF YOU ARE USING PURCHASE ORDERS + * in which case payment is due in 30 days. + * Not necessary for cheques, credit cards, etc. + * ---------- + * + * WATTCP Manual + * c/o Supro Network Software Inc. + * P.O. Box 18, + * Warsaw, Ont. + * CANADA + * K0L 3A0 + * + * Phone (705) 652-1572 and be certain to mention that you are talking + * about the WATTCP manual. + * + * Please note, I am not involved in the processing loop for the manual + * and cannot tell you of the status of your order. Use Supro's number + * instead. + * + * + * Developers' Meeting Place + * ------------------------- + * Many of the key people involved in WATTCP frequent the + * comp.protocols.tcp-ip.ibmpc Usenet newgroup, and there + * are several people there who can answer most any question. + * + * If you need my personal attention (I seem to have less and less + * available) you will have to Email my address below. I cannot take + * phone calls relating to WATTCP at my place of occupation. + * + * + * Erick Engelke erick@dorm.rutgers.edu + * 48 Daytona St. + * Kitchener, Ont. + * Canada + * + */ +#define WATTCP_C "WATTCP_C" diff --git a/CODE/RP/MUNGA_L4/NetNub/include/ELIB.H b/CODE/RP/MUNGA_L4/NetNub/include/ELIB.H new file mode 100644 index 0000000..b6d3b1a --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/ELIB.H @@ -0,0 +1,25 @@ +void outch( char ch ); /* print character to stdio */ +void outs( char far *s); /* print a ASCIIZ string to stdio */ +void outsn( char far *s,int n); /* print a string with len max n */ +void outhex( char ch ); +void outhexes( char far *ch, int n ); +void qmove( void far * src, void far * dest, int len ); +int qcmp( void far *src, void far *dest, int len ); +void _keep( int status, int paragraphs ); +int sem_up( void far * ptr ); +unsigned long set_timeout( unsigned int seconds ); +unsigned long set_ttimeout( unsigned int ticks ); +int chk_timeout( unsigned long timeout ); + +unsigned long intel( unsigned long ); +unsigned short intel16( unsigned short ); +unsigned inchksum( void far *ptr, int len); /* IP checksum */ + +/* + * qmsg.c + */ +void dputch( char x ); +void dmsg( char *s ); +void dhex1int( int x ); +void dhex2int( int x ); +void dhex4int( int x ); diff --git a/CODE/RP/MUNGA_L4/NetNub/include/ETHDEV.H b/CODE/RP/MUNGA_L4/NetNub/include/ETHDEV.H new file mode 100644 index 0000000..f8149f2 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/ETHDEV.H @@ -0,0 +1,16 @@ +/* + * + * Ethernet Interface + */ + +extern byte *_eth_FormatPacket(), *_eth_WaitPacket(); + +typedef struct ether { + byte dest[6]; /* destination ethernet address */ + byte src[6]; /* source ethernet address */ + word type; + byte data[ 1500 ]; +}; + + +#define ETH_MIN 60 /* Minimum Ethernet packet size */ diff --git a/CODE/RP/MUNGA_L4/NetNub/include/ICMP.H b/CODE/RP/MUNGA_L4/NetNub/include/ICMP.H new file mode 100644 index 0000000..01bfdc5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/ICMP.H @@ -0,0 +1,101 @@ + +#ifndef _wattcp_icmp_h +#define _wattcp_icmp_h + +//#include +#include + +typedef struct icmp_unused { + byte type; + byte code; + word checksum; + longword unused; + in_Header ip; + byte spares[ 8 ]; +}; + +typedef struct icmp_pointer { + byte type; + byte code; + word checksum; + byte pointer; + byte unused[ 3 ]; + in_Header ip; +}; +typedef struct icmp_ip { + byte type; + byte code; + word checksum; + longword ipaddr; + in_Header ip; +}; +typedef struct icmp_echo { + byte type; + byte code; + word checksum; + word identifier; + word sequence; + longword index; +}; + +typedef struct icmp_timestamp { + byte type; + byte code; + word checksum; + word identifier; + word sequence; + longword original; /* original timestamp */ + longword receive; /* receive timestamp */ + longword transmit; /* transmit timestamp */ +}; + +typedef struct icmp_info { + byte type; + byte code; + word checksum; + word identifier; + word sequence; +}; + +typedef union { + struct icmp_unused unused; + struct icmp_pointer pointer; + struct icmp_ip ip; + struct icmp_echo echo; + struct icmp_timestamp timestamp; + struct icmp_info info; +} icmp_pkt; + +typedef struct _pkt { + in_Header in; + icmp_pkt icmp; + in_Header data; +}; + +#define ICMPTYPE_ECHOREPLY 0 +#define ICMPTYPE_UNREACHABLE 3 +#define ICMPTYPE_TIMEEXCEEDED 11 + +typedef enum ICMP_UnreachableCodes +{ + ICMP_UNREACH_NET = 0, + ICMP_UNREACH_HOST = 1, + ICMP_UNREACH_PROTO = 2, + ICMP_UNREACH_PORT = 3, + ICMP_UNREACH_FRAGNEEDED = 4, + ICMP_UNREACH_SRCROUTEFAILED = 5 +}; + +typedef enum ICMP_TimeExceededCodes +{ + ICMP_EXCEEDED_TTL = 0, + ICMP_EXCEEDED_FRAGREASM = 1 +}; + +/* a user-installed ICMP handler */ +typedef int (*icmp_handler_type)( in_Header *ip ); + +/* install a user ICMP handler, or NULL to disable */ +void set_icmp_handler( icmp_handler_type user_handler ); + +#endif /* ndef _wattcp_icmp_h */ diff --git a/CODE/RP/MUNGA_L4/NetNub/include/STATE.RST b/CODE/RP/MUNGA_L4/NetNub/include/STATE.RST new file mode 100644 index 0000000..fa131ce --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/STATE.RST @@ -0,0 +1,13 @@ +[edit-] +screen=80 25 +toggles=1 1 0 1 0 0 +srch= +src= +rpl= +file=c:\tcpip\include\bootp.h 1 23 2 28 +[brief] +file=c:\tcpip\include\bootp.h 1 23 2 28 1 22 78 1 c=0 +file=c:\tcpip\include\wattcp.h 1 1 1 1 +file=c:\tcpip\include\copyrigh.h 1 67 1 67 +[shared-] +pmark=c:\tcpip\include\bootp.h 2 28 diff --git a/CODE/RP/MUNGA_L4/NetNub/include/TCP.H b/CODE/RP/MUNGA_L4/NetNub/include/TCP.H new file mode 100644 index 0000000..ef31670 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/TCP.H @@ -0,0 +1,98 @@ + +/* + * Waterloo TCP + * + * Copyright (c) 1990, 1991, 1992, 1993 Erick Engelke + * + * Portions copyright others, see copyright.h for details. + * + * This library is free software; you can use it or redistribute under + * the terms of the license included in LICENSE.H. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * file LICENSE.H for more details. + * + */ +#ifndef _wattcp_tcp_h +#define _wattcp_tcp_h + +#ifndef WTCP_VER + +#define __WATTCP_USER__ /* Not compiling the kernel itself, hide some stuff */ + +#include + +/* handle some early dumb naming conventions */ +#define dbuginit() dbug_init() + +/* Kernal version (major major minor minor) */ +#define WTCP_VER 0x0102 + +/* + * Typedefs and constants + */ + +struct in_addr { + longword s_addr; +}; + +/* + * BSD-style socket info routines -- bsdname.c + */ +int getpeername( sock_type *s, void *dest, int *len ); +int getsockname( sock_type *s, void *dest, int *len ); +char *getdomainname( char *name, int length ); +char *setdomainname( char *string ); +char *gethostname( char *name, int len ); +char *sethostname( char *name ); +void psocket( sock_type *s ); + +/* + * ICMP-related stuff -- pcicmp.c + */ +/* + * Send an icmp echo request using specified ttl and tos. + * if(icmp_id != NULL) store copy of the id there + */ +int _send_ping( longword host, longword countnum, byte ttl, + byte tos, longword *theid ); +/* backward compatibility */ +#define _ping( h, c ) _send_ping( h, c, 250, 0, NULL ) +longword _chk_ping( longword host , longword *ptr); + +/* + * Daemons -- wattcpd.c + */ +int addwattcpd( void (*p)( void ) ); +int delwattcpd( void (*p)( void ) ); + +/* + * Background net I/O processing -- netback.c + */ +void backgroundon( void ); +void backgroundoff(void); +void backgroundfn( void (*fn)() ); + +/* + * More background processing -- pcintr.c + */ +void wintr_enable( void ); +void wintr_disable( void ); +void wintr_shutdown( void ); +void wintr_init( void ); + +/* + * Socket stats -- pcstat.c + */ +int sock_stats( sock_type *s, word *days, word *inactive, word *cwindow, word *avg, word *sd ); + +/* + * Debug test routine -- test.c + */ +void debugpsocketlen( void ); + +#endif /* WTCP_VER */ + +#endif /* ndef _wattcp_tcp_h */ diff --git a/CODE/RP/MUNGA_L4/NetNub/include/TCP.MOD b/CODE/RP/MUNGA_L4/NetNub/include/TCP.MOD new file mode 100644 index 0000000..ce53a9a --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/TCP.MOD @@ -0,0 +1,288 @@ +/* + * Waterloo TCP + * + * Copyright (c) 1990, 1991, 1992, 1993 Erick Engelke + * + * Portions copyright others, see copyright.h for details. + * + * This library is free software; you can use it or redistribute under + * the terms of the license included in LICENSE.H. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * file LICENSE.H for more details. + * + */ +#ifndef WTCP_VER +extern "C" { +/* handle some early dumb naming conventions */ +#define dbuginit() dbug_init() + +/* Kernal version (major major minor minor) */ +#define WTCP_VER 0x0102 + +/* + * Typedefs and constants + */ + +#ifndef byte +typedef unsigned char byte; +#endif byte +#ifndef word +typedef unsigned int word; +#endif word +#ifndef longword +typedef unsigned long longword; +#endif longword + +typedef struct { + byte undoc[ 4300 ]; +} tcp_Socket; + +typedef struct { + byte undoc[ 2200 ]; +} udp_Socket; + + +typedef struct sockaddr { + word s_type; + word s_port; + longword s_ip; + byte s_spares[6]; /* unused in TCP realm */ +}; + +#define sockaddr_in sockaddr + +typedef struct in_addr { + longword s_addr; +}; + + +#define MAX_COOKIES 10 +#define MAX_NAMESERVERS 10 + +#define TCP_MODE_BINARY 0 +#define TCP_MODE_ASCII 1 +#define UDP_MODE_CHK 0 /*default to checksum */ +#define UDP_MODE_NOCHK 2 +#define TCP_MODE_NAGLE 0 /* Nagle algorithm */ +#define TCP_MODE_NONAGLE 4 + +extern sock_init(); +/* + * s is the pointer to a udp or tcp socket + */ +extern sock_read(void *s, byte *dp, int len ); +extern sock_fastread(void *s, byte *dp, int len ); +extern sock_write(void *s, byte *dp, int len); +extern void sock_enqueue(void *s, byte *dp, int len); +extern sock_fastwrite(void *s, byte *dp, int len ); +extern sock_flush( void *s ); +extern sock_flushnext( void *s); +extern sock_puts( void *s, byte *dp ); +extern word sock_gets( void *s, byte *dp, int n ); +extern byte sock_putc( void *s, byte c ); +extern byte sock_getc( void *s ); +extern word sock_dataready( void *s ); +extern sock_close( void *s ); +extern sock_abort( void *s ); +extern sock_printf( void *s, char *format, ... ); +extern sock_scanf( void *s, char *format, ... ); +extern sock_mode( void *s, word mode ); /* see TCP_MODE_... */ +extern void db_write( char *msg ); +extern void dbug_init(); +extern void dbug_printf(char *,... ); + +/* + * TCP or UDP specific stuff, must be used for open's and listens, but + * sock stuff is used for everything else + */ +typedef int(*UDPdataHandlerType)(udp_Socket *s, byte *dp, int len, void *ph, void *up); +typedef int(*TCPdataHandlerType)(tcp_Socket *s, byte *dp, int len); + +extern int udp_open(void *s, word lport, longword ina, word port, UDPdataHandlerType); +extern int tcp_open(void *s, word lport, longword ina, word port, TCPdataHandlerType); +extern tcp_listen(void *s, word lport, longword ina, word port, TCPdataHandlerType, word timeout); +extern int tcp_established(void *s); +extern char *rip( char *s ); +extern longword resolve( char *name); +/* + * less general functions + */ +extern longword aton( char *text ); +extern int isaddr( char *text ); +extern tcp_cbreak( word mode ); +extern longword intel( longword x ); +extern word intel16( word x ); + +/* + * timers + */ + +extern void ip_timer_init( void *s , word delayseconds ); +extern word ip_timer_expired( void *s ); + /* + * TCP/IP system variables - do not change these since they + * are not necessarily the source variables, instead use + * ip_Init function + */ +extern longword my_ip_addr; +extern longword sin_mask; /* eg. 0xfffffe00L */ +extern word sock_delay; + + /* + * tcp_init/tcp_shutdown + * - init/kill all tcp and lower services + * - only call if you do not use sock_init + * (NOT RECOMMENDED) + */ +extern tcp_shutdown(); +extern tcp_Init(); + +/* + * things you probably won't need to know about + */ + /* + * sock_debugdump + * - dump some socket control block parameters + * used for testing the kernal, not recommended + */ +extern sock_debugdump( void *s); + /* + * tcp_config - read a configuration file + * - if special path desired, call after sock_init() + * - null reads path from executable + * see sock_init(); + */ +extern tcp_config( char *path ); + /* + * tcp_tick - called periodically by user application in sock_wait_... + * - returns 1 when our socket closes + */ +extern tcp_tick( void *s ); + /* + * Retransmitter - called periodically to perform tcp retransmissions + * - normally called from tcp_tick, you have to be pretty + * low down to use this one + */ +extern tcp_Retransmitter(); + /* + * tcp_set_debug_state - set 1 or reset 0 - depends on what I have done + */ +extern tcp_set_debug_state( word x ); + + +extern int _last_cookie; +extern longword _cookie[MAX_COOKIES]; + + /* + * name domain constants + */ + +extern char *def_domain; +extern longword def_nameservers[ MAX_NAMESERVERS ]; + + +extern word wathndlcbrk; +extern word watcbroke; +/* + * sock_wait_... macros + */ +/* + * sock_wait_established() + * - waits then aborts if timeout on s connection + * sock_wait_input() + * - waits for received input on s + * - may not be valid input for sock_Gets... check returned length + * sock_tick() + * - do tick and jump on abort + * sock_wait_closed(); + * - discards all received data + * + * jump to sock_err with contents of *statusptr set to + * 1 on closed + * -1 on timeout + * + */ +extern int _ip_delay0( void *s, int seconds, int (*fn)(), void *statusptr ); +extern int _ip_delay1( void *s, int seconds, int (*fn)(), void *statusptr ); +extern int _ip_delay2( void *s, int seconds, int (*fn)(), void *statusptr ); + +extern unsigned long set_timeout( unsigned int seconds ); +extern unsigned long set_ttimeout( unsigned int ticks ); +extern int chk_timeout( unsigned long timeout ); + + + +extern int tcp_tick( void *s ); + +#define sock_wait_established( s, seconds, fn, statusptr ) \ + if (_ip_delay0( s, seconds, fn, statusptr )) goto sock_err; +#define sock_wait_input( s, seconds, fn , statusptr ) \ + if (_ip_delay1( s, seconds, fn, statusptr )) goto sock_err; +#define sock_tick( s, statusptr ) \ + if ( !tcp_tick(s)) { if (statusptr) *statusptr = 1 ; goto sock_err; } +#define sock_wait_closed(s, seconds, fn, statusptr )\ + if (_ip_delay2( s, seconds, fn, statusptr )) goto sock_err; + +/* user initialization file */ +extern void (*usr_init)(); + +extern void outs( char far * string ); +extern longword aton( char * string); +extern int _ping( longword host , longword countnum ); +extern longword _chk_ping( longword host , longword *ptr); +extern void _arp_register( longword use, longword instead_of ); + + + +extern void _eth_init(); +extern byte *_eth_formatpacket( void *eth_dest, word eth_type ); +extern void _eth_send( word len); +extern void _eth_free( void *buf); +extern byte *_eth_arrived( word *type_ptr); +extern void _eth_release(); + + + +/* bsd-similar stuff */ + +extern int sock_rbsize( void *s ); +extern int sock_rbused( void *s ); +extern int sock_rbleft( void *s ); +extern int sock_tbsize( void *s ); +extern int sock_tbused( void *s ); +extern int sock_tbleft( void *s ); + + +extern _chk_socket( tcp_Socket *s ); +extern char *inet_ntoa( char *s, longword x ); +extern char *psocket( tcp_Socket *s ); +extern longword inet_addr( char *s ); +extern char *sockerr( tcp_Socket *s ); +extern char *sockstate( tcp_Socket *s ); +extern getpeername( tcp_Socket *s, void *dest, int *len ); +extern getsockname( tcp_Socket *s, void *dest, int *len ); +extern longword gethostid(); +extern longword sethostid( longword ip ); +extern char *getdomainname( char *name, int length ); +extern char *setdomainname( char *string ); +extern char *gethostname( char *name, int length ); +extern char *sethostname( char *string ); +extern word ntohs( word a ); +extern word htons( word a ); +extern longword ntohl( longword x ); +extern longword htonl( longword x ); + +extern void _arp_register( longword use, longword instead_of ); +extern int _arp_resolve( longword ina, void *ethap, int nowait ); + +extern _survivebootp; +extern int sock_established( tcp_Socket *s); +extern sock_stats( tcp_Socket *s, word *days, word *inactive, word *cwindow, word *avg, word *sd ); +extern int addwattcpd( void (*p)() ); +extern int delwattcpd( void (*p)() ); +extern int tap_add( void *socket, void *userid ); +}; +#endif /* WTCP_VER */ diff --git a/CODE/RP/MUNGA_L4/NetNub/include/WATTCP.H b/CODE/RP/MUNGA_L4/NetNub/include/WATTCP.H new file mode 100644 index 0000000..4ea59f1 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/include/WATTCP.H @@ -0,0 +1,735 @@ + +#ifndef _wattcp_wattcp_h +#define _wattcp_wattcp_h + +/* + * Are we compiling the kernel? + * or an application using the kernel? + */ +#if !defined(__WATTCP_USER__) +#define __WATTCP_KERNEL__ +#endif + +/* + * Note that some stuff is not available to user applications. + * This is generally detail you shouldn't need to worry about, + * and best stay away from to preserve the kernel integrity. + * Note also that there is a lot of other stuff that should probably + * be protected but isn't. + */ + +#define WATTCPH + +/* these are visible for select.c routine return values */ +#define SOCKESTABLISHED 1 +#define SOCKDATAREADY 2 +#define SOCKCLOSED 4 + +#if defined(__WATTCP_KERNEL__) + +#define IP_TYPE 0x0008 + +/* +#define DEBUG +*/ + +#include +#include + +#define MAX_GATE_DATA 12 +#define MAX_STRING 50 /* most strings are limited */ +#endif /* defined(__WATTCP_KERNEL__) */ + +#define MAX_NAMESERVERS 10 +#define MAX_COOKIES 10 + +#if defined(__WATTCP_KERNEL__) + +#define MAXVJSA 1440 /* 10 s */ +#define MAXVJSD 360 /* 10 s */ +#define SAFETYTCP 0x538f25a3L +#define SAFETYUDP 0x3e45e154L +#define TRUE 1 +#define true TRUE +#define FALSE 0 +#define false FALSE + +#define EL_INUSE 0x0001 +#define EL_DELAY 0x0002 +#define EL_TCP 0x0004 +#define EL_SERVER 0x0008 +#define EL_ASCII 0x0010 +#define EL_NEVER 0x0020 + +/* These are Ethernet protocol numbers but I use them for other things too */ +#define UDP_PROTO 0x11 +#define TCP_PROTO 0x06 +#define ICMP_PROTO 0x01 + +#endif /* defined(__WATTCP_KERNEL__) */ + +#define TCP_MODE_BINARY 0 /* default mode */ +#define TCP_MODE_ASCII 1 +#define UDP_MODE_CHK 0 /* default to having checksums */ +#define UDP_MODE_NOCHK 2 /* turn off checksums */ +#define TCP_MODE_NAGLE 0 /* Nagle algorithm */ +#define TCP_MODE_NONAGLE 4 + +typedef unsigned long longword; /* 32 bits */ +typedef unsigned short word; /* 16 bits */ +typedef unsigned char byte; /* 8 bits */ + +typedef struct { byte eaddr[6]; } eth_address; // 94.11.19 -- made an array + +#if defined(__WATTCP_KERNEL__) + +/* undesirable */ +extern longword MsecClock(); +#define clock_ValueRough() MsecClock() + +#define TICKS_SEC 18 + +#define checksum( p, len) inchksum( p, len ) + +#define PD_ETHER 1 +#define PD_SLIP 6 + +extern word sock_inactive; /* in pcbootp.c */ +extern word _pktdevclass; +extern word _mss; +extern word _bootptimeout; /* in pcbootp.c */ +extern longword _bootphost; /* in pcbootp.c */ +extern word _bootpon; + +/* The Ethernet header */ +typedef struct { + eth_address destination; + eth_address source; + word type; +} eth_Header; + +/* The Internet Header: */ +typedef struct { + unsigned hdrlen : 4; + unsigned ver : 4; + byte tos; + word length; + word identification; + word frags; + byte ttl; + byte proto; + word checksum; + longword source; + longword destination; +} in_Header; + + +#define in_GetVersion(ip) ( (ip)->ver ) +#define in_GetHdrlen(ip) ( (ip)->hdrlen ) /* 32 bit word size */ +#define in_GetHdrlenBytes(ip) ( in_GetHdrlen(ip) << 2 ) /* 8 bit byte size */ +#define in_GetTos(ip) ( (ip)->tos) + +#define in_GetTTL(ip) ((ip)->ttl) +#define in_GetProtocol(ip) ((ip)->proto ) + +typedef struct { + word srcPort; + word dstPort; + word length; + word checksum; +} udp_Header; + +#define UDP_LENGTH ( sizeof( udp_Header )) + +typedef struct { + word srcPort; + word dstPort; + longword seqnum; + longword acknum; + word flags; + word window; + word checksum; + word urgentPointer; +} tcp_Header; + +#define tcp_FlagFIN 0x0001 +#define tcp_FlagSYN 0x0002 +#define tcp_FlagRST 0x0004 +#define tcp_FlagPUSH 0x0008 +#define tcp_FlagACK 0x0010 +#define tcp_FlagURG 0x0020 +#define tcp_FlagDO 0xF000 +#define tcp_GetDataOffset(tp) (intel16((tp)->flags) >> 12) + +#endif /* defined(__WATTCP_KERNEL__) + +/* The TCP/UDP Pseudo Header */ +typedef struct { + longword src; + longword dst; + byte mbz; + byte protocol; + word length; + word checksum; +} tcp_PseudoHeader; + + +/* A datahandler for tcp or udp sockets */ +typedef int (*dataHandler_t)( void *s, byte *data, int len, tcp_PseudoHeader *pseudohdr, void *protohdr ); +/* A socket function for delay routines */ +typedef int (*sockfunct_t)( void *s ); + +#if defined(__WATTCP_KERNEL__) +/* + * TCP states, from tcp manual. + * Note: close-wait state is bypassed by automatically closing a connection + * when a FIN is received. This is easy to undo. + */ +#define tcp_StateLISTEN 0 /* listening for connection */ +#define tcp_StateSYNSENT 1 /* syn sent, active open */ +#define tcp_StateSYNREC 2 /* syn received, synack+syn sent. */ +#define tcp_StateESTAB 3 /* established */ +#define tcp_StateESTCL 4 /* established, but will FIN */ +#define tcp_StateFINWT1 5 /* sent FIN */ +#define tcp_StateFINWT2 6 /* sent FIN, received FINACK */ +#define tcp_StateCLOSWT 7 /* received FIN waiting for close */ +#define tcp_StateCLOSING 8 /* sent FIN, received FIN (waiting for FINACK) */ +#define tcp_StateLASTACK 9 /* fin received, finack+fin sent */ +#define tcp_StateTIMEWT 10 /* dally after sending final FINACK */ +#define tcp_StateCLOSEMSL 11 +#define tcp_StateCLOSED 12 /* finack received */ + + +#endif + +#define tcp_MaxBufSize 4096 // was 2048 and inside the __WATTCP_KERNEL__ ifdef /* maximum bytes to buffer on input */ + +#if defined(__WATTCP_KERNEL__) +/* + * UDP socket definition + */ +typedef struct _udp_socket { + struct _udp_socket *next; + word ip_type; /* always set to UDP_PROTO */ + char *err_msg; /* null when all is ok */ + char *usr_name; + void (*usr_yield)( void ); + byte rigid; + byte stress; + word sock_mode; /* a logical OR of bits */ + longword usertimer; /* ip_timer_set, ip_timer_timeout */ + dataHandler_t dataHandler; + eth_address hisethaddr; /* peer's ethernet address */ + longword hisaddr; /* peer's internet address */ + word hisport; /* peer's UDP port */ + longword myaddr; + word myport; + word locflags; + + int queuelen; + byte *queue; + + int rdatalen; /* must be signed */ + word maxrdatalen; + byte *rdata; + byte rddata[ tcp_MaxBufSize + 1]; /* if dataHandler = 0, len == 512 */ + longword safetysig; +} udp_Socket; +#else /* __WATTCP_USER */ +/* + * Don't give users access to the fields. + */ +typedef struct { + byte undoc[ tcp_MaxBufSize + 152]; // was [2200]; +} udp_Socket; +#endif /* __WATTCP_USER__ */ + +#if defined(__WATTCP_KERNEL__) +/* + * TCP Socket definition + */ +typedef struct _tcp_socket { + struct _tcp_socket *next; + word ip_type; /* always set to TCP_PROTO */ + char *err_msg; + char *usr_name; + void (*usr_yield)(void); + byte rigid; + byte stress; + word sock_mode; /* a logical OR of bits */ + + longword usertimer; /* ip_timer_set, ip_timer_timeout */ + dataHandler_t dataHandler; /* called with incoming data */ + eth_address hisethaddr; /* ethernet address of peer */ + longword hisaddr; /* internet address of peer */ + word hisport; /* tcp ports for this connection */ + longword myaddr; + word myport; + word locflags; + + int queuelen; + byte *queue; + + int rdatalen; /* must be signed */ + word maxrdatalen; + byte *rdata; + byte rddata[tcp_MaxBufSize+1]; /* received data */ + longword safetysig; + word state; /* connection state */ + + longword acknum; + longword seqnum; /* data ack'd and sequence num */ + long timeout; /* timeout, in milliseconds */ + byte unhappy; /* flag, indicates retransmitting segt's */ + byte recent; /* 1 if recently transmitted */ + word flags; /* tcp flags word for last packet sent */ + + word window; /* other guy's window */ + int datalen; /* number of bytes of data to send */ + /* must be signed */ + int unacked; /* unacked data */ + + byte cwindow; /* Van Jacobson's algorithm */ + byte wwindow; + + word vj_sa; /* VJ's alg, standard average */ + word vj_sd; /* VJ's alg, standard deviation */ + longword vj_last; /* last transmit time */ + word rto; + byte karn_count; /* count of packets */ + byte tos; /* priority */ + /* retransmission timeout proceedure */ + /* these are in clock ticks */ + longword rtt_lasttran; /* last transmission time */ + longword rtt_smooth; /* smoothed round trip time */ + longword rtt_delay; /* delay for next transmission */ + longword rtt_time; /* time of next transmission */ + + word mss; + longword inactive_to; /* for the inactive flag */ + int sock_delay; + + byte data[tcp_MaxBufSize+1]; /* data to send */ +} tcp_Socket; +#else /* __WATTCP_USER */ +/* + * Don't give users access to the fields. + */ +typedef struct { + byte undoc[((tcp_MaxBufSize*2)+204)]; // WAS [ 4300 ]; +} tcp_Socket; +#endif /* __WATTCP_USER__ */ + +#if defined(__WATTCP_KERNEL__) +/* sock_type used for socket io */ +typedef union { + udp_Socket udp; + tcp_Socket tcp; +} sock_type; +#else /* __WATTCP_USER__ */ +typedef void sock_type; +#endif /* __WATTCP_USER__ */ + +/* similar to UNIX */ +struct sockaddr { + word s_type; + word s_port; + longword s_ip; + byte s_spares[6]; /* unused in TCP realm */ +}; +#define sockaddr_in sockaddr + + /* + * TCP/IP system variables - do not change these since they + * are not necessarily the source variables, instead use + * ip_Init function + */ +extern longword my_ip_addr; +extern longword sin_mask; /* eg. 0xfffffe00L */ +extern word sock_delay; + +#if defined(__WATTCP_KERNEL__) +extern eth_address _eth_addr; +extern eth_address _eth_brdcast; +#endif + + +#if defined(__WATTCP_KERNEL__) +/* + * ARP definitions + */ +#define arp_TypeEther 0x100 /* ARP type of Ethernet address */ + +/* arp op codes */ +#define ARP_REQUEST 0x0100 +#define ARP_REPLY 0x0200 + +/* + * Arp header + */ +typedef struct { + word hwType; + word protType; + word hwProtAddrLen; // hw and prot addr len + word opcode; + eth_address srcEthAddr; + longword srcIPAddr; + eth_address dstEthAddr; + longword dstIPAddr; +} arp_Header; + +#define ETH_MSS 1400 // MSS for Ethernet + +byte *fragment( in_Header * ip ); +void timeout_frags( void ); + +#endif + + +/* + * Ethernet interface -- pcsed.c + */ +void _eth_init( void ); +byte *_eth_formatpacket( eth_address *eth_dest, word eth_type ); +int _eth_send( word len ); +void _eth_free( void *buf ); +byte *_eth_arrived( word *type_ptr ); +void _eth_release( void ); +#if defined(__WATTCP_KERNEL__) +extern void *_eth_hardware( byte *p ); +#endif + + +/* + * timers -- pctcp.c + */ +void ip_timer_init( sock_type *s, int delayseconds ); +int ip_timer_expired( sock_type *s ); +longword MsecClock( void ); + + +/* + * sock_init() -- initialize wattcp libraries -- sock_ini.c + */ +void sock_init(void); +void sock_exit( void ); /* normally called via atexit() in sock_init() */ + + + /* + * tcp_init/tcp_shutdown -- pctcp.c + * - init/kill all tcp and lower services + * - only call if you do not use sock_init + * (NOT RECOMMENDED) + */ +void tcp_shutdown(void); +void tcp_init(void); + +/* + * things you probably won't need to know about + */ + /* + * sock_debugdump -- sock_dbu.c + * - dump some socket control block parameters + * used for testing the kernal, not recommended + */ +void sock_debugdump( sock_type *s ); + /* + * tcp_config - read a configuration file + * - if special path desired, call after sock_init() + * - null reads path from executable + * see sock_init(); + */ +int tcp_config( char *path ); + /* + * tcp_tick - called periodically by user application in sock_wait_... + * - returns 1 when our socket closes + */ +int tcp_tick( sock_type *s ); + /* + * Retransmitter - called periodically to perform tcp retransmissions + * - normally called from tcp_tick, you have to be pretty + * low down to use this one + */ +void tcp_Retransmitter(void); + /* + * tcp_set_debug_state - set 1 or reset 0 - depends on what I have done + */ +void tcp_set_debug_state( int x ); + +/* + * check for bugs -- pctcp.c + */ +int tcp_checkfor( sock_type *t ); + +/* + * Timeout routines. + */ +unsigned long set_timeout( unsigned int seconds ); +unsigned long set_ttimeout( unsigned int ticks ); +int chk_timeout( unsigned long timeout ); + +/* + * socket macros + */ + +/* + * sock_wait_established() + * - waits then aborts if timeout on s connection + * sock_wait_input() + * - waits for received input on s + * - may not be valid input for sock_gets... check returned length + * sock_tick() + * - do tick and jump on abort + * sock_wait_closed(); + * - discards all received data + * + * jump to sock_err with contents of *statusptr set to + * 1 on closed + * -1 on timeout + * + */ + +int _ip_delay0( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr ); +int _ip_delay1( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr); +int _ip_delay2( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr); + + +#if defined(__WATTCP_KERNEL__) +#define set_mstimeout( x ) (set_timeout(0)+ (x / 55)) +#endif /* defined(__WATTCP_KERNEL__) */ + +#define sock_wait_established( s, seconds, fn, statusptr ) \ + if (_ip_delay0( s, seconds, fn, statusptr )) goto sock_err; +#define sock_wait_input( s, seconds, fn , statusptr ) \ + if (_ip_delay1( s, seconds, fn, statusptr )) goto sock_err; +#define sock_tick( s, statusptr ) \ + if ( !tcp_tick(s)) { *statusptr = 1 ; goto sock_err; } +#define sock_wait_closed(s, seconds, fn, statusptr )\ + if (_ip_delay2( s, seconds, fn, statusptr )) goto sock_err; + +/* + * TCP or UDP specific stuff, must be used for open's and listens, but + * sock stuff is used for everything else -- pctcp.c + */ +int tcp_open( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler ); +int udp_open( udp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler ); +int tcp_listen( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler, word timeout ); +int tcp_established( tcp_Socket *s ); + +/* + * Clean up a string -- pctcp.c + */ +char *rip( char *s); + +/* + * Name service / name lookup routines -- udp_dom.c + */ +longword resolve( char *name ); +int reverse_addr_lookup( longword ipaddr, char *name ); + +/* + * less general functions + */ +longword intel( longword x ); +word intel16( word x ); +longword MsecClock( void ); + +/* + * Ctrl-break handling -- pc_cbrk.c + */ +void tcp_cbrk( int mode ); + +void outs( char far * string ); + +#if defined(__WATTCP_KERNEL__) +/* icmp handler -- pcicmp.c */ +int icmp_handler( in_Header *ip ); +#endif + + +/* + * ARP -- pcarp.c + */ +#if defined(__WATTCP_KERNEL__) +void _arp_add_gateway( char *data, longword ip ); +int _arp_handler( arp_Header *in ); +#endif +void _arp_register( longword use, longword instead_of ); +void _arp_tick( longword ip ); /* kernel only? */ +int _arp_resolve( longword ina, eth_address *ethap, int nowait ); + + + +/* + * Packet -- pcpkt.c + * + * These probably shouldn't be visible to user app code. + */ +eth_address *_pkt_eth_init( void ); +int pkt_send( char *buffer, int length ); +void pkt_buf_wipe( void ); +void pkt_buf_release( char *ptr ); +void * pkt_received( void ); +void pkt_release( void ); + +#if defined(__WATTCP_KERNEL__) +void _add_server( int *counter, int max, longword *array, longword value ); +extern word debug_on; +#endif + + +/* + * pcbsd.c + */ +int _chk_socket( sock_type *s ); +char *inet_ntoa( char *s, longword x ); +longword inet_addr( char *s ); +char *sockerr( sock_type *s ); +char *sockstate( sock_type *s ); +longword gethostid( void ); +longword sethostid( longword ip ); +word ntohs( word a ); +word htons( word a ); +longword ntohl( longword x ); +longword htonl( longword x ); + + +#if defined(__WATTCP_KERNEL__) +void *_tcp_lookup( longword hisip, word hisport, word myport ); + +void _tcp_cancel( in_Header *ip, int code, char *msg, longword dummyip ); +void _udp_cancel( in_Header *ip ); + +int _dobootp(void); +#endif + + +/* + * General socket I/O -- pctcp.c + */ +word sock_mode( sock_type *, word); /* see TCP_MODE_... */ +void sock_abort( sock_type *); +void tcp_sendsoon( tcp_Socket *s ); +int sock_fastwrite( sock_type *, byte *, int ); +int sock_write( sock_type *, byte *, int ); +int sock_read( sock_type *, byte *, int ); +int sock_fastread( sock_type *, byte *, int ); +int sock_gets( sock_type *, byte *, int ); +void sock_close( sock_type *s ); + +byte sock_putc( sock_type *s, byte c ); +int sock_getc( sock_type *s ); +int sock_puts( sock_type *s, byte *dp ); +int sock_gets(sock_type *, byte *, int ); + +int sock_setbuf( sock_type *s, byte *dp, int len ); + +int sock_yield( tcp_Socket *s, void (*fn)( void ) ); + + +/* + * s is the pointer to a udp or tcp socket + */ + + +/* + * Socket text output/input routines -- sock_prn.c + */ +int sock_printf( sock_type *s, char *format, ... ); +int sock_scanf( sock_type *s, char *format, ... ); + + +/* + * Misc. socket I/O -- pctcp.c + */ +int sock_setbuf( sock_type *s, byte *dp, int len ); +int sock_enqueue( sock_type *s, byte *dp, int len ); +void sock_noflush( sock_type *s ); +void sock_flush( sock_type *s ); +void sock_flushnext( sock_type *s); +int sock_dataready( sock_type *s ); +int sock_established( sock_type *s ); +void sock_sturdy( sock_type *s, int level ); + + +/* + * Debug output -- pcdbug.c + */ +void db_write( char *msg ); +void db_open( void ); +void db_close( void ); +void dbug_printf( char *, ... ); +void dbug_init( void ); +void dbug_init( void ); + + + +/* + * Socket Select -- select.c + */ +int sock_sselect( sock_type *s, int waitstate ); + + + +/* + * recv routines -- pcrecv.c + */ +int sock_recv_init( sock_type *s, void *space, word len ); +int sock_recv_from( sock_type *s, long *hisip, word *hisport, char *buffer, int len, word flags ); +int sock_recv( sock_type *s, char *buffer, int len, word flags ); + + +/* + * bsd-similar stuff -- pcbuf.c + */ +int sock_rbsize( sock_type *s ); +int sock_rbused( sock_type *s ); +int sock_rbleft( sock_type *s ); +int sock_tbsize( sock_type *s ); +int sock_tbused( sock_type *s ); +int sock_tbleft( sock_type *s ); +int sock_preread( sock_type *s, byte *dp, int len ); + + +/* + * Name conversion stuff -- udp_nds.c + */ +longword aton( char *text ); +int isaddr( char *text ); + +/* + * Configuration -- pcconfig.c + */ +char *_inet_atoeth( char *src, byte *eth ); +void _add_server( int *counter, int max, longword *array, longword value ); +int tcp_config( char *path ); + + /* + * name domain constants + */ + +extern char *def_domain; +extern longword def_nameservers[ MAX_NAMESERVERS ]; + +extern word wathndlcbrk; +extern word watcbroke; + +/* user initialization file */ +extern void (*usr_init)(char *name, char *value); + +extern int _survivebootp; + +extern int _last_cookie; +extern longword _cookie[MAX_COOKIES]; + +extern int _last_nameserver; +extern char *_hostname; + +/* + * Elib stuff + */ +int isstring( char *string, unsigned stringlen ); /* isstring.c */ + + + +#endif /* ndef _wattcp_wattcp_h */ diff --git a/CODE/RP/MUNGA_L4/NetNub/include/vssver.scc b/CODE/RP/MUNGA_L4/NetNub/include/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..cb5d54044bcd159749cb0f90be5991beca4062d5 GIT binary patch literal 176 zcmXpJVq`d2=P%iL-obO(RqsctpMq+xUbQILZ^Zxx2Y~b%4y~r$fu`RXfg%TieAh*{ z^*(Ps^$o;71msWpSTkqi$$Mb_VIW`Oqi9<5f~R2q5g@;2kHvk*?JvRnqd>khhn+Y3 s>Azt9F(Cibk*HV6wasAuaUlP|Ic>|Sr{;k9CxHCGXH)uYotJ|705Cj1YXATM literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/NetNub/lib/WATTCPLG.LIB b/CODE/RP/MUNGA_L4/NetNub/lib/WATTCPLG.LIB new file mode 100644 index 0000000000000000000000000000000000000000..fbbe1fe52a1ec14d4c70b18d8b5998faa6b96cd1 GIT binary patch literal 150016 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/NetNub/lib/vssver.scc b/CODE/RP/MUNGA_L4/NetNub/lib/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..2303893e46bdb9363b13bd86711d206d5cb5d092 GIT binary patch literal 48 ycmXpJVq`d2=P%iL-obO(RqsctpMq+%#G5ltS}}mZDIopj^g8GFU%bCD0!09;f)Ql^ literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/NetNub/mssccprj.scc b/CODE/RP/MUNGA_L4/NetNub/mssccprj.scc new file mode 100644 index 0000000..224058a --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/mssccprj.scc @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[netnub.mak] +SCC_Aux_Path = "M:\VWESS" +SCC_Project_Name = "$/Tesla_rp/MUNGA_L4/NetNub", DGWAAAAA diff --git a/CODE/RP/MUNGA_L4/NetNub/netnub.mak b/CODE/RP/MUNGA_L4/NetNub/netnub.mak new file mode 100644 index 0000000..e436129 --- /dev/null +++ b/CODE/RP/MUNGA_L4/NetNub/netnub.mak @@ -0,0 +1,95 @@ +.autodepend +.suffixes: .cpp + +!include make.cfg + +!ifndef NETNUB_ROOT +!error NETNUB_ROOT macro is not defined +!endif + +INCLUDE_PATH = $(NETNUB_ROOT)\include;$(NETNUB_ROOT);$(BC_ROOT)\include +LIBRARY_PATH = $(NETNUB_ROOT)\lib;$(BC_ROOT)\lib +.path.obj = $(NETNUB_ROOT)\obj +.path.lib = $(LIBRARY_PATH) + +CFG_FILE = $(NETNUB_ROOT)\netnub.cfg +OBJ_PREFIX = $(NETNUB_ROOT)\obj\\ + +#------------------------------------------------------------------------------ +# targets +# +all: $(CFG_FILE) $(NETNUB_ROOT)\netnub.exe + +clean: + del $(NETNUB_ROOT)\obj\*.obj + del $(NETNUB_ROOT)\*.exe + +assemble: + @echo No assembly targets + +#------------------------------------------------------------------------------ +# Implicit rules +# +LINK_OPTIONS = -Tde -c -L$(LIBRARY_PATH) +BCC = bcc + +$(CFG_FILE): $(NETNUB_ROOT)\netnub.mak + copy &&| +-DMSDOS;NETNUB;USE_PROFILE_ANALYSIS;CLEAN_BUILD=1 +-b +-r +-ff +-AT +-k- +-N- +-v- +-3 +-V +-Jg +-x- +-RT- +-O2 +-Ot +-Oc +-Og +-O +-Ol +-Z +-Ob +-Oe +-Oi +-Om +-Op +-Ov +-w +-c +-ml +-I$(INCLUDE_PATH) +-n$(NETNUB_ROOT)\obj +| $(CFG_FILE) + +{$(NETNUB_ROOT)}.cpp{$(NETNUB_ROOT)\obj}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +#------------------------------------------------------------------------------ +# Test program +# +NETNUB_OBJS = \ + ?netnub.obj \ + ?analysis.obj \ + ?nopause.obj + +$(NETNUB_ROOT)\netnub.exe:\ + $(NETNUB_OBJS:?=) $(NETNUB_ROOT)\lib\wattcplg.lib + tlink @&&| +$(LINK_OPTIONS) + +$(BC_ROOT)\lib\c0l.obj+ +$(NETNUB_OBJS:?=$(OBJ_PREFIX)) +$<,$* +wattcplg.lib+ +emu.lib+ +mathl.lib+ +cl.lib +| >>error.log + +$(NETNUB_OBJS:?=): $(CFG_FILE) diff --git a/CODE/RP/MUNGA_L4/NetNub/vssver.scc b/CODE/RP/MUNGA_L4/NetNub/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..d4d3c97e18ddb96cd03378ce85861724251fe099 GIT binary patch literal 144 zcmXpJVq`d2=P%iL-obO(RqsctpMq*kjz65d-HHJWb^vJ${dNIKgIrP2A6U^TO + rxBuf COMBUF <> +PCSPAK ENDS + +HISTORYSIZE equ 256 + +IRQ_EVENT equ 0 +IRQ_EVENT_RX equ 1 +IRQ_EVENT_TX equ 2 +IRQ_EVENT_MSR equ 3 +IRQ_EVENT_LSR equ 4 +IRQ_EVENT_BOGUS equ 5 + +TX_EVENT_RESTART equ 10 +TX_EVENT_ABANDON equ 11 +TX_EVENT_DONE equ 12 +TX_EVENT_ACK equ 13 +TX_EVENT_NAK equ 14 +TX_EVENT_EARLY equ 15 +TX_EVENT_EMPTY equ 16 +TX_EVENT_KICK equ 17 + +RX_EVENT_FULL equ 20 +RX_EVENT_NOT_CMD equ 21 +RX_EVENT_FULLBODY equ 22 +RX_EVENT_NAK equ 23 +RX_EVENT_CKSMERR equ 24 +RX_EVENT_OK equ 25 + +if KEEP_HISTORY + + SAVE_TX MACRO + LOCAL skip + + push ax + push ebx + + mov ebx,historyIndex + cmp ebx,HISTORYSIZE + jge skip + + mov ah,01h + mov history[ebx],ax + add ebx,2 + mov historyIndex,ebx + + inc pcspakCharactersSent ;;keep a running count +skip: + pop ebx + pop ax + ENDM + + SAVE_RX MACRO + LOCAL skip + + push ax + push ebx + + mov ebx,historyIndex + cmp ebx,HISTORYSIZE + jge skip + + mov ah,02h + mov history[ebx],ax + add ebx,2 + mov historyIndex,ebx + +skip: + pop ebx + pop ax + ENDM + + SAVE_EVENT MACRO marker + LOCAL skip + + push ax + push ebx + + mov ebx,historyIndex + cmp ebx,HISTORYSIZE + jge skip + + mov ah,03h + mov al,marker + mov history[ebx],ax + add ebx,2 + mov historyIndex,ebx + +skip: + pop ebx + pop ax + ENDM +else + SAVE_TX MACRO + inc pcspakCharactersSent ;;keep a running count + ENDM + + SAVE_RX MACRO + ENDM + + SAVE_EVENT MACRO marker + ENDM +endif + +;=========================================================================== +; Data segment +;=========================================================================== +BEGIN_DATA + +data_selector dw ? +irq_com1 IRQDATA +irq_com2 IRQDATA +irq_com3 IRQDATA +irq_com4 IRQDATA + + public historyIndex +historyIndex dd 0 + + public history +if KEEP_HISTORY + history dw HISTORYSIZE dup(0) +else + history dw 0 +endif + + public iThinkIRQIsOn +iThinkIRQIsOn dd 0 + + public pcspakCharactersSent +pcspakCharactersSent dd 0 + + public previousIMR,previousISR,previousIRR +previousIMR db 0 +previousISR db 0 +previousIRR db 0 + + public middleIMR,middleISR,middleIRR +middleIMR db 0 +middleISR db 0 +middleIRR db 0 + + public postIMR,postISR,postIRR +postIMR db 0 +postISR db 0 +postIRR db 0 + + public pcspakLSR,pcspakIER,pcspakIIR +pcspakLSR db 0 +pcspakIER db 0 +pcspakIIR db 0 + + + +global_serial_port dw 0 + +END_DATA +;=========================================================================== +; Code segment +;=========================================================================== +BEGIN_CODE + +;------------------------------------------------------------------------- +; PCSPAKInit() +; Constructor for serial packet driver interface +;------------------------------------------------------------------------- +; Enter: +; init_this = pointer to object +; init_port = address of serial port +; init_irq_num = interrupt number +; init_rx_len = pointer to (byte) receive length table +; init_tx_len = pointer to (byte) transmit length table +;------------------------------------------------------------------------- +; Returns: +; 1 if ok, +; -1 if IRQ's all used, +; -2 if DPMI error, +; -3 if really weird bogus error, +; else IIR value +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKInit + + ARG_DPTR init_this + ARG_WORD init_rate + ARG_WORD init_port + ARG_WORD init_irq_num + ARG_DPTR init_rx_len + ARG_WORD init_rx_count + ARG_DPTR init_tx_len + ARG_WORD init_tx_count + + LOCAL_DWORD return_status + + BUILD_STACK_FRAME + + mov return_status,0 ;everything's OK + ;-------------------------------------------------------------- + ; Save off the data selector so we can get it back later. + ;-------------------------------------------------------------- + ; ...In flat mode, CS and DS overlap, but CS is write-protected + ; and DS isn't. Therefore we can write DS to [data_selector] + ; and read it back from CS later. + ;-------------------------------------------------------------- + mov [data_selector],ds + ;-------------------------------------------------------------- + ; Disable interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + IRQ_WATCH 0 + ;-------------------------------------------------------------- + ; Point ESI at object data + ;-------------------------------------------------------------- + mov esi,init_this + ;-------------------------------------------------------------- + ; Clear the data buffers + ;-------------------------------------------------------------- + COM_INIT rxBuf ;assumes esi points to object + COM_INIT txBuf ;assumes esi points to object + ;-------------------------------------------------------------- + ; Initialize values + ;-------------------------------------------------------------- + xor eax,eax + mov enabled[esi],al ;clear 'enabled' flag + + mov txHoldOff[esi],al ;flag as not held off + mov txReply[esi],al ;clear 'reply' char + mov rxFlags[esi],al ;clear receive flags (ack/nak) + mov ErrorValue[esi],ax ;clear errors + mov intDataPtr[esi],eax ;(flag as not allocated) + + mov historyIndex,eax + + mov al,TX_IDLE_STATE ;initialize to idle state + mov txState[esi],al + + mov al,RX_IDLE_STATE ;initialize to idle state + mov rxState[esi],al + + mov ax,init_port ;get the port address + mov portBase[esi],ax ;save it + + mov eax,init_tx_len ;set dialect transmit table pointer + mov txTablePtr[esi],eax + + mov ax,init_tx_count ;set maximum dialect transmit index + mov txMaximum[esi],al + + mov eax,init_rx_len ;set dialect receive table pointer + mov rxTablePtr[esi],eax + + mov ax,init_rx_count ;set maximum dialect receive index + mov rxMaximum[esi],al + ;-------------------------------------------------------------- + ; Find unused IRQDATA structure + ;-------------------------------------------------------------- + mov ecx,4 + mov edi,OFFSET irq_com1 +searchLoop: + mov ax,irqPort[edi] ;is irqPort equal to zero? + je short searchDone ;yes, use this structure + add edi,SIZE IRQDATA ;no, move to next one + loop searchLoop + + mov ErrorValue[esi],ERR_INIT ;allocation failed, set errors! + mov return_status,-1 ;return an error code + jmp allocFailed + +searchDone: + mov ax,init_port ;save port address + mov irqPort[edi],ax + mov global_serial_port,ax ;save in case of crash + + mov ax,init_irq_num ;save interrupt number + mov irqNum[edi],al + ;-------------------------------------------------------------- + ; Save init_this in irq structure, irqPtr in "this" structure + ;-------------------------------------------------------------- + mov irqThis[edi],esi + mov intDataPtr[esi],edi + ;-------------------------------------------------------------- + ; Save the old PROTECTED MODE interrupt vector + ;-------------------------------------------------------------- + mov bl,irqNum[edi] ;bl has interrupt number + DPMI_GET_PROT_VECTOR ;returns cx:edx + mov irqOldSelector[edi],cx + mov irqOldOffset[edi],edx + ;-------------------------------------------------------------- + ; Set the new PROTECTED MODE interrupt vector + ;-------------------------------------------------------------- + mov bx,init_irq_num ;bl has interrupt number + mov cx,cs ;cx:edx has selector:offset + mov edx,irqHandler[edi] + DPMI_SET_PROT_VECTOR + jnc short allocOk ;carry clear, allocation succeeded + + mov ErrorValue[esi],ERR_INIT ;allocation failed, set errors! + mov return_status,-2 ;return an error code + jmp allocFailed +allocOk: + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ; Diagnostics values + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + PIC_IMR_TO_AL + mov previousIMR,al + PIC_ISR_TO_AL + mov previousISR,al + PIC_IRR_TO_AL + mov previousIRR,al + ;-------------------------------------------------------------- + ; Initialize PIC + ;-------------------------------------------------------------- + ;----------------------------- + ; Get master PIC data: + ; enable bit in bl, + ; interrupt number in bh + ;----------------------------- + mov ax,init_irq_num ;get interrupt number + cmp ax,0000Ch ;COM1? + jnz short mustBeCom2 ;no, must be COM2 + + mov bl,PIC_COM1COM3 ;yes, get COM1, COM3 enable... + mov bh,OCW2_SPEC_EOI+4 ;...and PIC specific EOI + jmp short hasPicBits + +mustBeCom2: + mov bl,PIC_COM2COM4 ;get COM2, COM4 enable... + mov bh,OCW2_SPEC_EOI+3 ;...and PIC specific EOI +hasPicBits: + mov irqPICbit[edi],bl ;save for termination + ;----------------------------- + ; Enable interrupts in PIC + ;----------------------------- + ASSERT_PIC_REG bl + ;----------------------------- + ; Make sure PIC interrupt + ; request is cleared + ;----------------------------- + mov al,bh ;output the specific EOI + out PIC_MASTER_0,al + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ; Diagnostics values + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + PIC_IMR_TO_AL + mov middleIMR,al + PIC_ISR_TO_AL + mov middleISR,al + PIC_IRR_TO_AL + mov middleIRR,al + ;-------------------------------------------------------------- + ; Initialize UART + ;-------------------------------------------------------------- + mov dx,init_port ;get port address from stack + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ; Diagnostics values + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + add dx,UART_IIR + in al,dx + mov pcspakIIR,al + sub dx,UART_IIR + ;----------------------------- + ; Disable UART interrupts + ;----------------------------- + RETRACT_MCR UART_MCR_IRQ ;This clears irq into PIC + ;----------------------------- + ; Disable all UART interrupt + ; sources. Not mandatory, + ; but a safe practice. + ;----------------------------- + RETRACT_IER UART_IER_ALL + ;----------------------------- + ; Set baud rate + ; Side effect: the divisor + ; latch access bit is cleared + ;----------------------------- + mov cx,init_rate ;set data rate + SETBAUD_CX ;macro from PCSERIAL.INC + ;----------------------------- + ; Set data format: + ; 8 data bits, + ; 1 stop bit, + ; no parity + ; Side effect: the divisor + ; latch access bit is cleared + ;----------------------------- + mov al,UART_LCR_8+UART_LCR_S1+UART_LCR_NP + SETFORMAT_AL + + + ;----------------------------- + ; Enable UART interrupt sources + ;----------------------------- + ASSERT_IER UART_IER_ALL + ;----------------------------- + ; Enable UART interrupts, RTS + ;----------------------------- + ASSERT_MCR UART_MCR_IRQ+UART_MCR_RTS + ;----------------------------- + ; Clear UART interrupt sources + ;----------------------------- + in al,dx ;clear receiver interrupt (read inputs) + in al,dx + +;; mov al,IDLE_CHAR ; clear transmit interrupt +;; out dx,al +;; out dx,al + + add dx,UART_MSR ;read modem status reg to clear IRQ + in al,dx ;discard the result + sub dx,UART_MSR + + add dx,UART_LSR ;read line status reg to clear IRQ + in al,dx ;read value + mov pcspakLSR,al ;(save for diagnostics) + sub dx,UART_LSR + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ; Diagnostics values + ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + add dx,UART_IER + in al,dx + mov pcspakIER,al + sub dx,UART_IER + + PIC_IMR_TO_AL + mov postIMR,al + PIC_ISR_TO_AL + mov postISR,al + PIC_IRR_TO_AL + mov postIRR,al + ;-------------------------------------------------------------- + ; Mark as 'enabled' + ;-------------------------------------------------------------- + mov enabled[esi],1 + +allocFailed: + ;-------------------------------------------------------------- + ; Reenable the old interrupt state and return + ;-------------------------------------------------------------- + DPMI_RESTORE_PREV_INT ;pops ax! + IRQ_WATCH 1 + + mov eax,return_status + +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKTerm() +; Destructor for serial packet interface +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; (nothing) +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKTerm + + ARG_DPTR term_this + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Disable interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + IRQ_WATCH 0 + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,term_this + mov eax,esi ;is it NULL? + or eax,eax + jz short skipRestore ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Turn off RTS and interrupts + ;-------------------------------------------------------------- + mov dx,portBase[esi] + RETRACT_MCR UART_MCR_IRQ+UART_MCR_RTS + + ; NOTE: from this point on, interrupts CANNOT occur from the UART. + + ;-------------------------------------------------------------- + ; If improperly allocated, skip 'release' + ;-------------------------------------------------------------- + mov eax,intDataPtr[esi] ;get pointer to IRQ data + or eax,eax + jz short skipRestore ;null pointer, skip release + + mov edi,eax ;place pointer in edi + ;-------------------------------------------------------------- + ; Mark IRQDATA record as unused + ;-------------------------------------------------------------- + mov irqPort[edi],0 + ;-------------------------------------------------------------- + ; Restore the old PROTECTED MODE interrupt vector + ;-------------------------------------------------------------- + mov bl,irqNum[edi] ;bl has interrupt number + mov cx,irqOldSelector[edi] ;cx:edx has selector:offset + mov edx,irqOldOffset[edi] + DPMI_SET_PROT_VECTOR + ;-------------------------------------------------------------- + ; Disable PIC channel + ;-------------------------------------------------------------- + mov bl,irqPICbit[edi] ;get our PIC bit + RETRACT_PIC bl ;no, turn it off +skipRestore: + ;-------------------------------------------------------------- + ; Reenable the old interrupt state and return + ;-------------------------------------------------------------- + DPMI_RESTORE_PREV_INT ;pops ax! + IRQ_WATCH 1 + +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKReceive() +; Returns packet if available +;------------------------------------------------------------------------- +; Enter: +; rp_this = pointer to object +; Byte *destPtr = pointer to 128-byte destination buffer +;------------------------------------------------------------------------- +; Returns: +; int packetSize (or zero if no packet available) +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKReceive + + ARG_DPTR rp_this + ARG_DPTR rp_dest + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,rp_this + mov eax,esi ;is it NULL? + or eax,eax + jz spr_done ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Skip if disabled + ;-------------------------------------------------------------- + mov al,enabled[esi] ;if disabled, don't even try + or al,al + jnz short recvOK + + xor eax,eax + jmp spr_done +recvOK: + ;-------------------------------------------------------------- + ; Check character count: non-zero indicates entire packet + ;-------------------------------------------------------------- + xor eax,eax ;clear top of eax + mov ax,rxBuf.count[esi] ;get # of characters in ax + or ax,ax ;empty? + jz spr_done ;yes, return zero +;;; ;-------------------------------------------------------------- +;;; ; Disable interrupts +;;; ;-------------------------------------------------------------- +;;; DPMI_DISABLE_INT +;;; IRQ_WATCH 0 + ;-------------------------------------------------------------- + ; Get buffer length + ;-------------------------------------------------------------- + mov edi,rp_dest ;get pointer to destination + cld ;make sure direction is ok + + xor eax,eax ;clear top of ax + COM_GET_AL rxBuf ;get character into al + ;-------------------------------------------------------------- + ; Verify first char is a valid command character + ;-------------------------------------------------------------- + test al,080h ;1st character = command (high bit set)? + jnz short sprOk + + DISABLE_AND_DIE 9 + xor eax,eax + jmp short spr_done +sprOk: + stosb ;save it + and al,07Fh ;remove MSB + mov ebx,rxTablePtr[esi] ;point bx at length table + xlatb ;translate into length + xor ecx,ecx ;set ecx from al + mov cl,al + mov edx,ecx ;save in edx + inc edx ;return at least one character + ;-------------------------------------------------------------- + ; Transfer data from buffer + ;-------------------------------------------------------------- + or cx,cx ;if no additional characters, skip + jz short spr_skip +spr_loop: + COM_GET_AL rxBuf ;get character into al + stosb ;save in buffer + loop spr_loop +spr_skip: + COM_ACCEPT_OUT rxBuf ;accept all 'taken' characters +;;; ;-------------------------------------------------------------- +;;; ; Reenable the old interrupt state +;;; ;-------------------------------------------------------------- +;;; DPMI_RESTORE_PREV_INT ;pops ax! +;;; IRQ_WATCH 1 + + mov eax,edx ;place count in eax + ;-------------------------------------------------------------- + ; Return count in eax + ;-------------------------------------------------------------- +spr_done: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKSend() +; Transmits packet +;------------------------------------------------------------------------- +; Enter: +; sp_this = pointer to object +; Byte *sp_src = pointer to (up to) 128-byte source buffer +;------------------------------------------------------------------------- +; Returns: +; void +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKSend + + ARG_DPTR sp_this + ARG_DPTR sp_src + + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,sp_this + mov eax,esi ;is it NULL? + or eax,eax + jz sendSkip ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Wait for sufficient room + ;-------------------------------------------------------------- + mov al,enabled[esi] ;if disabled, don't even try + or al,al + jz sendSkip + +;;; SET_LPT 5 + + mov edi,sp_src ;get pointer to source + mov al,[edi] ;get the command byte + and al,07Fh ;remove MSB + mov ebx,txTablePtr[esi] ;set ebx to point to length table + xlatb ;get the length in al + xor ecx,ecx ;move al to ecx + mov cl,al + inc cx ;add one for command byte +spt_wait: + COM_SPACE_IN txBuf,ax ;get buffer 'in' space + cmp ax,cx ;enough room? + jae spt_space ;yes, continue + + DISABLE_AND_DIE 0 + jmp short spt_wait + +spt_space: + ;-------------------------------------------------------------- + ; Disable interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + IRQ_WATCH 0 + ;-------------------------------------------------------------- + ; Copy data into tx buffer + ;-------------------------------------------------------------- +spt_loop: + mov al,[edi] ;get the byte + inc edi ;increment the source pointer + COM_PUT_AL txBuf ;place it in the buffer + loop spt_loop + + COM_ACCEPT_IN txBuf ;accept all 'placed' characters + mov dx,portBase[esi] ;set dx to port base address + call StartSending ;attempt to start tx interrupt + ;-------------------------------------------------------------- + ; Reenable the old interrupt state + ;-------------------------------------------------------------- + DPMI_RESTORE_PREV_INT ;pops ax! + IRQ_WATCH 1 + +;;; CLEAR_LPT 5 + +sendSkip: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKActive() +; Returns transmitter 'active' state (=0 when all transmission is done). +;------------------------------------------------------------------------- +; Enter: +; pa_this = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int errors +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKActive + + ARG_DPTR pa_this + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,pa_this + mov eax,esi ;is it NULL? + or eax,eax + jz short actNULL ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Get 'active' status + ; + ; The LSR register has two bits reflecting the + ; transmitter state: + ; THR = transmit holding register (1=empty) + ; TSR = transmit serial register (1=empty) + ; + ; The transmission is completely finished when both of these + ; bits are high. + ;-------------------------------------------------------------- + xor eax,eax ;clear top of eax + + mov dx,portBase[esi] ;get the port base + add dx,UART_LSR ;get LSR + in al,dx + ;;sub dx,UART_LSR ;we usually subtract, no need here + + and al,UART_LSR_THR+UART_LSR_TSR ; remove all but THR,TSR + xor al,UART_LSR_THR+UART_LSR_TSR ; invert the bits +actNULL: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKErrors() +; Returns error bits: zero indicates no errors. +; The error code is cleared by this call as well. +;------------------------------------------------------------------------- +; Enter: +; pe_this = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int errors +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKErrors + + ARG_DPTR pe_this + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,pe_this + mov eax,esi ;is it NULL? + or eax,eax + jz short errNULL ;OHMIGOSH!! EXIT!!! + ;-------------------------------------------------------------- + ; Get, clear error word + ;-------------------------------------------------------------- + mov ax,ErrorValue[esi] ;init error? + and ax,ERR_INIT + jnz short haveInitError ;yes, don't clear it + + xor ax,ax ;no, go ahead and clear it + xchg ax,ErrorValue[esi] +haveInitError: + and eax,0FFFFh ;make sure top of eax is clear +errNULL: +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKIRQState() +; Returns IRQ state +;------------------------------------------------------------------------- +; Enter: +; (void) +;------------------------------------------------------------------------- +; Returns: +; int state +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKIRQState + + BUILD_STACK_FRAME + + DPMI_INT_STATE + and eax,0FFh ;make sure top of eax is clear +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKTestInstance() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int True +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKTestInstance + mov eax,1 + ret +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKIsSignatureBad() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int False +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKIsSignatureBad + mov eax,0 + ret +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKReceiveCount() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int number of items in receive queue +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKReceiveCount + + ARG_DPTR prc_this + BUILD_STACK_FRAME + + mov esi,prc_this + xor eax,eax + mov ax,rxBuf.count[esi] +END_C_PROC + +;------------------------------------------------------------------------- +; PCSPAKTransmitCount() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +;------------------------------------------------------------------------- +; Returns: +; int number of items in transmit queue +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKTransmitCount + + ARG_DPTR ptc_this + BUILD_STACK_FRAME + + mov esi,ptc_this + xor eax,eax + mov ax,txBuf.count[esi] +END_C_PROC + + +;------------------------------------------------------------------------- +; PCSPAKSetDTR() +;------------------------------------------------------------------------- +; Enter: +; (this) = pointer to object +; on = zero to retract DTR, non-zero to assert DTR +;------------------------------------------------------------------------- +; Returns: +; int number of items in transmit queue +;------------------------------------------------------------------------- +BEGIN_C_PROC PCSPAKSetDTR + + ARG_DPTR sdtr_this + ARG_DWORD sdtr_on + BUILD_STACK_FRAME + ;-------------------------------------------------------------- + ; Get "this" pointer + ;-------------------------------------------------------------- + mov esi,sdtr_this + mov eax,esi ;is it NULL? + or eax,eax + jz short sdtrExit ;OHMIGOSH!! EXIT!!! + + mov dx,portBase[esi] ;get the port base + ;-------------------------------------------------------------- + ; Get "on" + ;-------------------------------------------------------------- + cmp sdtr_on,0 + je sdtrOff + ;-------------------------------------------------------------- + ; Assert DTR + ;-------------------------------------------------------------- + ASSERT_MCR UART_MCR_DTR + jmp short sdtrExit + ;-------------------------------------------------------------- + ; Retract DTR + ;-------------------------------------------------------------- +sdtrOff: + RETRACT_MCR UART_MCR_DTR +sdtrExit: + +END_C_PROC + +;------------------------------------------------------------------------- +; StartSending - attempt to start transmitter (if allowed) +; ...called from the receive interrupt routine and PCSPAK::sendPacket. +;------------------------------------------------------------------------- +; Enter: +; ESI = pointer to PCSPAK structure +; DX = UART base address +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +; Side effects: +; Modifies register AL +;------------------------------------------------------------------------- +StartSending PROC NOLANGUAGE NEAR + + add dx,UART_LSR ;get THR bit from LSR + in al,dx + sub dx,UART_LSR + + test al,UART_LSR_THR ;is there anything in the holding reg? + jz sptNoKick ;yes, interrupt will occur later + + SAVE_EVENT TX_EVENT_KICK + call SendChar ;restart transmitter +sptNoKick: + ret +StartSending ENDP + +;------------------------------------------------------------------------- +; SendChar - send character through UART +; ...called from the interrupt routine and PCSPAK::sendCommand. +;------------------------------------------------------------------------- +; Enter: +; ESI = pointer to PCSPAK structure +; DX = UART base address +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +; Side effects: +; registers EAX, EBX, ECX modified +;------------------------------------------------------------------------- +SendChar PROC NOLANGUAGE NEAR +;;; SET_LPT 6 + + ;-------------------------------------------------------------- + ; Send reply character if one is waiting + ;-------------------------------------------------------------- + cmp txReply[esi],0 ;"reply" character waiting? + je noReply ;no, continue + + xor al,al ;prepare for exchange + xchg al,txReply[esi] ;get and clear the "reply" character + out dx,al ;yes, send the reply character + SAVE_TX + jmp sendDone ;done for now. +noReply: + ;-------------------------------------------------------------- + ; Enter the appropriate state handler + ;-------------------------------------------------------------- + mov al,txState[esi] ;get the transmit state + + cmp al,TX_IDLE_STATE ;idle state? + je short txIdleState ;yes, go to it + + cmp al,TX_BODY_STATE ;"body" state? + je txBodyState ;yes, go to it + + cmp al,TX_WAIT_STATE ;"wait" state? + je txWaitState ;yes, go to it + + cmp al,TX_RESTART_STATE ;restart state? + je short txRestartState ;yes, go to it + + DISABLE_AND_DIE 1 + jmp txWaitState ;must be "wait" state + ;-------------------------------------------------------------- + ; Transmitter idle state + ;-------------------------------------------------------------- +txIdleState: + cmp txHoldOff[esi],0 ;If transmitter 'held off', do nothing + jne short txIsIdle + + cmp txBuf.count[esi],0 ;input buffer available? + jne short txIdleAvail ;yes, send something +txIsIdle: + SAVE_EVENT TX_EVENT_EMPTY ;nothing to send, just return + jmp sendDone + +txIdleAvail: + ;--------------------------- + ; Buffer ready, start + ;--------------------------- + mov txResetCount[esi],TXMAXRESET ;set the 'reset' counter + mov txErrorCount[esi],TXMAXERROR ;set the 'error' counter + + ;...deliberately fall through into 'txRestartState' + + ;-------------------------------------------------------------- + ; Transmitter restart state + ;-------------------------------------------------------------- +txRestartState: + COM_GET_AL txBuf ;assumes esi points to object + + cmp al,07Fh ;is it a command? + jbe short txRestartBad ;no, discard it + + mov ah,al ;transfer to ah + and ah,07Fh ;remove MSB + cmp ah,txMaximum[esi] ;legitimate command? + jb short txRestartOk ;yes + +txRestartBad: + DISABLE_AND_DIE 2 + COM_ACCEPT_OUT txBuf ;eat the character + mov txState[esi],TX_IDLE_STATE ;move to the "idle" state + jmp sendDone + +txRestartOk: + out dx,al ;transmit the command character + mov txChecksum[esi],al ;begin a new checksum count + SAVE_TX + + mov al,ah ;move AND'ed value back to al + mov ebx,txTablePtr[esi] ;get length table pointer into ebx + xlatb ;look up length + inc al ;include the command byte + mov txCount[esi],al ;save the length + + mov txState[esi],TX_BODY_STATE ;move to the "body" state + jmp sendDone + + ;-------------------------------------------------------------- + ; Transmitter "body" state + ; Send message body, then checksum (unless interrupted by ACK/NAK) + ;-------------------------------------------------------------- +txBodyState: + ;--------------------------- + ; Interrupted by ACK/NAK? + ;--------------------------- + cmp rxFlags[esi],0 ;flag set? + je txBodySend ;no, send normal body + + COM_RESTORE_OUT txBuf ;interrupted, reset 'out' pointer + + mov al,rxFlags[esi] ;get flags + mov rxFlags[esi],0 ;clear them + + test al,RX_ACK_BIT ;was it an ACK? + jne short txBodyNak ;no + or ErrorValue[esi],TX_EARLY_ERR ;yes, set error flag +txBodyNak: + SAVE_EVENT TX_EVENT_EARLY + ;--------------------------- + ; Restart or die + ;--------------------------- + dec txResetCount[esi] ;check the restart count + jl short txBodyGiveUp ;if too many errors, give up + ;--------------------------- + ; Attempt restart + ;--------------------------- + mov al,RESTART_CHAR ;no, send restart character + out dx,al + SAVE_TX + + mov txState[esi],TX_RESTART_STATE ;move to the "restart" state + jmp sendDone + ;--------------------------- + ; Too many errors, die! + ;--------------------------- +txBodyGiveUp: + SAVE_EVENT TX_EVENT_ABANDON + or ErrorValue[esi],TX_ABANDON ;set error flag + mov ebx,txTablePtr[esi] ;get pointer to length table + COM_EAT_PACKET txBuf ;discard current packet + jmp txIdleState ;start another packet + ;--------------------------- + ; Send body or checksum + ;--------------------------- +txBodySend: + dec txCount[esi] ;is buffer done? + jle txBodyCheck ;yes, send checksum + ;--------------------------- + ; Send a body character + ;--------------------------- + COM_GET_AL txBuf ;get a character from the buffer + + cmp al,07Fh ;legitimate body char? + jbe txBodyOk ;yes, continue + DISABLE_AND_DIE 3 + and al,07Fh ;prevent bad data from becoming command +txBodyOk: + out dx,al ;send it + add txChecksum[esi],al ;add to the checksum + SAVE_TX + jmp sendDone + ;--------------------------- + ; End of body, send checksum + ;--------------------------- +txBodyCheck: + mov al,txChecksum[esi] ;get the checksum + and al,07Fh ;limit it + out dx,al ;send it + SAVE_TX + SAVE_EVENT TX_EVENT_DONE + ;--------------------------- + ; prepare for "wait" state + ;--------------------------- + mov txIdleCount[esi],TXMAXIDLE ;set the idle counter + mov txState[esi],TX_WAIT_STATE ;move to the "wait" state + jmp sendDone + + ;-------------------------------------------------------------- + ; Transmitter "wait" state + ; Waits for reply from other end + ;-------------------------------------------------------------- +txWaitState: + xor al,al ;prepare to exchange flags + xchg al,rxFlags[esi] ;get flags, also clear them + or al,al ;flags clear? + jz txWaitMore ;yes, keep waiting + + test al,RX_ACK_BIT ;ACK? + jz short txWaitNak ;no, process NAK + ;--------------------------- + ; ACK, buffer received OK + ;--------------------------- + SAVE_EVENT TX_EVENT_ACK + COM_ACCEPT_OUT txBuf ;yes, good transmission. Discard packet. + mov txState[esi],TX_IDLE_STATE ;move to the "idle" state + jmp txIdleState ;start another buffer + ;--------------------------- + ; NAK! + ;--------------------------- +txWaitNak: + SAVE_EVENT TX_EVENT_ACK + or ErrorValue[esi],TX_NAK ;set error flag + COM_RESTORE_OUT txBuf ;restore output pointers + + dec txErrorCount[esi] ;check the error count + jl txWaitGiveUp ;if too many errors, give up + jmp txRestartState ;no, resend it + ;--------------------------- + ; Keep waiting + ;--------------------------- +txWaitMore: + dec txIdleCount[esi] ;have we waited too long? + jl short txWaitDone ;yes, attempt to restart + + mov al,IDLE_CHAR ;no, send idle character + out dx,al + SAVE_TX + jmp sendDone + ;--------------------------- + ; Attempt restart + ;--------------------------- +txWaitDone: + SAVE_EVENT TX_EVENT_RESTART + or ErrorValue[esi],TX_RESTART ;set error flag + COM_RESTORE_OUT txBuf ;restore output pointers + + dec txResetCount[esi] ;too many restarts? + jl short txWaitGiveUp ;yes, abandon buffer + + mov al,RESTART_CHAR ;no, send restart character + out dx,al + SAVE_TX + + mov txIdleCount[esi],TXMAXIDLE ;reset the idle counter + mov txState[esi],TX_RESTART_STATE ;move to the "idle" state + jmp short sendDone + ;--------------------------- + ; Give up + ;--------------------------- +txWaitGiveUp: + SAVE_EVENT TX_EVENT_ABANDON + or ErrorValue[esi],TX_ABANDON ;set error flag + mov ebx,txTablePtr[esi] ;get pointer to length table + COM_EAT_PACKET txBuf ;discard the packet + mov txState[esi],TX_IDLE_STATE ;move to the "idle" state + jmp txIdleState ;start another packet + +sendDone: +;;; CLEAR_LPT 6 + + ret + +SendChar ENDP + +;------------------------------------------------------------------------- +; RecvChar - receive character from UART +;------------------------------------------------------------------------- +; Enter: +; ESI = pointer to PCSPAK structure +; DX = UART base address +; AL = character +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +; Side effects: +; registers EAX, EBX, ECX modified +;------------------------------------------------------------------------- +RecvChar PROC NOLANGUAGE NEAR + SAVE_RX + ;-------------------------------------------------------------- + ; Process universal special characters: ACK, NAK, IDLE + ;-------------------------------------------------------------- + test al,080h ;MSB set? + jz short rcNotSpecial ;no, can't be special character + ;------------------------------ + ; IDLE + ;------------------------------ + cmp al,IDLE_CHAR ;IDLE character? + jne short rcNotIdle ;no + jmp recvDone ;yes, ignore it +rcNotIdle: + ;------------------------------ + ; ACK + ;------------------------------ + cmp al,ACK_CHAR ;ACK character? + jne short rcNotAck ;no + or rxFlags[esi],RX_ACK_BIT ;yes, flag for transmitter + jmp recvDone +rcNotAck: + ;------------------------------ + ; NAK + ;------------------------------ + cmp al,NAK_CHAR ;NAK character? + jne short rcNotNak ;no + or rxFlags[esi],RX_NAK_BIT ;yes, flag for transmitter + jmp recvDone +rcNotNak: +rcNotSpecial: + ;-------------------------------------------------------------- + ; Process state-dependent characters + ;-------------------------------------------------------------- + cmp rxState[esi],0 ;test the state + jne rxActive ;non-zero, so active + ;-------------------------------------------------------------- + ; Receiver "idle" state + ; Wait for command character + ;-------------------------------------------------------------- + test al,080h ;is it a control character? + jnz short rxIdleSpecial ;yes, process it + + or ErrorValue[esi],RX_SEQ_ERR ;Not expecting data, so error. + jmp recvDone + +rxIdleSpecial: + cmp al,RESTART_CHAR ;restart? + je recvDone ;yes, discard it + + COM_SPACE_IN rxBuf,bx ;get remaining space + or bx,bx ;zero? + jnz short rxIdleSpace ;no, continue + + SAVE_EVENT RX_EVENT_FULL + DISABLE_AND_DIE 4 + or ErrorValue[esi],RX_COM_ERR ;error. Set flag. + jmp recvDone + +rxIdleSpace: + mov ah,al ;move to ah for testing + and ah,07Fh ;remove MSB + cmp ah,rxMaximum[esi] ;legitimate command? + jb short rxIdleOk ;yes, continue + + SAVE_EVENT RX_EVENT_NOT_CMD + DISABLE_AND_DIE 5 + or ErrorValue[esi],RX_COM_ERR ;no. + jmp recvDone +rxIdleOk: + COM_PUT_AL rxBuf ;save command character in buffer + mov rxChecksum[esi],al ;start a new receive checksum + + mov al,ah ;put ah back into al + mov ebx,rxTablePtr[esi] ;get length table pointer into ebx + xlatb ;look up length + inc al ;include the command byte + mov rxCount[esi],al ;save the length + + mov rxState[esi],RX_ACTIVE_STATE ;change to "active" state + jmp recvDone + + ;-------------------------------------------------------------- + ; Receiver "active" state + ; Place N characters into buffer, test checksum, and reply + ;-------------------------------------------------------------- +rxActive: + test al,080h ;control character? + jz short rxActiveData ;no, therefore data + + or ErrorValue[esi],RX_SEQ_ERR ;yes, error. Set error flag + COM_RESTORE_IN rxBuf ;Discard received data + ;------------------------------ + ; Process control char + ;------------------------------ + cmp al,RESTART_CHAR ;restart character? + je rxActiveAbandon ;yes, abandon received data + + SAVE_EVENT RX_EVENT_NAK + mov al,NAK_CHAR ;error, tell transmitter to send NAK + jmp rxActiveReply + ;------------------------------ + ; Process data + ;------------------------------ +rxActiveData: + dec rxCount[esi] ;check the receive count + jle rxActiveCheck ;if end of message, process checksum + ;------------------------------ + ; Enough space in buffer? + ;------------------------------ + COM_SPACE_IN rxBuf,bx ;get remaining space + + or bx,bx ;zero? + jnz short rxActiveSpace ;no, continue + + SAVE_EVENT RX_EVENT_FULLBODY + DISABLE_AND_DIE 6 ;crash hard (if enabled) + or ErrorValue[esi],RX_COM_ERR ;error. Set flag. + COM_RESTORE_IN rxBuf ;Discard received data + jmp rxActiveAbandon ;give up on packet + +rxActiveSpace: + ;------------------------------ + ; Save data in buffer + ;------------------------------ + add rxChecksum[esi],al ;update the checksum + COM_PUT_AL rxBuf ;save the character + jmp recvDone + ;------------------------------ + ; Test checksum + ;------------------------------ +rxActiveCheck: + mov bl,rxChecksum[esi] ;get the checksum + and bl,07Fh ;remove MSB + cmp al,bl ;checksum OK? + je short rxActiveOk ;yes! + ;------------------------------ + ; Buffer error + ;------------------------------ + SAVE_EVENT RX_EVENT_CKSMERR + or ErrorValue[esi],RX_BAD_CHECKSUM ;error. Set flag. + COM_RESTORE_IN rxBuf ;Discard received data + mov al,NAK_CHAR ;tell transmitter to send NAK + jmp short rxActiveReply + ;------------------------------ + ; Buffer OK + ;------------------------------ +rxActiveOk: + SAVE_EVENT RX_EVENT_OK + COM_ACCEPT_IN rxBuf ;accept the received data + mov al,ACK_CHAR ;tell transmitter to send ACK + +rxActiveReply: + mov txReply[esi],al + call StartSending ;restart transmitter if needed + ;------------------------------ + ; Return to inactive state + ;------------------------------ +rxActiveAbandon: + mov rxState[esi],RX_IDLE_STATE +recvDone: + ret +RecvChar ENDP + +;------------------------------------------------------------------------- +; Interrupt handlers +;------------------------------------------------------------------------- +IntHandler PROC NOLANGUAGE NEAR + ASSUME cs:_TEXT + +IntCom1: + pushad + mov edi,OFFSET irq_com1 ;point EDI at IRQDATA structure + call IntMain + popad + iret + ;jmp cs:fword ptr [irq_com1.irqOldOffset] +IntCom2: + pushad + mov edi,OFFSET irq_com2 ;point EDI at IRQDATA structure + call IntMain + popad + iret + ;jmp cs:fword ptr [irq_com2.irqOldOffset] +IntCom3: + pushad + mov edi,OFFSET irq_com3 ;point EDI at IRQDATA structure + call IntMain + popad + iret + ;jmp cs:fword ptr [irq_com3.irqOldOffset] +IntCom4: + pushad + mov edi,OFFSET irq_com4 ;point EDI at IRQDATA structure + call IntMain + popad + iret + ;jmp cs:fword ptr [irq_com4.irqOldOffset] + + ;-------------------------------------------------------------- + ; Serial interrupt handler main body + ;-------------------------------------------------------------- +IntMain: + push ds ;save registers + push es + mov ds,cs:[data_selector] ;get our DS + ASSUME ds:_DATA + + IRQ_WATCH_ENTRY +;;; SPKR_SET ;********************************************* + + SAVE_EVENT IRQ_EVENT + ;-------------------------------------------------------------- + ; Get pointer to PCSPAK structure, UART base address + ;-------------------------------------------------------------- + mov esi,irqThis[edi] + mov dx,irqPort[edi] + ;-------------------------------------------------------------- + ; Get status in al + ;-------------------------------------------------------------- +procLoop: + add dx,UART_IIR ;point to interrupt ident reg + in al,dx ;get interrupt source ID + sub dx,UART_IIR ;restore dx + ;-------------------------------------------------------------- + ; Receive character + ;-------------------------------------------------------------- + cmp al,UART_IIR_RDR ;receiver ready? + jne short procNoRx ;no, skip it + + in al,dx ;get character + call RecvChar ;process it + jmp short procLoop +procNoRx: + ;-------------------------------------------------------------- + ; Send character + ;-------------------------------------------------------------- + cmp al,UART_IIR_THR ;transmitter ready? + jne short procNoTx ;no, skip it + + call SendChar ;send a character if available + jmp short procLoop +procNoTx: + ;-------------------------------------------------------------- + ; Process modem status register change + ; + ; We currently ignore it. We could someday implement + ; DTR/CTS/... flow control here if we desire. + ;-------------------------------------------------------------- + cmp al,UART_IIR_MSR ;MSR change? + jne short procNoMSR ;no, skip it + + SAVE_EVENT IRQ_EVENT_MSR + add dx,UART_MSR ;read modem status reg to clear IRQ + in al,dx ;discard the result + sub dx,UART_MSR + jmp procLoop +procNoMSR: + ;-------------------------------------------------------------- + ; Process line status register change (error or break) + ;-------------------------------------------------------------- + cmp al,UART_IIR_LSR ;LSR change? + jne short procNoLSR ;no, skip it + + SAVE_EVENT IRQ_EVENT_LSR + add dx,UART_LSR ;read line status reg to clear IRQ + in al,dx ;read value + sub dx,UART_LSR + + and ax,UART_LSR_ERRS ;remove non-error bits + or ErrorValue[esi],ax ;OR with current error state + jmp procLoop +procNoLSR: + ;-------------------------------------------------------------- + ; Check for UART done + ;-------------------------------------------------------------- + cmp al,001h ;if LSB is set, no interrupt + je short procDone + SAVE_EVENT IRQ_EVENT_BOGUS + DISABLE_AND_DIE 7 ;weird state, flag error +procDone: + ;-------------------------------------------------------------- + ; PIC port write + ; (allows future interrupts to occur) + ;-------------------------------------------------------------- + PIC_RESET_MASTER + ;-------------------------------------------------------------- + ; Restore registers, return from SUBROUTINE (not interrupt!) + ;-------------------------------------------------------------- + IRQ_WATCH_EXIT +;;; SPKR_RESET ;********************************************* + + pop es + pop ds + ret + +IntHandler ENDP + +END_CODE + + END diff --git a/CODE/RP/MUNGA_L4/SOSMAWE.C b/CODE/RP/MUNGA_L4/SOSMAWE.C new file mode 100644 index 0000000..89d73ab --- /dev/null +++ b/CODE/RP/MUNGA_L4/SOSMAWE.C @@ -0,0 +1,458 @@ +/**************************************************************************** + + File : sosmawe.c + + Purpose : Module to handle AWE32 .SBK file uploads + + Date : 1-20-95 + + Programmer(s) : Don Fowler + + Last Updated : 1-29-95 + +**************************************************************************** + Copyright(c) 1992,1995 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sosm.h" +#include "sosmawe.h" + +// maximum number of .SBK files that can be set on the chip +#define _MAX_SBKS 0x10 + +// offset into slot list for .SBK files to start +#define _SBK_SLOT_OFFSET 0x01 + +// size of buffer needed to read in a chunk of .SBK file +#define _READ_BUFFER_SIZE 0x2000 + +// pointer to preset data for awe32 +#ifdef __BORLANDC__ +PSTR _lpSOSMIDIAwe32PresetBuffer[ _SOS_MIDI_MAX_DRIVERS ][ _MAX_SBKS ] = { +#else +LPSTR _lpSOSMIDIAwe32PresetBuffer[ _SOS_MIDI_MAX_DRIVERS ][ _MAX_SBKS ] = { +#endif + + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL } + + }; + +// index into list of presets to the currently available slot, +// start the index at 0 to leave slot 0 open for general midi +// rom on the AWE32 +WORD _wSOSMIDIAwe32PresetIndex[ _SOS_MIDI_MAX_DRIVERS ] = { + + _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET, + _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET + }; + +/*************************************************************************** + +Function : WORD sosMIDIAWE32SetSBKFile + +Parameters : WORD hDriver + Handle of SOS driver to set SBK file on. + PSTR szFileName + Name of .SBK file to set. + +Returns : -1 if error; otherwise, slot that the .SBK file was + assigned to on the AWE32. + +Description : Stream a .SBK file onto the awe32 and return the slot + streamed to. + +****************************************************************************/ + +#pragma warn -def +#pragma warn -sus +#pragma warn -pia + +WORD sosMIDIAWE32SetSBKFile( WORD hDriver, const char *szFileName ) +{ + WORD wIndex; + WORD hFile; + WORD wReadSize; + PSTR pDataPtr; +#ifdef __BORLANDC__ + SFAR lpTemp; +#endif + + // attempt to find a slot to use for the .SBK file + if( _wSOSMIDIAwe32PresetIndex[ hDriver ] == ( _MAX_SBKS - 1 ) ) + return( -1 ); + + // attempt to open the sbk file + if( ( hFile = open( ( const char * )szFileName, O_RDONLY | O_BINARY ) ) == -1 ) + return( -2 ); + + // attempt to allocate a buffer to use for transfer + if( ( pDataPtr = ( PSTR )malloc( _READ_BUFFER_SIZE ) ) == NULL ) + { + // close the file + close( hFile ); + + // return an error + return( -3 ); + } + + // open the awe32 stream +#ifdef __BORLANDC__ + if( ( wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 5 ], + lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 5 ]( _NULL, + _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // free the previously allocated memory + free( pDataPtr ); + + // close the file + close( hFile ); + + // return error + return( -4 ); + } + + // read in a chunk of data from the file + if( read( hFile, pDataPtr, wReadSize ) == -1 ) + return( -5 ); + + // get the sample data seek location +#ifdef __BORLANDC__ + lpTemp.sel = getDS(); + lpTemp.off = pDataPtr; + if( ( wIndex = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 8 ], + lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wIndex = _lpSOSMIDIDrvFunction[ hDriver ][ 8 ]( ( LPSTR )pDataPtr, + _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // free the previously allocated memory + free( pDataPtr ); + + // close the file + close( hFile ); + + // return error + return( -6 ); + } + + // seek the file to the sample location + if( lseek( hFile, wIndex, SEEK_SET ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -7 ); + } + + // send chunks of data to the driver + do + { + // read in a chunk of data from the file + if( read( hFile, pDataPtr, wReadSize ) == -1 ) + return( -8 ); + + // send the data to the driver +#ifdef __BORLANDC__ + lpTemp.sel = getDS(); + lpTemp.off = pDataPtr; + if( ( wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ] + [ 6 ], lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 6 ]( + ( LPSTR )pDataPtr, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // close the file + close( hFile ); + + // free the memory + free( pDataPtr ); + + // return an error + return( -9 ); + } + } while( wReadSize ); + + // free the temporary memory buffer + free( pDataPtr ); + + // get the preset data size +#ifdef __BORLANDC__ + wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 7 ], + lpTemp, 0x00, 0x00 ); +#else + wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 7 ]( _NULL, 0x00, 0x00 ); +#endif + + // get the preset location in the file +#ifdef __BORLANDC__ + lpTemp.sel = getDS(); + lpTemp.off = &wIndex; + sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ], lpTemp, + 0x00, 0x00 ); +#else + _lpSOSMIDIDrvFunction[ hDriver ][ 9 ]( ( LPSTR )&wIndex, 0x00, 0x00 ); +#endif + + // allocate the memory for the preset information +#ifdef __BORLANDC__ + if( !( _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] = + ( PSTR )malloc( wReadSize ) ) ) +#else + if( !( _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] = + ( LPSTR )malloc( wReadSize ) ) ) +#endif + { + // close the file + close( hFile ); + + // return an error + return( -10 ); + } + + // seek the file to the preset location + if( lseek( hFile, wIndex, SEEK_SET ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -11 ); + } + + // read in the preset information + if( read( hFile, ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ + _wSOSMIDIAwe32PresetIndex[ hDriver ] ], wReadSize ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -12 ); + } + + // send the preset information to the driver +#ifdef __BORLANDC__ + lpTemp.sel = getDS(); + lpTemp.off = _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ]; + if( ( sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 10 ], + lpTemp, 0x00, 0x00 ) ) == -1 ) +#else + if( ( _lpSOSMIDIDrvFunction[ hDriver ][ 10 ]( ( LPSTR ) + _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ], 0x00, 0x00 ) ) == -1 ) +#endif + { + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // close the file + close( hFile ); + + // return an error + return( -13 ); + } + + // close the SBK file + close( hFile ); + + // increment the preset buffer index to the next available slot + _wSOSMIDIAwe32PresetIndex[ hDriver ]++; + + // return no error + return( _wSOSMIDIAwe32PresetIndex[ hDriver ] ); +} + +#pragma warn .def +#pragma warn .sus +#pragma warn .pia + +/*************************************************************************** + +Function : WORD sosMIDIAWE32ReleaseAllSBKFiles + +Parameters : WORD hDriver + Handle of SOS driver to release .SBK files from + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Release all of the memory associated to the .SBK files + uploaded to the awe32. + +****************************************************************************/ + +#pragma warn -def + +WORD sosMIDIAWE32ReleaseSBKFiles( WORD hDriver ) +{ + WORD wIndex; +#ifdef __BORLANDC__ + SFAR lpTemp; +#endif + + // call the driver to release all of the .SBK files +#ifdef __BORLANDC__ + if( sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ], lpTemp, + 0x01, 0x00 ) == -1 ) +#else + if( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ]( ( LPSTR )_NULL, 0x01, 0x00 ) + == -1 ) +#endif + return( -1 ); + + // free the memory allocated for the awe32 preset information + for( wIndex = _SBK_SLOT_OFFSET; wIndex < _wSOSMIDIAwe32PresetIndex[ hDriver ]; + wIndex++ ) + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ wIndex ] ); + + // reset the available slot index + _wSOSMIDIAwe32PresetIndex[ hDriver ] = _SBK_SLOT_OFFSET; + + // return no error + return( _ERR_NO_ERROR ); +} + +#pragma warn .def + +/*************************************************************************** + +Function : WORD sosMIDIAWE32NoteOn + +Parameters : WORD hDriver + Handle of SOS driver + WORD wSlot + .SBK file slot to associate patch to + WORD wChannel + Channel to use + WORD wPatch + Patch to use + WORD wNote + MIDI relative pitch to use + WORD wVelocity + Velocity to use + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Turn a note on + +****************************************************************************/ + +#pragma warn -sig + +WORD sosMIDIAWE32NoteOn( WORD hDriver, WORD wSlot, WORD wChannel, + WORD wPatch, WORD wNote, WORD wVelocity ) +{ + BYTE szMIDIData[ 0x10 ]; + + // setup the midi data structure to associate a slot to a channel + szMIDIData[ 0 ] = 0xb0 | wChannel; + szMIDIData[ 1 ] = 0x00; + szMIDIData[ 2 ] = wSlot; +#ifdef __BORLANDC__ + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x03 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x03 ); +#endif + + // select the patch for the channel + szMIDIData[ 0 ] = 0xc0 | wChannel; + szMIDIData[ 1 ] = wPatch; +#ifdef __BORLANDC__ + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x02 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x02 ); +#endif + + // turn the note on with the correct pitch and attack + szMIDIData[ 0 ] = 0x90 | wChannel; + szMIDIData[ 1 ] = wNote; + szMIDIData[ 2 ] = wVelocity; +#ifdef __BORLANDC__ + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x02 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x02 ); +#endif + + // return no error + return( _ERR_NO_ERROR ); +} + +#pragma warn .sig + +/*************************************************************************** + +Function : WORD sosMIDIAWE32NoteOff + +Parameters : WORD hDriver + Handle of SOS driver + WORD wChannel + Channel to use + WORD wNote + MIDI relative pitch to use + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Turn a note on + +****************************************************************************/ + +#pragma warn -sig + +WORD sosMIDIAWE32NoteOff( WORD hDriver, WORD wChannel, WORD wNote ) +{ + BYTE szMIDIData[ 0x10 ]; + + // turn the note off + szMIDIData[ 0 ] = 0x90 | wChannel; + szMIDIData[ 1 ] = wNote; + szMIDIData[ 2 ] = 0x00; +#ifdef __BORLANDC__ + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x03 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x03 ); +#endif + + // return no error + return( _ERR_NO_ERROR ); +} + +#pragma warn .sig + + + + + + + diff --git a/CODE/RP/MUNGA_L4/SOSMAWE.H b/CODE/RP/MUNGA_L4/SOSMAWE.H new file mode 100644 index 0000000..cf8f1e6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/SOSMAWE.H @@ -0,0 +1,16 @@ + +#include "sosm.h" + +#ifdef __cplusplus // HACK - ECH 96/01/26 +extern "C" { +#endif + +WORD sosMIDIAWE32SetSBKFile( WORD, const char *szFileName ); +WORD sosMIDIAWE32ReleaseSBKFiles( WORD ); +WORD sosMIDIAWE32NoteOn( WORD, WORD, WORD, WORD, WORD, WORD ); +WORD sosMIDIAWE32NoteOff( WORD, WORD, WORD ); + +#ifdef __cplusplus // HACK - ECH 96/01/26 +} +#endif + diff --git a/CODE/RP/MUNGA_L4/SPEAKER.HPP b/CODE/RP/MUNGA_L4/SPEAKER.HPP new file mode 100644 index 0000000..7151f17 --- /dev/null +++ b/CODE/RP/MUNGA_L4/SPEAKER.HPP @@ -0,0 +1,9 @@ +#include +#include +#undef inp +#undef outp + +#define SPKSET outp(0x61,(2 | inp(0x61))) +#define SPKCLR outp(0x61,((~2) & inp(0x61))) + + diff --git a/CODE/RP/MUNGA_L4/STARTDPL.C b/CODE/RP/MUNGA_L4/STARTDPL.C new file mode 100644 index 0000000..038fbe9 --- /dev/null +++ b/CODE/RP/MUNGA_L4/STARTDPL.C @@ -0,0 +1,275 @@ +#include +#include +#include +#include + +int x_size=832, + y_size=512; + +#define dpl_arg_sep '~' + +float near_clip=4.0f, far_clip=2000.0f; + +/*{{{ static char *find_dpl_arg ( char *dpl_arg, char *find_arg )*/ +static char *find_dpl_arg ( char *dpl_arg, char *find_arg ) +{ + char *check=dpl_arg, *ret=NULL; + int len=strlen(find_arg); + + while (*check) { + /* printf ("checking %s with %s, %d chars\n", find_arg, check, len ); */ + if (strncmp (check, find_arg, len) == 0) { + /* found it ? */ + /* printf ("preliminary match, on %s\n", check ); */ + while ((*check) != dpl_arg_sep) { + if ((*check) == 0x0) return NULL; + /* printf ("skipping %c\n", *check ); */ + check++; + } + check++; + if ((*check) == 0x0) return NULL; + else { + /* printf ("match, returning %s!\n", check ); */ + return check; + } + } + else check++; + } + return NULL; +} +/*}}} */ + +/*{{{ int screen_resolution ( dpl_argv )*/ +int screen_resolution ( char *dpl_argv ) +{ + char *video=find_dpl_arg ( dpl_argv, "video" ); + + if (video == NULL) return 0; + + if (strncmp ( video, "ntsc", 4 ) == 0) { + x_size=704; + y_size=480; + return 1; + } + + if (strncmp ( video, "ntsc_rgb", 4 ) == 0) { + x_size=704; + y_size=480; + return 1; + } + + if (strncmp ( video, "vga", 3 ) == 0) { + x_size=640; + y_size=480; + return 1; + } + + if (strncmp ( video, "pal", 3 ) == 0) { + x_size=832; + y_size=512; + return 1; + } + + if (strncmp ( video, "pal_rgb", 7 ) == 0) { + x_size=832; + y_size=512; + return 1; + } + + if (strncmp ( video, "hires", 5 ) == 0) { + x_size=1024; + y_size=768; + return 1; + } + + if (strncmp ( video, "svga", 4 ) == 0) { + x_size=832; + y_size=512; + return 1; + } + + if (strncmp ( video, "nucolor", 7 ) == 0) { + x_size=640; + y_size=480; + return 1; + } + + if (strncmp ( video, "kaiser", 6 ) == 0) { + x_size=832; + y_size=256; + return 1; + } + + else { + printf ("Unknown video format %s\n", video ); + x_size=640; + y_size=480; + return 0; + + } +} +/*}}} */ + +/*{{{ dpl_ZONE *initialize_eyes ( char *dpl_args, int stereo,*/ +dpl_ZONE *initialize_eyes ( int stereo, + dpl_VIEW **lye, + dpl_VIEW **rye, + float fog_near ) +{ + dpl_DCS *d; + dpl_ZONE *z; + dpl_VIEW *eye; + float fog_far; + + if (fog_near > far_clip) + fog_far=fog_near+256; + else + fog_far=far_clip; + + + printf ("initialize eyes\n" ); + + z=dpl_NewZone(); + + printf ("create 1st view\n" ); + + *lye = dpl_NewView(); + + if ((*lye) == NULL) { + printf ("NULL eye\n" ); + return NULL; + } + + eye=*lye; + + d=dpl_NewDCS(); + dpl_SetViewDCS(eye, d); + + dpl_SetZoneAllViewsOn ( z ); +// dpl_AddZoneToScene ( z ); + dpl_SetViewClipPlanes ( eye, near_clip, far_clip ); + dpl_SetViewBackGround ( eye, 0.4f, 0.6f, 0.9f ); + dpl_SetViewFog ( eye, 0, 0.5f, 0.5f, 0.6f, fog_near, fog_far ); + dpl_SetViewPort ( eye, 0, 0, x_size-1, y_size-1 ); + dpl_SetViewProjection ( eye, + -1.0f, -1.0f, 1.0f, 1.0f, + 1.3f ); + dpl_AddViewToScene ( eye ); + + dpl_FlushDCS(d); + dpl_FlushView(eye); + dpl_FlushZone(z); + + if (stereo == 0) { + *rye=NULL; + } + else { + printf ("create 2nd view\n" ); + *rye = dpl_NewView(); + if ((*rye) == NULL) { + printf ("NULL rye\n" ); + return NULL; + } + + eye=*rye; + + d=dpl_NewDCS(); + dpl_SetViewDCS(eye, d); + + dpl_SetViewClipPlanes ( eye, near_clip, far_clip ); + dpl_SetViewBackGround ( eye, 0.4f, 0.6f, 0.9f ); + dpl_SetViewFog ( eye, 0, 0.5f, 0.5f, 0.6f, fog_near, fog_far ); + dpl_SetViewPort ( eye, 0, 0, x_size-1, y_size-1 ); + dpl_SetViewProjection ( eye, + -1.0f, -1.0f, 1.0f, 1.0f, + 1.3f ); + dpl_AddViewToScene ( eye ); + + dpl_FlushDCS(d); + dpl_FlushView(eye); + } + return z; +} +/*}}} */ + +/*{{{ static char *explode_an_arg( char *dpl_args, char **where, char sep )*/ +static char *explode_an_arg( char *dpl_args, char **where, char sep ) +{ + int explode=1, good_chars=0; + char *arg0=dpl_args; + + + while (explode) { + if (*dpl_args == sep) { + /*{{{ a separator*/ + /* end of a string */ + if (good_chars) { + *where=malloc(good_chars+1); + memcpy ( *where, arg0, good_chars ); + (*where)[good_chars]=0x0; + dpl_args++; + } + else { + *where=malloc(1); + (*where)[0]=0x0; + dpl_args++; + } + /*}}} */ + explode=0; + } + else if (*dpl_args) { + good_chars++; + dpl_args++; + } + else { + /*{{{ end of whole dpl_args string*/ + if (good_chars) { + *where=malloc(good_chars+1); + memcpy ( *where, arg0, good_chars ); + (*where)[good_chars]=0x0; + explode=0; /* ensure we return pointer to (char) 0x0 */ + } + else return NULL; + /*}}} */ + } + } + return dpl_args; +} +/*}}} */ +/*{{{ static int explode_args ( char **argv, char *dpl_args, char dpl_arg_sep )*/ +int explode_args ( char **argv, char *dpl_args, char sep ) +{ + int argc=0; + + while (*dpl_args) { + dpl_args=explode_an_arg(dpl_args, &argv[argc], sep); + if (dpl_args) + argc++; + else + return argc; + } + return argc; +} +/*}}} */ + +/*{{{ dpl_ZONE *initialize_all ( char *dpl_args,*/ +dpl_ZONE *initialize_all ( char *dpl_args, + int stereo, + dpl_VIEW **lye, + dpl_VIEW **rye, + float fog_near ) +{ + dpl_ZONE *z; + char *argv[32]; + int argc=0; + + argc = explode_args ( argv, dpl_args, dpl_arg_sep ); + + dpl_Init ( argc, argv ); + + z = initialize_eyes ( stereo, lye, rye, fog_near ); + + return z; +} +/*}}} */ + diff --git a/CODE/RP/MUNGA_L4/joystick.OBJ b/CODE/RP/MUNGA_L4/joystick.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..0387528ab728e0a5276aae6d02b55a8d527e112e GIT binary patch literal 612 zcmZqRW8lfkuPiRfOwQIzEY5B3P+(wSkO?U*O3GJoEG|yXP0C3vQcws>Eh^5;&r>kf zGnm;S!r<^SD=b$NMdz;$L8vfijtS5tz0ADiX&pj9u?nD4u7c#0g4|4y;HwU1prFq* zCI*HK5Od*_X*>+9@gc4eAuP`RF0RvNursWzU|?cqv;s@GIEFZ~fQUmN2`&Z}R>mdM z*ce#cd>lh8XE8Cb#ZBX2U~_Q~@(&H@p2fnz{+}sof)oQIqi}qHbG(;-WN?V5vv+)G z0MHCqpy%QyNH8!m38F~)ItF`lFfe=o>0?6CXBZ#k7#<%9bgVZn$q1mKewdO*5S?rc z3~sn2BUl(1JSRv4?G!{)G#nIFq{C|6c8L3l(vI` z^Q>W7K-w-wrZnS|U8+F0GZ-Cs_eO~o%sNtHu!6CKJ*|@$D9*5g3Csj~fnfy;m~Yp9~zOd(tA#8ov200V0AyL>`b>w}6iUWD6AVGdOkuxg`K{>8Akz literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/l4serial.OBJ b/CODE/RP/MUNGA_L4/l4serial.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..c04f2444d03f490effb4fd9cea6eb64009211fc1 GIT binary patch literal 2312 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�TTvAVu+cGda>J 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VREND.MNG b/CODE/RP/MUNGA_L4/libDPL/VREND.MNG new file mode 100644 index 0000000000000000000000000000000000000000..4f084f9b2e746787b6b2c028a82449e2599d2683 GIT binary patch literal 385404 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%0A96Ba1vMJ(`^Nd^Xl`ULQntREB;vsa3 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VREND2.BTL b/CODE/RP/MUNGA_L4/libDPL/VREND2.BTL new file mode 100644 index 0000000000000000000000000000000000000000..1d247f91c8a3acf20b7e1bfa479800d741d1241f GIT binary patch literal 87075 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%0D?+7JWu?IcVqJ=N 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

Z-SybRbROg)9Hrm6-@Z-93={858R|n`- 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 E0l@;Ff&c&j literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VREND3.BTL b/CODE/RP/MUNGA_L4/libDPL/VREND3.BTL new file mode 100644 index 0000000000000000000000000000000000000000..d8bde5a693bbc19ae223fe4afe2ff8e1500a8d5a GIT binary patch literal 88860 zcmeFad3aREl{eg&-57({$z(F~-MaU-dQnTd5(2!G?b||NY-3{sCQjnS-C9@zhP(DI z3F3S+p7-@UVc)l4b}-DAWRloUhH>tFCK@Ele*Z-)^x9j1{ znr>XyHRCF)Et)BP*mViKE@IzX6?udWux7ctJ;pwau@AhL#Xe@lq~H70uD&cg6!?(& zK4g#gv0dU!Kz#>&W%N^2t*H6Onqzvbzi`_l;>Eu>^Z%S?#tE~-j6BiA)X zsb6NsrHGoRKz2L41dt2#yIR$}k)r_p5Mk;@cXPyJG#kw5ImsTCdh&+u?e@*=Ze~^R zScWe58?Bb~VeYdXf7+>O8}a%qI;PS1)F{(pF21s9^Pt9i9uJ*~dQl25Tb zOTNjHb68G&>o#VEFZ-wKJ)*o5jPFeQG$1 zci0EwEY{5|`?A_x-C~6e`J#M@?KYU%uYY78qDX@6f!jq@yvTUz*oHS)$szmreq`Rt zLKEya!~@}GL)_)$toz^CYlOR-$LRha?lHnW&BnfzL#k#x3-aOikB84RkgR`3X#@atW$Wjwo$$C~a-u@XKe*5=KtDhbj@(+L5rkJFimb?Jn(_ao5-H%fv|Hqr_o0RKW>Ua9F(P zA7THictq_;b|%Dc-o~jhuS<75|9?X0>Iv@%``_dvw@)ly&0;O4+%5gS#mpI6pR}LT zcekPSpf}I%WBbZxYjSrtdAhutG;+Ih%!Bw2HzwXCuQqbEV@HJ1u>5BGq!mt~GYqsk zWvMA1!D2b4D_S?TU5eaPp%D%mK_j15V1F-mMP3i*xR$p~X~5F^*kR4md;0d^lQVU* zTa){Btvj!2-MOd-*s4(o>+k4O#Fq_ahJ4W|=udr4XO-d0hN72K$L%%>AyqH$%j)mc zj1{{)D|qBPO{W`ku~W&DOlwy2;kJpbx5Xh`;vt*8V(Esr8zQ~Oiaf^j{wJg!x!-}L z57jm!F1zAaJHckVKLx|vqka35u(IkU{(m!Og#J$kjlX$`|KAK7@_%OB_?wrUkpm8m z9e?xRgU5dl9{;}_JXThH&GW+7R=n_EF@&s~_TPiZf3HCPdj<0UxfRIDY5!$|$h4Jz z_2L_MR(;KJUYIuMA_z11ci2blh}_*eF+Y67C6KRw_WEs{p zshc&OXAP{W62Jul?&)T{>6ZlEi=g)ixDUXu2)G}>uUR8&nhfA=mSRosurzCWS7ohL ztc_XOeXNP!%Q{9P4eP+dwV{vs53x9{IjiI@xx4=a%OodtC(pyF>`o%X}m9MwfbKi662YsLsT;=Nf6o+toLj z_EuBz-bP@?`rBhlM|@h}q3U>#xGVnSqvD8gyyr+&yysB-hu<8&D&6l;i8bjQy5 z#&g!_LL&x)Vil~DB?ifNCc-`7UOA0`{Q{2pw4MXnkG^>e<*F;J0lVwba2w(B+eO+r7Ec#1Ca0j5I+9bbFIKaf zi|6%Ynp30-&FC*ooQ++UB_2tZSIPVm+moF7C>!W1BrB6sr4L&#X=vGD*hKV6(O|r`qLx(W8cPF}q(k6syF)MZeD~@$HC= z(f&c~;#Ky71@(qt)Gv6hcDcRG61boUifSHdyOmO9O;gbPtQxJ-+(Xe5oM|(WOhVfzex#^~1!-fwZ zHf+R*VZ(m#gO^@1nynWiv*b&ymfCkvN9L8LCHIS6reR&CJs88Nkhjbb_io5(*#o*_ zhU8T!9Ow#yQ#r58=vR3*(+o*#hfvt|$QUFN*Jy8Rld}gnB@?zp#;Dp^RXZmJ9@WlM zLGSVQuO#=E+67fBxHKK2(eJT1!ZBF*ALY=vw6ca%tU-Y|TMBDY-&EgHS+fc;Pq5Cf zPG~1LF<-vyA>oOqXU!5E@zX2= zSVNH%N5R74IyVRQfG}ms6v6MU3s7!60c5cCgUENi=#K4~oSILk5`p4%ZT3O?c=mw( zMt1+$RO_wj)^VBEF)<|(@UM%Exy`D+tT%I`q9tiwfzAW1X-qbqCQEh=i~}rD^8q%> zBi}I2en;$b`uyLaMg-x_;%YX)�YhhuY3`bjR2m;%>EZ67(3g@>=v)Eg-H6!$0eU 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VREND5.BTL b/CODE/RP/MUNGA_L4/libDPL/VREND5.BTL new file mode 100644 index 0000000000000000000000000000000000000000..fd72eb5f795c7d0968cd93959204f1d1541b1d14 GIT binary patch literal 92518 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®B4ckHi}gDebco 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VREND7.BTL b/CODE/RP/MUNGA_L4/libDPL/VREND7.BTL new file mode 100644 index 0000000000000000000000000000000000000000..91b75e912a1d20a1a073a9907caf3e7bb327e8fd GIT binary patch literal 96264 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VREND8.BTL b/CODE/RP/MUNGA_L4/libDPL/VREND8.BTL new file mode 100644 index 0000000000000000000000000000000000000000..6d7114c52fc5387ca6db072452072b0b0548a681 GIT binary patch literal 98181 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

?E8S&Ql! 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 QO((i3*7OE?e4*(70n#XY8UO$Q literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VREND9.BTL b/CODE/RP/MUNGA_L4/libDPL/VREND9.BTL new file mode 100644 index 0000000000000000000000000000000000000000..9403ff5650b205a0dbdea177b70e0d0b90d5cec5 GIT binary patch literal 100098 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 Nd9eqrr^lCz{vRGNLJ0r> literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VRENDMON.BTL b/CODE/RP/MUNGA_L4/libDPL/VRENDMON.BTL new file mode 100644 index 0000000000000000000000000000000000000000..eda5fed4158aeafcf3332c36e9d50063ee6f7715 GIT binary patch literal 85298 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/VRNOSTEX.MNG b/CODE/RP/MUNGA_L4/libDPL/VRNOSTEX.MNG new file mode 100644 index 0000000000000000000000000000000000000000..630e1eef80b7bbda2c2d3e7ebdfd5984c6658fa9 GIT binary patch literal 336252 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⁢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

d!=bn))9?jv???R^av)ls; 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

uI0Nq2@Q#Q-W%A%&*J+@e7{-wPSn{1JB>Xj h%SZ%1-yG + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create Elements */ + +extern dpl_ZONE *dpl_NewZone(void); +extern dpl_VIEW *dpl_NewView(void); +extern dpl_DCS *dpl_NewDCS(void); +extern dpl_INSTANCE *dpl_NewInstance(void); +extern dpl_LIGHT *dpl_NewLight(void); +extern dpl_TEXTURE *dpl_NewTexture(void); +extern dpl_TEXMAP *dpl_NewTexmap(void); +extern dpl_MATERIAL *dpl_NewMaterial(void); +extern dpl_OBJECT *dpl_NewObject(void); +extern dpl_LOD *dpl_NewLod(void); +extern dpl_GEOGROUP *dpl_NewGeogroup(void); +extern dpl_GEOMETRY *dpl_NewGeometry(void); +extern dpl_RAMP *dpl_NewRamp(void); + +/* Connect Structure */ + +extern void dpl_AddViewToScene(dpl_VIEW *v); +extern void dpl_AddDCSToScene(dpl_DCS *d); +extern void dpl_AddDCSToDCS(dpl_DCS *parent, dpl_DCS *child); +extern void dpl_AddInstanceToDCS(dpl_DCS *d, dpl_INSTANCE *i); +extern void dpl_AddLodToObject(dpl_OBJECT *o, dpl_LOD *l); +extern void dpl_AddGeogroupToLod(dpl_LOD *l, dpl_GEOGROUP *gg); +extern void dpl_AddGeometryToGeogroup(dpl_GEOGROUP *gg, dpl_GEOMETRY *g); + +/* Querry Structure */ + +extern dpl_VIEW *dpl_GetSceneView(int32 n); +extern dpl_DCS *dpl_GetSceneDCS(int32 n); +extern dpl_DCS *dpl_GetDCSChildDCS(dpl_DCS *parent, int32 n); +extern dpl_DCS *dpl_GetDCSParentDCS(dpl_DCS *child); +extern dpl_INSTANCE *dpl_GetDCSInstance(dpl_DCS *d, int32 n); +extern dpl_LOD *dpl_GetObjectLod(dpl_OBJECT *o, int32 n); +extern dpl_GEOGROUP *dpl_GetLodGeogroup(dpl_LOD *l, int32 n); +extern dpl_GEOMETRY *dpl_GetGeogroupGeometry(dpl_GEOGROUP *gg, int32 n); + +/* Disonnect Structure */ + +extern void dpl_RemoveViewFromScene(dpl_VIEW *v); +extern void dpl_RemoveDCSFromScene(dpl_DCS *d); +extern void dpl_RemoveDCSFromDCS(dpl_DCS *parent, dpl_DCS *child); +extern void dpl_RemoveInstanceFromDCS(dpl_DCS *d, dpl_INSTANCE *i); +extern void dpl_RemoveLodFromObject(dpl_OBJECT *o, dpl_LOD *lod); +extern void dpl_RemoveGeogroupFromLod(dpl_LOD *l, dpl_GEOGROUP *gg); +extern void dpl_RemoveGeometryFromGeogroup(dpl_GEOGROUP *gg, dpl_GEOMETRY *g); + +/* Delete Elements */ + +extern void dpl_DeleteZone(dpl_ZONE *z); +extern void dpl_DeleteView(dpl_VIEW *v); +extern void dpl_DeleteDCS(dpl_DCS *d); +extern void dpl_DeleteInstance(dpl_INSTANCE *i); +extern void dpl_DeleteLight(dpl_LIGHT *l); +extern void dpl_DeleteTexture(dpl_TEXTURE *t); +extern void dpl_DeleteTexmap(dpl_TEXMAP *tm); +extern void dpl_DeleteMaterial(dpl_MATERIAL *m); +extern void dpl_DeleteObject(dpl_OBJECT *o); +extern void dpl_DeleteLod(dpl_LOD *l); +extern void dpl_DeleteGeogroup(dpl_GEOGROUP *gg); +extern void dpl_DeleteGeometry(dpl_GEOMETRY *g); +extern void dpl_DeleteRamp(dpl_RAMP *); + +/* Scene Coherence */ + +extern void dpl_FlushZone(dpl_ZONE *z); +extern void dpl_FlushView(dpl_VIEW *v); +extern void dpl_FlushDCS(dpl_DCS *d); +extern void dpl_FlushInstance(dpl_INSTANCE *i); +extern void dpl_FlushLight(dpl_LIGHT *l); +extern void dpl_FlushTexture(dpl_TEXTURE *t); +extern void dpl_FlushTexmap(dpl_TEXMAP *tm); +extern void dpl_FlushMaterial(dpl_MATERIAL *m); +extern void dpl_FlushObject(dpl_OBJECT *o); +extern void dpl_FlushLod(dpl_LOD *l); +extern void dpl_FlushGeogroup(dpl_GEOGROUP *gg); +extern void dpl_FlushGeometry(dpl_GEOMETRY *g); +extern void dpl_FlushRamp(dpl_RAMP *); + +/* Modal Render Changes */ + +/* Render modes may be set and querried using these functions, this enables + modes like; wireframe rendering, single buffered rendering and the + graphical display of performance information. */ + +extern void dpl_SetRenderProperty(dpl_RENDER_PROP prp, dpl_RENDER_VALUE val, + void *data); +extern dpl_RENDER_VALUE dpl_GetRenderProperty(dpl_RENDER_PROP prp, + void *data); +extern void dpl_SetPipeWindow(int32 pipe, + int32 x0, int32 y0, int32 x1, int32 y1); +extern void dpl_GetPipeWindow(int32 pipe, + int32 *x0, int32 *y0, int32 *x1, int32 *y1); +extern void dpl_SetWindowName(int32 pipe, char8 *name); +extern char8 *dpl_GetWindowName(int32 pipe); +extern void dpl_SetDesktopStereo(int32 pipe, int32 mode); +extern int32 dpl_GetDesktopStereo(int32 pipe); +extern void dpl_SetFrameRate(float32 rate); +extern float32 dpl_GetFrameRate(void); + +/* Direct Render Calls */ + +/* These calls render the scene to all views and allow the application to + lock and therefore synch to the frame rate. In multi processor SGI + implementations this will lock to the cull rather than the render + process. */ + +extern void dpl_DrawScene(void); +extern void dpl_WaitSceneComplete(void); +extern int32 dpl_DrawSceneComplete(void); + +/* DCS */ + +/* Positional information may be set in a DCS in the form of a 4x4 matrix. */ + +extern void dpl_SetDCSMatrix(dpl_DCS *d, float32 *m); +extern float32 *dpl_GetDCSMatrix(dpl_DCS *d); + +/* DCS nodes may be billboarded around any set of axes. This makes them + automatically orient towards the view reguardless of their position + relative to the viewpoint. Multiple axes may be set by adding or bitwise + oring the axis definitions together. */ + +extern void dpl_SetDCSReorientAxes(dpl_DCS *d, dpl_REORIENT_AXES a); +extern dpl_REORIENT_AXES dpl_GetDCSReorientAxes(dpl_DCS *d); + +/* For switching and lighting model purposes a DCS has an associated zone + which it occupies. */ + +extern void dpl_SetDCSZone(dpl_DCS *d, dpl_ZONE *z); +extern dpl_ZONE *dpl_GetDCSZone(dpl_DCS *d); + +/* Zone */ + +/* Zones provide a means of controlling geometry switching on a per view + basis and may be used to associate groups of light sources with + particular DCS hierarchies. */ + +/* Sets rendering of the zone on for all views */ +extern void dpl_SetZoneAllViewsOn(dpl_ZONE *z); + +/* Sets rendering of the zone off for all views */ +extern void dpl_SetZoneAllViewsOff(dpl_ZONE *z); + +/* Sets rendering of the zone for the specified view on */ +extern void dpl_SetZoneViewOn(dpl_ZONE *z, dpl_VIEW *v); + +/* Sets rendering of the zone for the specified view off */ +extern void dpl_SetZoneViewOff(dpl_ZONE *z, dpl_VIEW *v); + +/* gets the rendering status of the zone in the view */ +extern int32 dpl_GetZoneView(dpl_ZONE *z, dpl_VIEW *v); + +/* sets all 32 views for this zone based on a bitmask*/ +extern void dpl_SetZoneBitmask(dpl_ZONE *z, uint32 m); + +/* gets a bitmask of all 32 views for this zone */ +extern uint32 dpl_GetZoneBitmask(dpl_ZONE *z); + +/* Instance */ + +/* Instances provide a means of copying an object without explicitly + recreating it in the database. All instances therefore reference an + object, any object may be multiply referenced by several instances. + Material overrides may be applied to all geometry below an instance. + Any material override applied to an instance will change the material + of those geosets which have no lock applied to the material or geoset. */ + +extern void dpl_SetInstanceObject(dpl_INSTANCE *, dpl_OBJECT *); + +extern dpl_OBJECT *dpl_GetInstanceObject(dpl_INSTANCE *); + +extern void dpl_SetInstanceForceLOD(dpl_INSTANCE *i, dpl_LOD *l); + +extern dpl_LOD *dpl_GetInstanceForceLOD(dpl_INSTANCE *i); + +extern void dpl_SetInstanceVisibility(dpl_INSTANCE *i, int32 v); + +extern int32 dpl_GetInstanceVisibility(dpl_INSTANCE *i); + +extern void dpl_SetInstanceIntersect(dpl_INSTANCE *i, dpl_ISECT_MODE m); + +extern dpl_ISECT_MODE dpl_GetInstanceIntersect(dpl_INSTANCE *i); + +extern void dpl_SetInstanceSectMask(dpl_INSTANCE *i, uint32 mask); + +extern uint32 dpl_GetInstanceSectMask(dpl_INSTANCE *i); + + +/* Object */ + +/* Objects contain lod nodes which switch according to ranging information + associated wit the object */ + +extern void dpl_SetObjectLodRange(dpl_OBJECT *o, + int32 transition, float32 range); + +extern void dpl_InvalidateObjectLodRanges(dpl_OBJECT *o); + +extern float32 dpl_GetObjectLodRange(dpl_OBJECT *o, int32 transition); + +extern void dpl_SetObjectLodHotSpot(dpl_OBJECT *o, + float32 x, float32 y, float32 z); + +extern void dpl_GetObjectLodHotSpot(dpl_OBJECT *o, + float32 *x, float32 *y, float32 *z); + +extern void dpl_SetObjectLodFadeRange(dpl_OBJECT *o, float32 range); + +extern float32 dpl_GetObjectLodFadeRange(dpl_OBJECT *o); + +extern void dpl_SetInstanceFrontMaterial(dpl_INSTANCE *i, dpl_MATERIAL *m); +extern void dpl_SetInstanceBackMaterial(dpl_INSTANCE *i, dpl_MATERIAL *m); +extern dpl_MATERIAL *dpl_GetInstanceFrontMaterial(dpl_INSTANCE *i); +extern dpl_MATERIAL *dpl_GetInstanceBackMaterial(dpl_INSTANCE *i); + +/* Light */ + +extern void dpl_SetLightDCS(dpl_LIGHT *, dpl_DCS *); +extern dpl_DCS *dpl_GetLightDCS(dpl_LIGHT *); +extern void dpl_SetLightType(dpl_LIGHT *l, dpl_LIGHT_TYPE t); +extern dpl_LIGHT_TYPE dpl_GetLightType(dpl_LIGHT *l); +extern void dpl_SetLightColor(dpl_LIGHT *l, float32 r, float32 g, float32 b); +extern void dpl_GetLightColor(dpl_LIGHT *l, + float32 *r, float32 *g, float32 *b); +extern void dpl_SetLightRadii(dpl_LIGHT *l, float32 r0, float32 r1); +extern void dpl_GetLightRadii(dpl_LIGHT *l, float32 *r0,float32 *r1); +extern void dpl_SetLightUmbra(dpl_LIGHT *l, float32 exp, float32 th); +extern void dpl_GetLightUmbra(dpl_LIGHT *l, float32 *exp, float32 *th); + +/* View */ + +extern void dpl_ViewShare(dpl_VIEW *master, dpl_VIEW *slave); +extern void dpl_SetViewDCS(dpl_VIEW *v, dpl_DCS *d); +extern dpl_DCS *dpl_GetViewDCS(dpl_VIEW *v); +extern void dpl_SetViewClipPlanes(dpl_VIEW *v, float32 hither, float32 yon); +extern void dpl_GetViewClipPlanes(dpl_VIEW *v, float32 *hither, float32 *yon); +extern void dpl_SetViewBackGround(dpl_VIEW *v, + float32 r, float32 g, float32 b); +extern void dpl_GetViewBackGround(dpl_VIEW *v, + float32 *r, float32 *g, float32 *b); +extern void dpl_SetViewFog(dpl_VIEW *v, dpl_FOG_TYPE enable, + float32 r, float32 g, float32 b, float32 neer, float32 phar); +extern void dpl_GetViewFog(dpl_VIEW *v, dpl_FOG_TYPE *enable, + float32 *r, float32 *g, float32 *b, float32 *neer, float32 *phar); +extern void dpl_SetViewPipe(dpl_VIEW *v, int32 pipe); +extern int32 dpl_GetViewPipe(dpl_VIEW *v); +extern void dpl_SetViewPort(dpl_VIEW *v, + float32 x0, float32 y0, float32 x1, float32 y1); +extern void dpl_GetViewPort(dpl_VIEW *v, + float32 *x0, float32 *y0, float32 *x1, float32 *y1); +extern void dpl_SetViewProjection(dpl_VIEW *v, float32 x0, float32 y0, + float32 x1, float32 y1, float32 zeye); +extern void dpl_GetViewProjection(dpl_VIEW *v, float32 *x0, float32 *y0, + float32 *x1, float32 *y1, float32 *zeye); +extern void dpl_SetViewNumber(dpl_VIEW *v, int32 n); +extern int32 dpl_GetViewNumber(dpl_VIEW *v); +extern void dpl_SetViewZClearOnly(dpl_VIEW *v, int32 mode); +extern int32 dpl_GetViewZClearOnly(dpl_VIEW *v); + +/* Material */ + +/* Various illumination properties of a material may be set independently. */ + +extern void dpl_SetMaterialAmbient(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialAmbient(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialEmissive(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialEmissive(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialDiffuse(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialDiffuse(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialSpecular(dpl_MATERIAL *m, + float32 r, float32 g, float32 b, float32 shininess); + +extern void dpl_GetMaterialSpecular(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b, float32 *shininess); + +extern void dpl_SetMaterialOpacity(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialOpacity(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialTexture(dpl_MATERIAL *m, dpl_TEXTURE *t); + +extern dpl_TEXTURE *dpl_GetMaterialTexture(dpl_MATERIAL *m); + +extern void dpl_SetMaterialEnvironment(dpl_MATERIAL *m, dpl_TEXTURE *t); + +extern dpl_TEXTURE *dpl_GetMaterialEnvironment(dpl_MATERIAL *m); + +extern void dpl_SetMaterialRamp(dpl_MATERIAL *, dpl_RAMP *); + +extern dpl_RAMP *dpl_GetMaterialRamp(dpl_MATERIAL *); + +/* Texture */ +/* Texture manipulation commands allow control over the various modes + associated with applying texmaps to polygons. Particular importance is + attached to the dpl_FlushTexture() function listed in a previous section. + Potentially, many of the mode changes associated with these commands + require a prohibitive ammount of time to be applied on some systems. + With write-back cacheing it is likely that applications will have to + flush a texture on most platforms before any modifications take effect, + this should be done as infrequently as possible, prefferably after all + modifications have been requested. Functions below allow various + properties to be set to particular parameter values. Hopefully this leads + to a flexible and extensible interface. For a list of properties see the + enumerated type definitions earlier in this document. */ + +extern void dpl_SetTextureProperty(dpl_TEXTURE *t, + dpl_TEX_PROP prp, dpl_TEX_VALUE val, void *data); + +extern dpl_TEX_VALUE dpl_GetTextureProperty(dpl_TEXTURE *t, + dpl_TEX_PROP prp, void *data); + +extern void dpl_SetTextureTexmap(dpl_TEXTURE *t, dpl_TEXMAP *tm); + +extern dpl_TEXMAP *dpl_GetTextureTexmap(dpl_TEXTURE *t); + +/* Texmap */ +/* These functions allow the creation of texmaps both from image files on + disk and from image data in memory. Using the high level loading + function eliminates the need to set the texmap dimensions. + Finally it is important to remember that this may be information used + to create a texture and not actual texture itself (I think this applies + to all target platforms & others may make a copy), so the texel memory + should be freed after the call. */ + +extern void dpl_SetTexmapEdgeSize(dpl_TEXMAP *, int32, int32); + +extern void dpl_GetTexmapEdgeSize(dpl_TEXMAP *tm, int32 *u, int32 *v); + +extern void dpl_SetTexmapTexelSize(dpl_TEXMAP *, int32); + +extern int32 dpl_GetTexmapTexelSize(dpl_TEXMAP *tm); + +extern void dpl_UpdateTexmapTexels2D(dpl_TEXMAP *, uint8 *, int32, int32); + +extern void dpl_GetTexmapTexels2D(dpl_TEXMAP *, uint8 *, int32, int32); + +/* throws away the texmap and saves some resources */ +extern void dpl_InvalidateTexels(dpl_TEXMAP *tm); + +/* Geogroup */ + +/* A material lock may be placed at the level of the geogroup which will + prevent material chain operations or override commands affecting its + material. */ + +/* set a geogroups front material */ +extern void dpl_SetGeogroupFrontMaterial(dpl_GEOGROUP *g, dpl_MATERIAL *m); + +/* set a geogroups back material */ +extern void dpl_SetGeogroupBackMaterial(dpl_GEOGROUP *g, dpl_MATERIAL *m); + +/* get a geogroups front material */ +extern dpl_MATERIAL *dpl_GetGeogroupFrontMaterial(dpl_GEOGROUP *g); + +/* get a geogroups back material */ +extern dpl_MATERIAL *dpl_GetGeogroupBackMaterial(dpl_GEOGROUP *g); + +/* lock a geogroups material */ +extern void dpl_SetGeogroupMaterialLockOn(dpl_GEOGROUP *m); + +/* unlock a geogroups material */ +extern void dpl_SetGeogroupMaterialLockOff(dpl_GEOGROUP *m); + +/* find out if a geogroups material is locked */ +extern int32 dpl_GetGeogroupMaterialLock(dpl_GEOGROUP *m); + +/* set decal displace value */ +void dpl_SetGeogroupDecalDisplace(dpl_GEOGROUP *, int32); + +/* returns decal displace on */ +int32 dpl_GetGeogroupDecalDisplace(dpl_GEOGROUP *); + +/* set wireframe TRUE or filled FALSE */ +void dpl_SetGeogroupWireframe(dpl_GEOGROUP *, int32); + +/* return wireframe TRUE or filled FALSE */ +int32 dpl_GetGeogroupWireframe(dpl_GEOGROUP *); + + +/* Geometry */ + +/* Functions are provided to create renderable database geometry from arrays + of co-ordinate information and connection lists. This is done by + specifying which type of geometry is required first. Next the vertex type + of the geometry is specified, then number of vertices. + Once this is done the vertices are passed vertice values may be set + in blocks of arbitrary sizes. + This information may be followed by an edge connection list or text + string or nothing depending on the type of geometry. Finally the geometry + is flushed to greate the requested primitives. Subsequent reads and + writes of this geometry information are possible. Of particular + importance to the creation of the geometric primitives is the type of + vertex being sent to the renderer. This determines how the primitive is + drawn in the scene, (cooked, illuminated, textured), and prepares the dPL + creation functions to expect vertex information in a particular form. + Vertex properties which may be set using the type specification function + above are enumerated as dpl_VERTEX_TYPE. These types may be added or + bitwise OR'd together to prepare dPL to receive the information. When the + contiguous block of vertices is passed the dPL uses the vertex type as a + guide to the size of each vertex and what information it holds. */ + + +/* determine the type of geometry to be held */ +extern void dpl_SetGeometryGeoType(dpl_GEOMETRY *g, dpl_GEO_TYPE gt); + +/* read the type of geometry held */ +extern dpl_GEO_TYPE dpl_GetGeometryGeoType(dpl_GEOMETRY *g); + +/* sets vertex type prior to creation, also determines space */ +extern void dpl_SetGeometryVertexType(dpl_GEOMETRY *g, dpl_VERTEX_TYPE vt); + +/* gets vertex type */ +extern dpl_VERTEX_TYPE dpl_GetGeometryVertexType(dpl_GEOMETRY *g); + +/* sets the number of vertices in the geometry */ +extern void dpl_SetGeometryNumVertices(dpl_GEOMETRY *g, int32 n); + +/* obtains the vertex count for geometry */ +extern int32 dpl_GetGeometryNumVertices(dpl_GEOMETRY *g); + +/* set values in n vertices starting from offset */ +extern void dpl_UpdateGeometryVertices(dpl_GEOMETRY *g, + float32 *v, int32 offset, int32 n); + +/* sends an edge connection list for some forms of geometry */ +extern void dpl_AddGeometryConnections(dpl_GEOMETRY *g, int32 *c, + int32 numpolys, int32 polysize); + +/* sends a strip connection list. */ +extern void dpl_AddGeometryStrip(dpl_GEOMETRY *g, int32 *c, + int32 numpolys, int32 polysize); + +/* sends a text string for display as text by geometry */ +extern void dpl_SetGeometryText(dpl_GEOMETRY *g, char8 *text); + +/* obtains n geometry vertices starting at offset */ +extern void dpl_GetGeometryVertices(dpl_GEOMETRY *g, + float32 *v, int32 offset, int32 n); + +/* gets the text string being displayed by text geometry */ +extern char8 *dpl_GetGeometryText(dpl_GEOMETRY *g); + +/* optimises and freezes geometry */ +extern void dpl_OptimiseGeometry(dpl_GEOMETRY *); + +/* set geometry subdivisions */ +extern void dpl_SetGeometryDice(dpl_GEOMETRY *, uint16, uint16); + +/* querry geometry subdivisions */ +extern void dpl_GetGeometryDice(dpl_GEOMETRY *, uint16 *, uint16 *); + +/* set the texture for textured font */ +void dpl_SetFontTexture(dpl_TEXTURE *); + +/* get the texture for textured font */ +dpl_TEXTURE *dpl_GetFontTexture(void); + +/* Setup & Cleanup */ + +extern int32 dpl_Init(int32 argc, char8 **argv); + +extern void dpl_Config(void); + +extern void dpl_Exit(int32 exit_code); + +/* Reporting Control */ + +extern void dpl_SetWarningLevel(dpl_WARN_LEVEL w); + +extern int32 dpl_GetWarningLevel(void); + +extern char8 *dpl_Version(void); + +/* these functions return types with defined contents */ + +extern dpl_STATISTICS *dpl_Statistics(void); + +extern dpl_STATUS *dpl_Status(void); + +dpl_CAPABILITY *dpl_GetCapability(void); + +/* Frame Store Query */ +/* These functions obtain a packed array of 8 bit red, green, blue & alpha + colour information from the currently displayed frame store associated + with a dpl_VIEW. A single pixel from the image is stored in each + unsigned integer in the hexadecimal form 0xRRGGBBAA, as can be seen the + high order 8 bits contain red, then green is stored then blue followed + by alpha information in the lowest order 8 bits. What is written to the + alpha bits is not specified at this stage but these may ultimately yield + useful information. Pixels will be written left to right(internal fast + loop) bottom to top(outside slow loop). The first function will return a + malloc'd block of packed information and returns it's size based on the + information in the dpl_VIEW structure, the application should free this + block when done with the image. The second function expects to be passed + the memory address of a contiguous block of memory where the write is to + be made and the dimensions of the required image, specifying the start + position and image size allows a portion of the frame store to be copied + to memory. There should be enough information allocated in the memory + block for an image of the requested size to be written. Values for display + portions incompatible with the dpl_VIEW information will produce undefined + results. */ + +extern uint32 *dpl_GetFrameStore(dpl_VIEW *v, int32 *x, int32 *y); + +extern void dpl_ReadFrameStore(dpl_VIEW *v, uint32 *pixels, + int32 startx, int32 starty, int32 sizex, int32 sizey); + +/* Intersection Functions */ +/* Intersection functions are used to determine the point of intersection + between a vector and the database contents. Vectors may be specified in + world co-ordinates or as a position on the viewport of a dpl_VIEW. + Depending upon the intersect mode set for the database instance + intersected, some of the fields may not return valid values. */ + +extern dpl_INSTANCE *dpl_SectVector(float32, float32, float32, + float32, float32, float32, uint32, + float32 *, float32 *, float32 *, + dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); +extern dpl_INSTANCE *dpl_SectPixel(dpl_VIEW *, float32, float32, uint32, + float32 *, float32 *, float32 *, + dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); + +/* Special Effects */ + +/* Provision is made for special effects to be requested by an application. + The idea here is that common rendering effects which might eat bandwidth + to the renderer or prove difficult to code using dPL can be implemented + in the renderer and initiated with a single high level dPL request then + left to look pretty: fire and forget rendering effects. Only explosions + have been considered so far but this interface may be extended as new + requirements arise. */ + +/* request an effect of the desired type and here's the type specific data + for the effect */ + +extern void *dpl_Effect(dpl_EFFECT_TYPE e, dpl_DCS *d, void *data); + +/* ramp stuff */ + +extern void dpl_SetRampComponents(dpl_RAMP *ramp, + float32 r0, float32 g0, float32 b0, + float32 r1, float32 g1, float32 b1); + +extern void dpl_GetRampComponents(dpl_RAMP *ramp, + float32 *r0, float32 *g0, float32 *b0, + float32 *r1, float32 *g1, float32 *b1); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/DPLTYPES.H b/CODE/RP/MUNGA_L4/libDPL/dpl/DPLTYPES.H new file mode 100644 index 0000000..65733b0 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/DPLTYPES.H @@ -0,0 +1,387 @@ +/***************************************************************************** + + PROJECT: + dPL + + FILE: + dpltypes.h + + CONTENTS: + Public type definitions for the dPL library. + +*****************************************************************************/ + +#ifndef _DPL_TYPES_H +#define _DPL_TYPES_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* dpl_TYPE definitions are used as tokenised identifiers for the various + coarse dPL database elements. */ + +typedef enum dpl_TYPE +{ + dpl_type_error, + dpl_type_scene, + dpl_type_zones, + dpl_type_view, + dpl_type_instance, + dpl_type_dcs, + dpl_type_light, + dpl_type_object, + dpl_type_lod, + dpl_type_geogroup, + dpl_type_geometry, + dpl_type_material, + dpl_type_texture, + dpl_type_texmap, + dpl_type_ramp +} dpl_TYPE; + +/* dpl_LIGHT_TYPE definitions are light type tokens identifying the behaviour + of a particular dPL light. */ + +typedef enum dpl_LIGHT_TYPE +{ + dpl_light_type_error, + dpl_light_type_disable, + dpl_light_type_ambient, + dpl_light_type_directional, + dpl_light_type_point, + dpl_light_type_conical +} dpl_LIGHT_TYPE; + +/* dpl_GEO_TYPE indicates which form of data a geometry database element + represents. */ + +typedef enum dpl_GEO_TYPE +{ + dpl_geo_type_error, + dpl_geo_type_empty, + dpl_geo_type_tristrip, + dpl_geo_type_polystrip, + dpl_geo_type_polygon, + dpl_geo_type_pmesh, + dpl_geo_type_string, + dpl_geo_type_lines, + dpl_geo_type_polyline, + dpl_geo_type_polypoints, + dpl_geo_type_spheres +} dpl_GEO_TYPE; + +/* dpl_ISECT_MODE is used to determine how detailed an intersection + calculation is to be performed by the renderer for a given instance, + providing a means of controlling the amount of time taken to obtain + intersection information. */ + +typedef enum dpl_ISECT_MODE +{ + dpl_isect_mode_error, + dpl_isect_mode_obj, + dpl_isect_mode_geogroup, + dpl_isect_mode_geometry +} dpl_ISECT_MODE; + +/* dpl_MORPH_MODE selects a mode of interpolation between the low level + geometry. */ + +typedef enum dpl_MORPH_MODE +{ + dpl_morph_mode_error, + dpl_morph_mode_simple, + dpl_morph_mode_blend +} dpl_MORPH_MODE; + +/* dpl_TEX_PROP are the various properties of a texture which may be + manipulated to control a texmaps application over polygons. */ + +typedef enum dpl_TEX_PROP +{ + dpl_tex_prop_error, + dpl_tex_prop_spheremap, + dpl_tex_prop_wrap, + dpl_tex_prop_wrapu, + dpl_tex_prop_wrapv, + dpl_tex_prop_minfilter, + dpl_tex_prop_magfilter, + dpl_tex_prop_alpha, + dpl_tex_prop_detail, + dpl_tex_prop_reduce, + dpl_tex_prop_bitslice +} dpl_TEX_PROP; + +/* dpl_TEX_VALUE are the values which may be assigned to the texture property + fields in a texture elements. */ + +typedef enum dpl_TEX_VALUE +{ + dpl_tex_value_error, + dpl_tex_value_on, + dpl_tex_value_off, + dpl_tex_value_repeat, + dpl_tex_value_clamp, + dpl_tex_value_select, + dpl_tex_value_blend, + dpl_tex_value_cut, + dpl_tex_value_blendcut, + dpl_tex_value_point, + dpl_tex_value_bilinear, + dpl_tex_value_trilinear, + dpl_tex_value_bicubic, + dpl_tex_value_sharpen, + dpl_tex_value_mipmap_point, + dpl_tex_value_mipmap_linear, + dpl_tex_value_mipmap_bilinear, + dpl_tex_value_mipmap_trilinear, + dpl_tex_value_mipmap_quadlinear, + dpl_tex_value_slice_mode0, + dpl_tex_value_slice_mode1, + dpl_tex_value_slice_mode2, + dpl_tex_value_slice_mode3, + dpl_tex_value_slice_mode4, + dpl_tex_value_slice_mode5, + dpl_tex_value_slice_mode6, + dpl_tex_value_slice_mode7, + dpl_tex_value_slice_mode8 +} dpl_TEX_VALUE; + +/* dpl_RENDER_PROP specifies global rendering properties which may be set to + affect output in all views. */ + +typedef enum dpl_RENDER_PROP +{ + dpl_render_prop_error, + dpl_render_prop_wireframe, + dpl_render_prop_report, + dpl_render_prop_singlebuffer, + dpl_render_prop_framerate, + dpl_render_prop_antialias, + dpl_render_prop_windowed, + dpl_render_prop_textured, + dpl_render_prop_LODscale, + dpl_render_prop_phase +} dpl_RENDER_PROP; + +/* dpl_RENDER_VALUE defines the values which may be used to set the render + properties. */ + +typedef enum dpl_RENDER_VALUE +{ + dpl_render_value_error, + dpl_render_value_on, + dpl_render_value_off, + dpl_render_value_increase, + dpl_render_value_decrease, + dpl_render_value_lock, + dpl_render_value_float, + dpl_render_value_free, + dpl_render_value_limit +} dpl_RENDER_VALUE; + +/* dpl_VERTEX_TYPE definitions are light type tokens identifying the behaviour + of a particular dPL light. */ + +typedef enum dpl_VERTEX_TYPE +{ + dpl_vertex_type_error = 0x00, + dpl_vertex_coord = 0x01, + dpl_vertex_normal = 0x02, + dpl_vertex_rgba = 0x04, + dpl_vertex_luminance = 0x08, + dpl_vertex_texture2D = 0x10, + dpl_vertex_texture3D = 0x20, + dpl_vertex_radius = 0x40 +} dpl_VERTEX_TYPE; + +/* dpl_REORIENT_AXES may be combined with an OR operation to switch billboard + axes at DCS nodes. */ + +typedef enum dpl_REORIENT_AXES +{ + dpl_reorient_axes_none = 0x00, + dpl_reorient_axes_x = 0x01, + dpl_reorient_axes_y = 0x02, + dpl_reorient_axes_z = 0x04 +} dpl_REORIENT_AXES; + +/* dpl_EFFECT_TYPE definitions are used in high level requests for specific + types of effect from the dpl renderer. */ + +typedef enum dpl_EFFECT_TYPE +{ + dpl_effect_type_explosion, + dpl_effect_type_particlestart, + dpl_effect_type_particlestop, + dpl_effect_type_particle +} dpl_EFFECT_TYPE; + +/* dpl_WARN_LEVEL defines the various warning levels avaliable from the + renderer */ + +typedef enum dpl_WARN_LEVEL +{ + dpl_warn_fatal, + dpl_warn_warn, + dpl_warn_notice, + dpl_warn_info, + dpl_warn_debug, + dpl_warn_fp_debug +} dpl_WARN_LEVEL; + +/* dpl_FOG_TYPE defines the various types of fog which can be applied to + a dpl_VIEW, support for the various types is platform dependent */ +typedef enum dpl_FOG_TYPE +{ + dpl_fog_type_error, /* error (feedback from querry) */ + dpl_fog_type_off, /* turn off fog for view */ + dpl_fog_type_vertex_lin, /* apply linear fog per vertex */ + dpl_fog_type_vertex_exp, /* exponential fog */ + dpl_fog_type_vertex_exp2, /* exponential squared fog */ + dpl_fog_type_pixel_lin, /* apply linear fog per pixel */ + dpl_fog_type_pixel_exp, /* exponential fog */ + dpl_fog_type_pixel_exp2 /* exponential squared fog */ +} dpl_FOG_TYPE; + +typedef struct s_dpldcs dpl_DCS; + +typedef struct s_dplview dpl_VIEW; + +typedef struct s_dpllight dpl_LIGHT; + +typedef struct s_dplzone dpl_ZONE; + +typedef struct s_dplmtl dpl_MATERIAL; + +typedef struct s_dplramp dpl_RAMP; + +typedef struct s_dpltexture dpl_TEXTURE; + +typedef struct s_dpltexmap dpl_TEXMAP; + +typedef struct s_dplinstance dpl_INSTANCE; + +typedef struct s_dplobject dpl_OBJECT; + +typedef struct s_dpllod dpl_LOD; + +typedef struct s_dplgeogroup dpl_GEOGROUP; + +typedef struct s_dplgeometry dpl_GEOMETRY; + +typedef void *dpl_LOAD_FUNCTION(char8 *); + +typedef struct dpl_EXPLOSION_EFFECT_INFO { + float32 x, y, z; /* positional information */ + int32 type; /* existing explosion options */ + dpl_TEXTURE *tex; /* explosion texture */ +} dpl_EXPLOSION_EFFECT_INFO; + +typedef struct dpl_PARTICLESTART_EFFECT_INFO { + int32 identifier; /* the identifying tag of this effect */ + + int32 maximum_issue; /* maximum number to be released */ + float32 release_period; /* the period for which particles will be + released */ + float32 rate; /* the rate at which particles will be + released */ + + float32 px, py, pz, pv; /* position of release and radius of the + variation in position */ + + float32 velx, vely, velz; /* initial velocity of particles */ + float32 velxv, velyv, velzv; /* variation of particle velocity */ + + float32 rad, radv; /* size of particle radius and variation in + the particle radius */ + float32 exp, expv; /* rate of expansion and variation in that + rate */ + float32 dexp, dexpv; /* rate of change of expansion and variation + in that rate */ + + float32 accelx, accely, accelz; /* acceleration of particles */ + float32 accelxv, accelyv, accelzv;/* and its variation */ + float32 atten, attenv; /* resistance to particle motion and it's + variation*/ + + float32 sRi, sGi, sBi, sAi; /* start colour interior */ + float32 sRiv, sGiv, sBiv, sAiv; /* and its variation */ + float32 sRo, sGo, sBo, sAo; /* start colour exterior */ + float32 sRov, sGov, sBov, sAov; /* and its variation */ + + float32 eRi, eGi, eBi, eAi; /* end colour interior */ + float32 eRiv, eGiv, eBiv, eAiv; /* and its variation */ + float32 eRo, eGo, eBo, eAo; /* end colour exterior */ + float32 eRov, eGov, eBov, eAov; /* and its variation */ + + float32 colour_warp; /* a warp factor allowing the interpolation + of the above colours to be weighted towards + the beginning or end using a gamma function + 1.0 = no weighting */ + + float32 alpha_warp; /* a warp factor for alpha (as above) */ + + float32 dur, durv; /* duration and variation in duration of + particles */ + + dpl_TEXTURE *tex; /* particle texture (if supported) */ +} dpl_PARTICLESTART_EFFECT_INFO; + +typedef struct dpl_PARTICLESTOP_EFFECT_INFO { + int32 identifier; /* the identifying tag of all effects + you want to stop */ +} dpl_PARTICLESTOP_EFFECT_INFO; + +typedef struct dpl_PARTICLE_EFFECT_INFO { + float32 px, py, pz; /* position of release */ + float32 velx, vely, velz; /* initial velocity of particle */ + float32 rad; /* size of particle radius */ + float32 exp; /* rate of expansion */ + float32 dexp; /* rate of change of expansion and variation */ + + float32 accelx, accely, accelz; /* acceleration of particle */ + + float32 atten; /* resistance to particle motion */ + + float32 sRi, sGi, sBi, sAi; /* start colour interior */ + float32 sRo, sGo, sBo, sAo; /* start colour exterior */ + + float32 eRi, eGi, eBi, eAi; /* end colour interior */ + float32 eRo, eGo, eBo, eAo; /* end colour exterior */ + + float32 colour_warp; /* a warp factor allowing the interpolation + of the above colours to be weighted towards + the beginning or end using a gamma function + 1.0 = no weighting */ + + float32 alpha_warp; /* a warp factor for alpha (as above) */ + + float32 dur; /* duration of particle */ + + dpl_TEXTURE *tex; /* particle texture (if supported) */ +} dpl_PARTICLE_EFFECT_INFO; + +typedef struct dpl_STATISTICS { + float32 framerate; +} dpl_STATISTICS; + +typedef struct dpl_STATUS { + int32 state; +} dpl_STATUS; + +typedef struct dpl_CAPABILITY { + /* is textured rendering supported */ + int32 textured_rendering; + /* is texture font specification supported */ + int32 font_texture_update; +} dpl_CAPABILITY; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/DPLUTILS.H b/CODE/RP/MUNGA_L4/libDPL/dpl/DPLUTILS.H new file mode 100644 index 0000000..e0e54c2 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/DPLUTILS.H @@ -0,0 +1,408 @@ +/* + * ---------------------------------------------------------------------------- + * + * Copyright 1994 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: dplutils.h,v $ + * Revision : $Revision: 1.3 $ + * Date : $Date: 1995/05/19 09:23:43 $ + * Author : $Author: nga $ + * + * Description : + * + * Notes : + * + * History : + * + * $Log: dplutils.h,v $ + * Revision 1.3 1995/05/19 09:23:43 nga + * Added texture enable/disable functions. + * + * Revision 1.2 1995/04/26 20:09:51 nga + * Added "special" functions. + * + * Revision 1.1 1995/03/10 15:58:16 nga + * Initial revision + * + * ---------------------------------------------------------------------------- + */ + +#ifndef _DPLUTILS_H +#define _DPLUTILS_H + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * !!! - temporary definitions to make PP5 build. + */ + +#define dpl_SetExtnGeoLoadFunc dpl_SetExtnObjectLoadFunc +#define dpl_SetExtnTexLoadFunc dpl_SetExtnTexmapLoadFunc +#define dpl_b2zRead NULL + + +/* + * Types. + */ + +/* dPL load mode. */ +typedef enum +{ + dpl_load_normal = 0x00, + dpl_load_nocache = 0x01, + dpl_load_noload = 0x02, + dpl_load_noreference = 0x04 +} dpl_LOAD_MODE; + +/* dPL look up mode. */ +typedef enum +{ + dpl_lookup_normal = 0x00, + dpl_lookup_nocreate = 0x01, + dpl_lookup_define = 0x02, + dpl_lookup_noreference = 0x04 +} dpl_LOOKUP_MODE; + +/* dPL path type. */ +typedef enum +{ + dpl_path_system, + dpl_path_user, + dpl_path_offset +} dpl_PATH_TYPE; + +/* dPL create/delete callback function type. */ +typedef void (dpl_CREATE_DELETE_CALLBACK)(dpl_TYPE type, void *handle); + +/* dPL special callback function type. */ +typedef void (dpl_SPECIAL_CALLBACK)(dpl_TYPE type, void *handle, + char8 *special, uint32 special_len); + +/* dPL material name callback function type. */ +typedef char8 *(dpl_MATERIAL_NAME_CALLBACK)(char8 *mat_name); + + +/* + * Prototypes. + */ + +extern void +dpl_SetObjectFileCacheSize(uint32 size); + +extern uint32 +dpl_GetObjectFileCacheSize(void); + +extern void +dpl_SetTexmapFileCacheSize(uint32 size); + +extern uint32 +dpl_GetTexmapFileCacheSize(void); + +extern void +dpl_SetMaterialFileCacheSize(uint32 size); + +extern uint32 +dpl_GetMaterialFileCacheSize(void); + +extern void +dpl_SetMaterialItemCacheSize(uint32 size); + +extern uint32 +dpl_GetMaterialItemCacheSize(void); + +extern void +dpl_SetHandleCacheSize(uint32 size); + +extern uint32 +dpl_GetHandleCacheSize(void); + +/* Add a path to object search path. */ +extern void +dpl_AddToObjectFilePath(char8 *path, dpl_PATH_TYPE type); + +/* Set entire object search path. */ +extern void +dpl_SetObjectFilePath(char8 *sys_path, char8 *user_path, char8 *offset); + +/* Get entire object search path. */ +extern char8 * +dpl_GetObjectFilePath(void); + +/* Associate an extension with a object load function. */ +extern void +dpl_SetExtnObjectLoadFunc(char8 *extn, dpl_LOAD_FUNCTION *load_func); + +/* Get a load function associated with an extension. */ +extern dpl_LOAD_FUNCTION * +dpl_GetExtnObjectLoadFunc(char8 *e); + +/* Get object file extensions. */ +extern char8 * +dpl_GetObjectFileExtns(void); + +/* Add a path to texmap search path. */ +extern void +dpl_AddToTexmapFilePath(char8 *path, dpl_PATH_TYPE type); + +/* Set entire texmap search path. */ +extern void +dpl_SetTexmapFilePath(char8 *sys_path, char8 *user_path, char8 *offset); + +/* Get entire texmap search path. */ +extern char8 * +dpl_GetTexmapFilePath(void); + +/* Associate an extension with a texmap load function. */ +extern void +dpl_SetExtnTexmapLoadFunc(char8 *extn, dpl_LOAD_FUNCTION *load_func); + +/* Get a load function associated with an extension. */ +extern dpl_LOAD_FUNCTION * +dpl_GetExtnTexmapLoadFunc(char8 *e); + +/* Get texmap file extensions. */ +extern char8 * +dpl_GetTexmapFileExtns(void); + +/* Add a path to material search path. */ +extern void +dpl_AddToMaterialFilePath(char8 *path, dpl_PATH_TYPE type); + +/* Set entire material search path. */ +extern void +dpl_SetMaterialFilePath(char8 *sys_path, char8 *user_path, char8 *offset); + +/* Get entire material search path. */ +extern char8 * +dpl_GetMaterialFilePath(void); + +/* Set texture load enable. */ +void +dpl_SetTextureLoadEnable(int32 i); + +/* Get texture load enable. */ +int32 +dpl_GetTextureLoadEnable(void); + +/* Set detail texture load enable. */ +void +dpl_SetDetailTextureLoadEnable(int32 i); + +/* Get detail texture load enable. */ +int32 +dpl_GetDetailTextureLoadEnable(void); + + +/* + * Built-in load functions. + */ + +/* bgf object file reader. */ +extern void * +dpl_bgfRead(char8 *); + +/* vtx texmap file reader. */ +extern void * +dpl_vtxRead(char8 *); + +/* SGI texmap file reader. */ +extern void * +dpl_sgiRead(char8 *); + +/* TGA texmap file reader. */ +extern void * +dpl_tgaRead(char8 *); + + +/* + * Find file & perform the loading function, based on extension returning + * NULL where the load fails. + */ + +extern dpl_OBJECT * +dpl_LoadObject(char8 *fname, dpl_LOAD_MODE mode); + +extern void +dpl_UnloadObject(dpl_OBJECT *o); + +extern dpl_TEXMAP * +dpl_LoadTexmap(char8 *fname, dpl_LOAD_MODE mode); + +extern void +dpl_UnloadTexmap(dpl_TEXMAP *t); + + +/* + * dPL lookup functions. + */ + +extern dpl_MATERIAL * +dpl_LookupMaterial(char8 *name, dpl_LOOKUP_MODE mode, int32 *status); + +extern void +dpl_ReferenceMaterial(dpl_MATERIAL *m); + +extern void +dpl_UnreferenceMaterial(dpl_MATERIAL *m); + +extern char8 * +dpl_LookupMaterialName(dpl_MATERIAL *m); + +extern dpl_MATERIAL * +dpl_GetFirstMaterial(char8 **name); + +extern dpl_MATERIAL * +dpl_GetNextMaterial(char8 **name); + +extern dpl_TEXTURE * +dpl_LookupTexture(char8 *name, dpl_LOOKUP_MODE mode, int32 *status); + +extern void +dpl_ReferenceTexture(dpl_TEXTURE *t); + +extern void +dpl_UnreferenceTexture(dpl_TEXTURE *t); + +extern char8 * +dpl_LookupTextureName(dpl_TEXTURE *t); + +extern dpl_TEXTURE * +dpl_GetFirstTexture(char8 **name); + +extern dpl_TEXTURE * +dpl_GetNextTexture(char8 **name); + +extern dpl_RAMP * +dpl_LookupRamp(char8 *name, dpl_LOOKUP_MODE mode, int32 *status); + +extern void +dpl_ReferenceRamp(dpl_RAMP *r); + +extern void +dpl_UnreferenceRamp(dpl_RAMP *r); + +extern char8 * +dpl_LookupRampName(dpl_RAMP *r); + +extern dpl_RAMP * +dpl_GetFirstRamp(char8 **name); + +extern dpl_RAMP * +dpl_GetNextRamp(char8 **name); + +extern dpl_LOD * +dpl_LookupLod(dpl_OBJECT *object, char8 *name, dpl_LOOKUP_MODE mode, + int32 *status); + +extern void +dpl_ReferenceLod(dpl_LOD *l); + +extern void +dpl_UnreferenceLod(dpl_LOD *l); + +extern char8 * +dpl_LookupLodName(dpl_LOD *l); + +extern dpl_LOD * +dpl_GetFirstLod(char8 **name); + +extern dpl_LOD * +dpl_GetNextLod(char8 **name); + +extern dpl_GEOGROUP * +dpl_LookupGeogroup(dpl_OBJECT *object, char8 *name, dpl_LOOKUP_MODE mode, + int32 *status); + +extern void +dpl_ReferenceGeogroup(dpl_GEOGROUP *g); + +extern void +dpl_UnreferenceGeogroup(dpl_GEOGROUP *g); + +extern dpl_GEOGROUP * +dpl_GetFirstGeogroup(char8 **name); + +extern dpl_GEOGROUP * +dpl_GetNextGeogroup(char8 **name); + +extern char8 * +dpl_LookupGeogroupName(dpl_GEOGROUP *g); + +extern char8 * +dpl_LookupGeogroupSpecial(dpl_GEOGROUP *g, uint32 *len); + +extern char8 * +dpl_LookupObjectFileName(dpl_OBJECT *o); + +extern char8 * +dpl_LookupObjectName(dpl_OBJECT *o); + +extern char8 * +dpl_LookupObjectSpecial(dpl_OBJECT *o, uint32 *len); + +extern char8 * +dpl_LookupTexmapFileName(dpl_TEXMAP *t); + + +/* + * dPL callback function. + */ + +extern void +dpl_SetCreateNodeCallback(dpl_CREATE_DELETE_CALLBACK *func); + +extern dpl_CREATE_DELETE_CALLBACK * +dpl_GetCreateNodeCallback(void); + +extern void +dpl_SetDeleteNodeCallback(dpl_CREATE_DELETE_CALLBACK *func); + +extern dpl_CREATE_DELETE_CALLBACK * +dpl_GetDeleteNodeCallback(void); + +extern void +dpl_SetSpecialCallback(dpl_SPECIAL_CALLBACK *func); + +extern dpl_SPECIAL_CALLBACK * +dpl_GetSpecialCallback(void); + +extern void +dpl_SetMaterialNameCallback(dpl_MATERIAL_NAME_CALLBACK *func); + +extern dpl_MATERIAL_NAME_CALLBACK * +dpl_GetMaterialNameCallback(void); + + +/* + * dPL error and warning message function. + */ + +extern void +dpl_SetWarnLogFile(FILE *fp); + +extern void +dpl_Warn(dpl_WARN_LEVEL l, char8 *format, ...); + + +/* + * dPL Utilities version. + */ + +extern char8 * +dpl_UtilsVersion(void); + +#ifdef __cplusplus +} +#endif + + +#endif /* _DPLUTILS_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_2D.H b/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_2D.H new file mode 100644 index 0000000..76259c5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_2D.H @@ -0,0 +1,123 @@ +#ifndef dpl_2d_h +#define dpl_2d_h +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define WORDS_PER_DISPLAY_CHUNK 30 + +typedef struct s_dpl2d_display { + void *remote; + struct s_dpl2d_display *next; + struct s_dpl2d_display *tail; + int32 size; + int32 open; + int32 data[WORDS_PER_DISPLAY_CHUNK]; +} dpl2d_DISPLAY; + +typedef enum dpl2d_OPEN_MODE +{ + dpl2d_open_mode_error, + dpl2d_open_mode_clear, + dpl2d_open_mode_append +} dpl2d_OPEN_MODE; + +typedef enum dpl2d_CLIP_MODE +{ + dpl2d_clip_mode_error, + dpl2d_clip_mode_OR, + dpl2d_clip_mode_AND, + dpl2d_clip_mode_XOR, + dpl2d_clip_mode_SET, + dpl2d_clip_mode_CLEAR +} dpl2d_CLIP_MODE; + +typedef int32 *dpl_2d_snapshot; + +typedef float32 dpl2d_MATRIX [6]; + +/* displaylist creation, destruction */ + +extern dpl2d_DISPLAY *dpl2d_NewDisplayList ( void ); + +extern int32 dpl2d_DeleteDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_OpenDisplayList ( dpl2d_DISPLAY *display, dpl2d_OPEN_MODE append ); + +extern int32 dpl2d_CloseDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_FlushDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenPolyline ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClosePolyline ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenLines ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddCloseLines ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenPolypoint ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClosePolypoint ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddPoint ( dpl2d_DISPLAY *display, float32 x, float32 y ); + +extern int32 dpl2d_AddCircle( dpl2d_DISPLAY *display, float32 x, float32 y, float32 r, int32 filled ); + +extern int32 dpl2d_AddPushState ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddPopState ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddSetColor ( dpl2d_DISPLAY *display, float32 r, float32 g, float32 b ); + +extern int32 dpl2d_AddSetAlpha ( dpl2d_DISPLAY *display, float32 a ); + +extern int32 dpl2d_AddSetMatrix ( dpl2d_DISPLAY *display, dpl2d_MATRIX ); + +extern int32 dpl2d_AddConcatMatrix ( dpl2d_DISPLAY *display, dpl2d_MATRIX, int32 post ); + +extern int32 dpl2d_AddSetLineWidth ( dpl2d_DISPLAY *display, + float32 w ); + +/* clip region support */ +extern int32 dpl2d_AddFullScreenClipRegion ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClearClipRegion ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenClipPolygon ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddCloseClipPolygon ( dpl2d_DISPLAY *display, + dpl2d_CLIP_MODE mode ); + +extern int32 dpl2d_AddClipCircle ( dpl2d_DISPLAY *display, + float32 x, float32 y, float32 rad, + dpl2d_CLIP_MODE mode ); + + +extern int32 dpl2d_AddCallDisplayList ( dpl2d_DISPLAY *display, + dpl2d_DISPLAY *sub_display ); + +extern int32 dpl2d_SetViewDisplayList ( dpl_VIEW *v, dpl2d_DISPLAY *disp ); + +extern dpl2d_DISPLAY *dpl2d_GetViewDisplayList ( dpl_VIEW *v ); + +/* and now the 2-D matrix support */ + +extern void dpl2d_IdMatrix ( dpl2d_MATRIX m ); +extern void dpl2d_TranslateMatrix ( dpl2d_MATRIX m, + float32 x, float32 y ); +extern void dpl2d_RotateMatrix ( dpl2d_MATRIX m, + float32 angle ); +extern void dpl2d_ScaleMatrix ( dpl2d_MATRIX m, + float32 sx, float32 sy ); +extern void dpl2d_ConcatMatrix ( dpl2d_MATRIX m, + dpl2d_MATRIX a, + dpl2d_MATRIX b ); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_PRIV.H b/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_PRIV.H new file mode 100644 index 0000000..3160f04 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_PRIV.H @@ -0,0 +1,531 @@ +#ifndef dpltyp_h +#define dpltyp_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpltypes.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Flesh out all the datatypes + + History : Rev 1.0, 18 / 06 / 1994 + 1.1, 22 / 06 / 1994 fixed unimplementable lists by + introducing dpl_superlist + 1.2, 27 / 06 / 1994 dislocated heirarchy from instances + and dropped back to matrix-only DCS + 2.0 16 / 11 / 1994 angusification started + + **************************** */ + +#include +#include + +#define OFF_SITE 1 + +#ifdef i860 +#define REMOTE 1 +#endif + +#define dpl_arg_sep '~' + +#define dcs_node_enable 0x1 +#define dcs_subtree_enable 0x2 +#define dcs_no_view_concat 0x4 + +#define dcs_billboard_x 0x8 +#define dcs_billboard_y 0x10 +#define dcs_billboard_z 0x20 +#define dcs_explode_geo 0x40 +#define dcs_ignore_geo 0x80 + +#define dcs_inherit_lmodel 0x100 +#define dcs_force_eval_lmodel 0x200 +#define dcs_near_field 0x400 +#define dcs_bounded 0x800 +#define dcs_backwards 0x1000 +#define dcs_uniform_scale 0x2000 + +#define dpl_draw_faceted 0x0000 +#define dpl_draw_smooth 0x0001 +#define dpl_draw_colored 0x0002 +#define dpl_draw_luminance 0x0004 +#define dpl_draw_textured 0x0008 +#define dpl_draw_3dtextured 0x0010 +#define dpl_draw_front 0x0200 +#define dpl_draw_back 0x0400 +#define dpl_draw_edges 0x0800 +#define dpl_draw_wireframe 0x1000 +#define dpl_draw_last 0x2000 +#define dpl_draw_envmapped 0x4000 +#define dpl_draw_flipped 0x8000 +#define dpl_draw_f_emissive 0x0020 +#define dpl_draw_b_emissive 0x0040 + +#define dpl_X 0 +#define dpl_Y 1 +#define dpl_Z 2 +#define dpl_W 3 + +#ifdef _DOS +#define dpl_path_separator '\\' +#else +#define dpl_path_separator '/' +#endif + +/* + NOTE in rpc implementations, the rather large overhead + of the dpl_node dplnode is never passed over to the + remote renderer, its just in the host space for management +*/ + +typedef struct s_dplnode* (*node_create_function)( void ); + +typedef struct s_dplnode { + int32 clean; + void *app_specific; + void *remote; /* this MUST be 1st word of REMOTE data */ + dpl_TYPE type_check; +} dpl_node; + +typedef struct s_dplremote_node { + void *remote; + dpl_TYPE type_check; +} dpl_remote_node; + +#ifdef REMOTE +#define dpl_node dpl_remote_node +#endif + +typedef struct s_dpl_chain_node { + dpl_node node; + struct s_dpl_chain_node *next_node; + struct s_dpldcs *dcs; +} dpl_chain_node; + +typedef int32 (*load_function)( dpl_node *, char * ); + +typedef struct s_dpllist { + dpl_node *item; + dpl_TYPE type_check; + struct s_dpllist *next; + struct s_dpllist *prev; +} dpl_list; + +/* + the dpl_superlist is used as the head node for + dpl_lists +*/ + +typedef struct s_dplsuperlist { + dpl_node *dplnode; + + dpl_list *last_accessed; + dpl_list *head; + dpl_list *tail; +} dpl_superlist; + +typedef float32 dpl_POINT [4]; +typedef float32 dpl_MATRIX[4][4]; + +typedef union { + double dbl_MATRIX[8]; + dpl_MATRIX matrix; +} dpl_dblMATRIX; + +/* introduce local datatypes */ + + +/* + +The renderer is currently blowing off way too much storage on the card, +which stands to sense when each polygon is around 144 bytes, 80 bytes for the +vertex and 64 for the connection structure. The currently unused datatypes +below will eventually attempt to buy back a lot of storage by moving away +from linked lists and towards packed structures + +*/ + + +typedef struct s_rvert { + dpl_POINT position; /* 0 */ + dpl_POINT normcol; /* 16 */ + float32 texcoords [3]; /* 32 */ + struct s_rvert *next; /* 44 */ + dpl_POINT xform_posn; /* 48 */ + float32 rendered_color[3]; /* 64 */ + int32 touched; /* 76 */ +} dpl_VERTEX; + +typedef struct s_conn { + struct s_conn *next; /* 0 */ + int32 n_verts; /* 4 */ + dpl_VERTEX* indices[6]; /* 8 */ + dpl_POINT planeEqn; /* 32 */ + float32 rendered_color[3]; /* 48 */ + int32 touched; /* 60 */ +} dpl_CONNECTION; + + +/* we will only use this structure for polys, not spheres, + so the W-coordinate (radius) holds the touched word + */ + +typedef struct s_ivert { + float32 position[3]; /* 3 */ + int32 touched; /* 4 */ + dpl_POINT normcol; /* 8 */ + float32 texcoords [2]; /* 10 total = 40 bytes */ +} dpl_idealVERTEX; + +typedef struct s_iconn { + dpl_POINT planeEqn; /* 4 */ + dpl_idealVERTEX* indices[6]; /* 10 */ +} dpl_idealCONNECTION; /* total 40 bytes */ + +typedef struct s_oconn { + float planeEqn[3]; + int touched; + int indices[6]; +} dpl_outputCONNECTION; /* total 40 bytes */ + + +/* + it looks like we can drop polygon storage down to 80 bytes + per poly, rather than 144, so we can achieve around 80% more + database storage + + the assumption is that we use connection[3] == NULL as the triangle + spotter. is this iffy? it lets us keep hexes for performance. + + planeEqn[3] = touched for output conns, so we have 32 bytes, giving + a 72 byte triangle and _doubling_ storage. + + in order to make this work, we will need a single PMESH of worst-case + size hanging round in memory. So xforming and lighting will no longer + happen in-place, but the destination for the work will always be the + same area of memory. So we'll get better cache and page coherence. + + It is recommended that we drop PMESH size from 6 to 4. + + The VERTEX pointers in the connection structure must now become + byte indices, so we just add on the base address of the VERTEX + structure. + + The only problem is special effects - the sphere effects are just dealt + with by keeping spherelists in the old vertex format; triangle effects + may be more difficult to deal with. + + */ + + + +/* flesh out the datatypes in dpltypes.h */ + +#if 0 +struct s_dpl_statistics { + float32 polys_in_last_frame; + float32 last_edit_time; + float32 last_cull_time; + float32 last_frame_time; + float32 last_frame_time_sb; + float32 polys_per_second; + float32 polys_per_second_sb; +} dpl_STATISTICS; + +#endif + +struct s_dpldcs { + dpl_node dplnode; + dpl_chain_node *nodes; + struct s_dplzone *zone; + dpl_MATRIX matrix; + int32 traversal; /* overload billboards in here for compactness */ + struct s_dpldcs *parent; + struct s_dpldcs *sibling; + struct s_dpldcs *child; + int32 lighting_mask; + dpl_POINT bounds[2]; +#ifdef REMOTE + dpl_dblMATRIX invModel; + float sphere_scale, sphere_big_scale; +#endif +} ; +struct s_dplzone { + dpl_node dplnode; + + int32 view_enable; +} ; +struct s_dplview { + dpl_chain_node dplnode; + + int32 view_id; + int32 pipe; + float32 x0, y0, x1, y1, zeye; + float32 x_size, y_size; + float32 hither_clip; + float32 yon_clip; + float32 back_color[3]; + int32 fog_enable; + float32 fog[5]; /* near, phar, r, g, b */ + struct s_dplview *share_view; + void *display_2d; +} ; +struct s_dpllight { + dpl_chain_node dplnode; + + dpl_LIGHT_TYPE light_type; + float32 color [3]; + float32 radius [2]; /* for radial lights */ + float32 umbra [2]; /* for conical lights */ + int32 lighting_mask; +#ifdef REMOTE + float32 position[3]; +#endif +}; +struct s_dpltexture { + dpl_node dplnode; + + struct s_dpltexmap *texmap; + + int32 minify; + int32 magnify; + int32 alpha; + int32 wrap_u; + int32 wrap_v; + int32 detail; + float32 u0; + float32 v0; + float32 du; + float32 dv; + float32 animate_time; + int32 bitslice; + int32 delta_size; + int32 delta_offs; +}; +struct s_dpltexmap { + dpl_node dplnode; + + int32 *texels; + int32 u_size; + int32 v_size; + int32 bits_per_texel; + int32 alpha; +#ifdef REMOTE + int32 hwareSize; + int32 hwareOffs; + int32 bilinear; + void *cell; +#endif +}; +struct s_dplmtl { + dpl_node dplnode; + + struct s_dpltexture *texture; + struct s_dpltexture *environment; + int32 immunity; + struct s_dplramp *ramp; + float32 emissive [3]; + float32 ambient [3]; + float32 diffuse [3]; + float32 opacity [3]; + float32 specular [4]; + float32 dither; +#ifdef REMOTE + float surf_opacity; + float *specular_table; + int32 pxpl5_cntl_word; + float du, dv; + float alpha_c, alpha_r; + int32 alpha_texture; + int32 cull_frame; +#endif +}; +struct s_dplramp { + dpl_node dplnode; + + float32 color0 [3]; + float32 color1 [3]; + int32 cntl_word; +}; +struct s_dplinstance { + dpl_chain_node dplnode; + + dpl_ISECT_MODE intersectmode; + int32 visibility; + struct s_dplobject *object; + struct s_dpllod *forcelod; + struct s_dplmtl *f_material; + struct s_dplmtl *b_material; + int32 intersect_mask; + int32 wireframe; +#ifdef REMOTE + int32 frame_count; + int32 last_LOD_index; +#endif +}; +#define MAX_LODS_PER_OBJECT 16 + +struct s_dplobject { + dpl_node dplnode; + + dpl_superlist lod_list; + dpl_POINT lod_hot_spot; + float32 lod_ranges[MAX_LODS_PER_OBJECT]; + float32 lod_fade_range; + int32 invalid_lods; + int32 clone; +#ifdef REMOTE + int32 lod_count; + float32 bounds[2][4]; + dpl_POINT sphere_bounds; +#endif +}; +struct s_dpllod { + dpl_node dplnode; + + float32 bounds[2][4]; + struct s_dplobject *parent; + dpl_superlist geogroup_list; + float32 hot_spot[3]; +#ifdef REMOTE + dpl_POINT sphere_bounds; +#endif +}; +struct s_dplgeogroup { + dpl_node dplnode; + + float32 bounds[2][4]; + struct s_dpllod *parent; + int32 draw_mode; + dpl_superlist geometry_list; + struct s_dplmtl *f_material; + struct s_dplmtl *b_material; + float32 decal_offs; + int32 lock; +#ifdef REMOTE + dpl_POINT sphere_bounds; + int32 clean; +#endif +}; +struct s_dplgeometry { + dpl_node dplnode; + + dpl_GEO_TYPE geometry_type; + dpl_VERTEX_TYPE vertex_type; + int32 num_vertices; + struct s_dplgeogroup *parent; + dpl_CONNECTION *connections; + dpl_VERTEX *vertices; + float lineWidth, pointSize; + +#ifdef REMOTE + int32 variable_alpha; + int32 n_connections; + int32 n_vertices; + dpl_CONNECTION *connection_tail; + dpl_VERTEX *vertex_tail; + int32 packed; +#endif + +}; +#if 0 +struct s_dpl_status { + int32 ok; +} dpl_STATUS; +#endif + + +/* ****************************************** + + BEWARE ! ! ! ! ! + + FOR REASONS OF STORAGE AND APPLICATIONS EFFICIENCY, THE FOLLOWING + DATA TYPES ARE N O T SUPERSETS OF DPL_NODE + + BE CAREFUL DEALING WITH VERTICES + +*/ + +/* typedefs for tracing performance */ + +typedef struct s_dpl_version { + int32 host; + int32 major_version; + int32 minor_version; + int32 firmware_major_version; + int32 firmware_minor_version; + char detailed[256]; +} dpl_VERSION; + +/* ********************************************************** + a scene contains a list of root-node dcs's, a list of zones + and a list of views + */ + +typedef struct s_dplscene { + dpl_node dplnode; + + dpl_superlist zone_list; + dpl_superlist view_list; + dpl_superlist dcs_list; + dpl_superlist light_list; +} dpl_SCENE; + +typedef enum { + dpl_artic_matrix, + dpl_artic_singleX, + dpl_artic_singleY, + dpl_artic_singleZ, + dpl_artic_quaternion +} dpl_ARTICULATION; + +/* additional geometry types - keep small for switch optim */ + +#define vpx_geo_type_f_t_dam 16 +#define vpx_geo_type_sca 17 +#define vpx_geo_type_undamage 18 +#define vpx_geo_type_f_t_undam 19 +#define vpx_geo_type_damage_set 20 + +#define dpl_morph_vertices 0x1 +#define dpl_morph_normals 0x2 +#define dpl_morph_texcoords 0x4 +#define dpl_morph_colors 0x8 + + + +typedef void (*vfptr)(); + +extern void * +dpl_svtRead(char8 *, int32 bilinear ); + +extern void * +dpl_bilRead(char8 *); + +extern void * +dpl_glmRead(char8 *); + +extern void +dpl_explodeTexels ( dpl_TEXMAP *tm, + int32 *dest_texels, + uint8 *src_texels, + int32 n_texels, + int32 start, int32 bilinear ); + + +#define POLY_FBITS 12 +#define SPHERE_FBITS 24 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_VPX.H b/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_VPX.H new file mode 100644 index 0000000..9c88d95 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/DPL_VPX.H @@ -0,0 +1,220 @@ +#ifndef dpl_vpx_h +#define dpl_vpx_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define VPX 1 +#include + +extern void +dpl_SetDeferredDeletes ( int32 d ); + +extern void +dpl_SetTextureScroll ( dpl_TEXTURE *t, float u, float v, float du, float dv ); + +extern void +dpl_SetGeomScaleFactor ( float32 geomscale ); + +extern void +dpl_SetDCSTraversal ( dpl_DCS *d, int32 trav ); + +extern void dpl_SetDCSXAxis ( dpl_DCS *d, float32 sin, float32 cos ); +extern void dpl_SetDCSYAxis ( dpl_DCS *d, float32 sin, float32 cos ); +extern void dpl_SetDCSZAxis ( dpl_DCS *d, float32 sin, float32 cos ); + +extern void +dpl_SetDCSQuaternion ( dpl_DCS *d, float32 *quaternion_stuff, float32 *xlate ); + +extern void +dpl_FlushDCSArticulations ( dpl_DCS **d ); + +extern void +dpl_SetObjectAdditiveLODs ( dpl_OBJECT *o ); + +extern void +dpl_SetMaterialDitherZ ( dpl_MATERIAL *m, float32 dither ); + +extern void +dpl_install_sfx ( int32 sfx_code, + dpl_TEXTURE *t, + int32 bang_type, + float frag_size, + float frag_velocity, + float vertical_bias, + float switch_off, + float cook_r, + float cook_g, + float cook_b, + float variance, + float gravity, + float cool, + float opacity_cool, + int32 fragments, + int32 iterations, + int32 immunity ); + +extern void +dpl_SetMaterialFogImmunity ( dpl_MATERIAL *m, int32 immunity ); + +extern void dpl_SetDCSExplodeGeo ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSIgnoreGeo ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSInheritLmodel ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSForceEvalLmodel ( dpl_DCS *d, int32 on ); + +extern void dpl_Damagize ( dpl_GEOGROUP *, dpl_MATERIAL *); +extern void dpl_UnDamagize ( dpl_GEOGROUP * ); +extern void dpl_Punchize ( dpl_GEOGROUP * ); +extern void dpl_Geometrize ( dpl_GEOMETRY *, int32 triangle_code ); + +extern dpl_INSTANCE * +dpl_RapidSectPixel ( float32 xp, float32 yp, + float32 radius, + uint32 mask, + float32 *xi, float32 *yi, float32 *zi, + dpl_DCS **d, dpl_GEOGROUP **gg, dpl_GEOMETRY ** g); + +extern void +dpl_RandomTable ( char *table ); + +extern int32 * +dpl_TouchNode ( int32 *list, void *n ); + +extern int32 +dpl_FlushNodes ( int32 *list ); + +extern void +dpl_SetMinRetraces ( int32 retraces ); + +extern void +dpl_KillEffectAtDCS ( dpl_DCS *dcs ); + +void +dpl_KillParticlefxRange ( int32 min, int32 max ); + +extern void +dpl_RedrawScene ( void ); + +extern void +dpl_PutAppSpecific ( void *node, void *app_specific ); + +extern void* +dpl_GetAppSpecific ( void *node ); + +extern void +dpl_MorphObject ( dpl_OBJECT *dest, + dpl_OBJECT *start, + dpl_OBJECT *end, + float32 alpha, + int32 morph_mode ); +extern void +dpl_MorphGeometry ( dpl_GEOMETRY *dest, + dpl_GEOMETRY *start, + dpl_GEOMETRY *end, + float32 alpha, + int32 morph_mode ); +extern void +dpl_MorphMaterial ( dpl_MATERIAL *dest, + dpl_MATERIAL *start, + dpl_MATERIAL *end, + float32 alpha, + int32 morph_mode ); + +extern void +dpl_TimedMorphObject ( dpl_OBJECT *dest, + dpl_OBJECT *start, + dpl_OBJECT *end, + float32 time, + int32 morph_mode, + float32 a, + float32 b, + float32 c, + float32 d ); +extern void +dpl_TimedMorphMaterial ( dpl_MATERIAL *dest, + dpl_MATERIAL *start, + dpl_MATERIAL *end, + float32 time, + int32 morph_mode, + float32 a, + float32 b, + float32 c, + float32 d ); + + +extern void dpl_SFXTexels2D ( dpl_TEXMAP *tm, + uint32 *texels ); + +extern void dpl_FakeTextureSize ( dpl_TEXTURE *t, int32 delta_size, int32 delta_offs ); + +extern void dpl_SetDCSLightingMask ( dpl_DCS *d, int32 mask ); +extern int32 dpl_GetDCSLightingMask ( dpl_DCS *d ); + +extern void dpl_SetLightLightingMask ( dpl_LIGHT *d, int32 mask ); +extern int32 dpl_GetLightLightingMask ( dpl_LIGHT *d ); + +extern void dpl_SetDCSNearField ( dpl_DCS *d, int32 on ); + +extern int32 +dpl_FreeMemory ( void ); + +extern int +dpl_bslReplace ( char8 *name, dpl_TEXTURE *tex ); + +extern void +dpl_tgaReplace(char8 *file, dpl_TEXTURE *tex ); + +extern void +dpl_DisableSyncOnCreate ( void ); + +extern void +dpl_EnableSyncOnCreate ( void ); + +extern void +dpl_SetDCSBound(dpl_DCS *d, float *minimax ); + +extern float32 +dpl_GetDCSBound(dpl_DCS *d ); + +extern void +dpl_PerfStats ( void ); + +extern void +dpl_SetLodStress ( float32 s ); + +extern +void dpl_SetGeogroupDrawLast(dpl_GEOGROUP *gg, int32 last_on); + +extern +int32 dpl_GetGeogroupDrawLast(dpl_GEOGROUP * gg); + +extern +void dpl_GetObjectBounds( dpl_OBJECT *o, float32 *b ); + +int32 +dpl_GetGeometryNumConnections(dpl_GEOMETRY *g ); + +void +dpl_GetGeometryConnections ( dpl_GEOMETRY *g, + int32 *v, + int32 offset, + int32 n ); + + +extern void +dpl_SetGeometryShadowVolume ( dpl_GEOMETRY *g ); + +extern void +dpl_SetGeometryLightVolume ( dpl_GEOMETRY *g, int imm ); + +extern void +dpl_CleanupGeogroup ( dpl_GEOGROUP *gg, int renorm_facets ); + +extern void +dpl_ReInit(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/MATRIX.H b/CODE/RP/MUNGA_L4/libDPL/dpl/MATRIX.H new file mode 100644 index 0000000..593d92c --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/MATRIX.H @@ -0,0 +1,47 @@ +#ifndef matrix_h +#define matrix_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpl.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Introduces all the datatypes and functions + used by the dpl interface + + History : Rev 1.0, 18 / 06 / 1994 + +**************************** */ + +#include +#include +#include + +extern void dpl_SetAngleMode( int degrees ); +extern void dpl_IdMatrix ( dpl_MATRIX m ); +extern void dpl_Translate ( dpl_MATRIX m, float32 dx, float32 dy, float32 dz ); +extern void dpl_Rotate ( dpl_MATRIX m, float32 angle, int32 axis ); +extern void dpl_Scale ( dpl_MATRIX m, float32 x, float32 y, float32 z ); +extern void dpl_Concat ( dpl_MATRIX m, dpl_MATRIX a, dpl_MATRIX b ); +extern void dpl_Invert ( dpl_MATRIX inverse, dpl_MATRIX mat ); +extern void dpl_XformPoint ( dpl_POINT q, dpl_POINT p, dpl_MATRIX m ); + +extern void dpl_IdMatrixDCS ( dpl_DCS *d ); +extern void dpl_TranslateDCS ( dpl_DCS *d, float32 dx, float32 dy, float32 dz ); +extern void dpl_RotateDCS ( dpl_DCS *d, float32 angle, int32 axis ); +extern void dpl_ScaleDCS ( dpl_DCS *d, float32 x, float32 y, float32 z ); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H new file mode 100644 index 0000000..5987cd5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H @@ -0,0 +1,33 @@ +#ifndef dpl_2dtag_h +#define dpl_2dtag_h + +typedef enum { + dpl2d_open_polyline, + dpl2d_close_polyline, + dpl2d_open_polypoint, + dpl2d_close_polypoint, + dpl2d_open_polygon, + dpl2d_close_polygon, + dpl2d_open_lines, + dpl2d_close_lines, + dpl2d_point, + dpl2d_circle, + + dpl2d_open_clip_polygon, + dpl2d_close_clip_polygon, + dpl2d_clip_circle, + dpl2d_clip_full, + dpl2d_clip_none, + + dpl2d_set_drawcolor, + dpl2d_set_matrix, + dpl2d_concat_matrix, + dpl2d_push_state, + dpl2d_pop_state, + + dpl2d_call_displaylist, + dpl2d_set_linewidth, + dpl2d_set_alpha +} dpl_2d_tag; + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H new file mode 100644 index 0000000..a41f650 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H @@ -0,0 +1,24 @@ +#ifndef dpl_mem_h +#define dpl_mem_h + +#ifdef __cplusplus +extern "C" { +#endif + +extern void *dpl_malloc ( int n_bytes ); +extern void *dpl_calloc ( size_t n, size_t size ); +extern void dpl_free ( void *ptr ); +extern void dpl_free_all ( void ); + +extern void dpl_tracemem ( void ); + +#ifndef dpl_mem_c +#define free dpl_free +#define malloc dpl_malloc +#define calloc dpl_calloc +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H new file mode 100644 index 0000000..593d92c --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H @@ -0,0 +1,47 @@ +#ifndef matrix_h +#define matrix_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpl.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Introduces all the datatypes and functions + used by the dpl interface + + History : Rev 1.0, 18 / 06 / 1994 + +**************************** */ + +#include +#include +#include + +extern void dpl_SetAngleMode( int degrees ); +extern void dpl_IdMatrix ( dpl_MATRIX m ); +extern void dpl_Translate ( dpl_MATRIX m, float32 dx, float32 dy, float32 dz ); +extern void dpl_Rotate ( dpl_MATRIX m, float32 angle, int32 axis ); +extern void dpl_Scale ( dpl_MATRIX m, float32 x, float32 y, float32 z ); +extern void dpl_Concat ( dpl_MATRIX m, dpl_MATRIX a, dpl_MATRIX b ); +extern void dpl_Invert ( dpl_MATRIX inverse, dpl_MATRIX mat ); +extern void dpl_XformPoint ( dpl_POINT q, dpl_POINT p, dpl_MATRIX m ); + +extern void dpl_IdMatrixDCS ( dpl_DCS *d ); +extern void dpl_TranslateDCS ( dpl_DCS *d, float32 dx, float32 dy, float32 dz ); +extern void dpl_RotateDCS ( dpl_DCS *d, float32 angle, int32 axis ); +extern void dpl_ScaleDCS ( dpl_DCS *d, float32 x, float32 y, float32 z ); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H new file mode 100644 index 0000000..1b36a00 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H @@ -0,0 +1,35 @@ +#ifndef tricoder_h +#define tricoder_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define triangle_intro_bits 0x0f + +#define triangle_opacity_intro 0x01 +#define triangle_unopacity_intro 0x02 +#define triangle_dmg_set_intro 0x03 +#define triangle_dmg_clear_intro 0x04 +#define triangle_sca_intro 0x05 +#define triangle_dmg2enbl_intro 0x06 +#define triangle_undmg2enbl_intro 0x07 +#define triangle_bright32_intro 0x08 +#define triangle_dark32_intro 0x09 +#define triangle_fifty_intro 0x0a +#define triangle_surfopacity_intro 0x0b +#define triangle_albright32_intro 0x0c +#define triangle_aldark32_intro 0x0d +#define triangle_albrightfog_intro 0x0e + +#define triangle_texture_bit 0x010 +#define triangle_dither_bit 0x020 +#define triangle_gouraud_bit 0x040 +#define triangle_enbl2dmg_bit 0x080 +#define triangle_white_bit 0x100 +#define triangle_emiss_bit 0x200 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H new file mode 100644 index 0000000..bcd5b4c --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H @@ -0,0 +1,95 @@ +#ifndef vr_prot_h +#define vr_prot_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum vr_action { + vr_init_action, + + vr_create_action, + vr_delete_action, + vr_flush_action, + + vr_sect_pixel_action, + vr_sect_vector_action, + + vr_dcs_nest_action, + vr_dcs_link_action, + vr_dcs_prune_action, + + vr_draw_scene_action, + vr_draw_scene_complete_action, + + vr_list_add_action, + vr_list_remove_action, + + vr_morph_action, + + vr_version_action, + vr_statistics_action, + vr_readpixels_action, + + vr_hspcode_action, + vr_860code_action, + vr_860data_action, + vr_860bss_action, + vr_860args_action, + + vr_set_geom_text_action, + vr_update_geom_verts_action, + vr_get_geom_verts_action, + vr_add_geom_connections_action, + vr_set_texmap_texels_action, + vr_sfx_action, + vr_install_sfx_action, + vr_psfx_action, + vr_install_psfx_action, + vr_flush_dcs_artic_action, + vr_damage_action, + vr_random_table_action, + vr_gamma_table_action, + vr_kill_sfx_action, + vr_geometrize_action, + vr_clone_object_action, + vr_set_sect_pixel_action, + vr_set_warning_action, + vr_set_render_prop_action, + vr_create_2d_display_action, + vr_delete_2d_display_action, + vr_flush_2d_display_action, + vr_freemem_action, + vr_sync_action, + vr_get_bounds_action, + vr_get_geom_connections_action, + vr_get_geom_numconnections_action, + vr_cleanup_gg_action, + vr_clear_dcs_action, + vr_remove_dcs_action, + vr_add_dcs_action +} vr_action; + +/* some i860 states for transputer-side monitoring */ + +#define state_vr_rcv_wait_lock 0 +#define state_vr_rcv_wait_ack 1 +#define state_vr_send_wait_lock 2 +#define state_vr_send_wait_ack 3 +#define state_vr_dma_wait_lock 4 +#define state_vr_dma_wait_ack 5 +#define state_vr_dma_spin_lock 6 +#define state_vr_texels_wait_lock 7 +#define state_vr_texels_wait_ack 8 +#define state_vr_texels_spin_lock 9 +#define state_vr_cull 10 +#define state_vr_draw 11 + +#define state_monitor 0 + +#define set_state(a,b,c) if (state_monitor) set_i860_state(a,b,c) +#define aux_state(a,b,c) if (state_monitor) set_i860_auxstate(a,b,c) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/vssver.scc b/CODE/RP/MUNGA_L4/libDPL/dpl/vpx/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..60709fae812d87d3fe87fb389b067b6b2d1b19c3 GIT binary patch literal 160 zcmXpJVq`d2=P%iL-obO(RqsctpMq-cUf|Shv|<2*CLn$PgBTm{OpDKqK#^u3zh}B( z(ZNecKY{oyK>p9plQ!}N$HDwoAYbJ5o@<%j=fM0nAU{j*fGfA)12DfG$gka!P@jJI eJDA@AIfcXIEr8DRN literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/dpl/vssver.scc b/CODE/RP/MUNGA_L4/libDPL/dpl/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..972051819c2960011e696ca7d1c39aa2b289d474 GIT binary patch literal 144 zcmXpJVq`d2=P%iL-obO(RqsctpMq-Ke6I3TS}}k@6_7Tb$t)Gf%lw%UC{hjN_e?h| z5?2%l^J{>7k=J{!CH{~H^J{_pEWHD+#h2B<{5l|iK8HnD?J8X`zaGe+86YstztsfH QZvgUZw, , ) + * + * $Log: divtypes.def,v $ + * Revision 2.3 1995/04/27 10:40:16 jeff + * *** empty log message *** + * + * Revision 2.2 1994/09/08 12:35:33 jeff + * added windows basic types. + * + * Revision 2.1 1994/04/08 13:50:14 jeff + * Importded from 2.0 tree. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#if defined (_WIN31) + +DEF_TYPE( CHAR8, char8, char) +DEF_TYPE( INT8, int8, signed char) +DEF_TYPE( UINT8, uint8, unsigned char) +DEF_TYPE( INT16, int16, signed int) +DEF_TYPE( UINT16, uint16, unsigned int) +DEF_TYPE( INT32, int32, signed long) +DEF_TYPE( UINT32, uint32, unsigned long) +DEF_TYPE( FLOAT32, float32, float) +DEF_TYPE( FLOAT64, float64, double) + +#else + +DEF_TYPE( CHAR8, char8, char) +DEF_TYPE( INT8, int8, signed char) +DEF_TYPE( UINT8, uint8, unsigned char) +DEF_TYPE( INT16, int16, signed short) +DEF_TYPE( UINT16, uint16, unsigned short) +DEF_TYPE( INT32, int32, signed int) +DEF_TYPE( UINT32, uint32, unsigned int) +DEF_TYPE( FLOAT32, float32, float) +DEF_TYPE( FLOAT64, float64, double) + +#endif + +/* + * Note we may need to put ifdefs back in here for some machines IE 64Bit + * processors ? + */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DIVTYPES.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DIVTYPES.H new file mode 100644 index 0000000..694be94 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DIVTYPES.H @@ -0,0 +1,73 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: vl + * MODULE: divtypes.h + * + * File: $RCSfile: divtypes.h,v $ + * Revision: $Revision: 2.11 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divtypes.h,v 2.11 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * + * This file contains standard type definitions used by all higher + * levels in the system. + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DIVTYPES_H +#define _DIVTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * mangle the divtypes.def file to get machine specific low level + * definitions for all our basic types. + */ +#define DEF_TYPE(a,b,c) typedef c b; +#include +#undef DEF_TYPE + +/* + * generate an enum list of all the symbolic values for the types. + */ +#define DEF_TYPE(a,b,c) a, +typedef enum dpDivType { +#include +LAST_TYPE +} dpDivType; +#undef DEF_TYPE +#define BASIC_TYPE_CNT ((int)LAST_TYPE) + +/* + * A structure to define the names etc of the basic types for internal + * use. + */ +typedef struct dpTypeSpec{ + char8 endian16[3]; + char8 endian32[5]; + struct { + char8 *name; + uint32 size; + uint32 alignment; + }Sizes[BASIC_TYPE_CNT]; +} dpTypeSpec; + +extern void dpGenDivTypes(dpTypeSpec *spec); + +#ifdef __cplusplus +} +#endif +#endif /* _DIVTYPES_H */ + + diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DIVVERS.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DIVVERS.H new file mode 100644 index 0000000..a7d07a5 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DIVVERS.H @@ -0,0 +1,54 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: dp + * MODULE: divvers.c + * + * File: $RCSfile: divvers.h,v $ + * Revision: $Revision: 1.6 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divvers.h,v 1.6 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * macro to aid the printing of version no's for components. + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DIVVERS_H +#define _DIVVERS_H + +#include +#define divVersion(filep,module,description,version) \ +do { \ + static int done = 0; \ + static char *vstring = "@(#)Division dVS. " module " - " description \ + ". Version " version ". " __DATE__ ; \ + if (done == 0) { \ + fprintf (stdout, "%s\n", &vstring [4]); \ + if (filep) \ + fprintf (filep, "%s\n", &vstring [4]); \ + } \ + done = 1; \ +} while (0) + +#define div3rdPartyVersion(filep,party,description,version,date) \ +do { \ + static int done = 0; \ + static char *vstring = party ". " description \ + ". Version " version ". " date ; \ + if (done == 0) { \ + fprintf (stdout, "%s\n", vstring); \ + if (filep) \ + fprintf (filep, "%s\n", vstring ); \ + } \ + done = 1; \ +} while (0) + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DLINK.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DLINK.H new file mode 100644 index 0000000..138f9b1 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DLINK.H @@ -0,0 +1,258 @@ +/******************************************************************************/ +/* */ +/* ###### ### # # ### ##### ### ####### # # */ +/* # # # # # # # # # # # ## # */ +/* # # # # # # # # # # # # # */ +/* # # # # # # ##### # # # # # # */ +/* # # # # # # # # # # # # # */ +/* # # # # # # # # # # # # ## */ +/* ###### ### # ### ##### ### ####### # # */ +/* */ +/* # ##### ##### ####### */ +/* ## # # # # # */ +/* # # # # # # # */ +/* # ###### ###### ###### */ +/* # # # # */ +/* # # # # # # # */ +/* ##### ##### ##### ##### */ +/* */ +/* Copyright (c) Division Limited. All rights reserved */ +/* */ +/* This Document may not, in whole or in part, be copied, photocopied, */ +/* reproduced, translated, or reduced to any electronic medium or machine */ +/* readable form without prior written consent from Division Ltd. */ +/* */ +/******************************************************************************/ + +#if !defined _DLINK_H_ +#define _DLINK_H_ + + +#if defined __cplusplus +extern "C" { +#endif + +/* This is the interface between dlink and the user. */ +/* It keeps track of which device we are talking to (via the */ +/* device driver file descriptor. It also keeps track of the protocol mode */ + +#if defined _UNIX + +typedef struct dbi_interface *DBI_INTERFACE_PTR; +typedef struct dbi_interface +{ + int fd; + int protocol; + +} DBI_INTERFACE; + +#else /* NOT _UNIX */ + +typedef void *DBI_INTERFACE_PTR; /* Redirect into the linkio structures */ + +#endif /* _UNIX */ + + + + + + + + + + + + +/* Open a dLink Device */ +/* On a success, returns a pointer that acts as a handle for all further operations. */ +/* When operations on this handle are finished, dlink_closeDevice should be called to */ +/* off any resources associated with the handle. In the unix world, dlink_initDevice */ +/* should be passed a filename that corresponds to the device being used. eg. /dev/dbi01 */ +/* Will return NULL, and print a message on error */ + +extern DBI_INTERFACE_PTR dlink_initDevice (char *deviceName); + + + + + + +/* Close a dLink Device */ +/* Attempts to free off any resources associated with a dLink device handle */ +/* which is passed into the routine. Returns 0 on success. On error, will print */ +/* a message and return (-1). */ +/* After a successful dlink_closeDevice, the dLink device pointer is no longer valid. */ + +extern int dlink_closeDevice (DBI_INTERFACE_PTR interface); + + + + + + +/* Reset the device associated with the dLink device handle. */ +/* This has the effect of resetting the hardware that is associated with the dLink */ +/* device handle passed into the routine. */ +/* Will return 0 on success, or print a message and return (-1) on error */ + +extern int dlink_resetDevice (DBI_INTERFACE_PTR interface); + + + + + + + +/* Write RAW data */ +/* Similar to the UNIX write system call. */ +/* Attempts to write nob bytes of data starting from the address in data to */ +/* the device associated with the dLink device handle passed in. */ +/* Returns the number of bytes written. */ +/* If an error occurs, will print a message and return (-1). */ + +extern int dlink_write (DBI_INTERFACE_PTR interface, char *data, unsigned int nob); + + + + + + + + + +/* Read RAW data */ +/* Similar to the UNIX read system call. */ +/* Attempts to read nob bytes of data starting to the address in data from */ +/* the device associated with the dLink device handle passed in. */ +/* Returns the number of bytes read. */ +/* If an error occurs, will print a message and return (-1). */ + +extern int dlink_read (DBI_INTERFACE_PTR interface, char *data, unsigned int nob); + + + + + + + + + +/* See if the link is ready */ +/* If there is input from the device waiting will return non-zero, */ +/* otherwise will return zero. */ +extern int dlink_inputReady (DBI_INTERFACE_PTR interface); + + + + + + + + + + + + + + + + + + +/* Send out a protocol packet */ +/* Attempts to send a protocol packet to the device associated with the dLink */ +/* device handle passed to the routine. */ +/* Parameters are as follows; + + interface dLink device handle. + data Address of data. + nob Number of bytes to send. Must be a multiple of 4, + and no more than 1020 bytes, as defined by the + protocol used. + protocolTag A protocol tag that will be interpreted by the + user code at the destination process. + target The ID of the destination process. Can be 0x0 to 0xFF, + where 0xFF is a broadcast message. + toIserver 0 for a non-Iserver message, 1 for a packet destined for + an Iserver. + needsFlipping. Specifies whether the data is affected by machine Endian + properties. If set to 1, dLink will automatically flip + the data on despatch. dLink will only do this if the + host machine is reverse endian to the destination. + If either needsFlipping is 0, or the host machined is the + same endian to the destination, no byte flipping is + performed. + + Returns 0 on success, or -1 and a message on error. */ + +extern int dlink_sendProtocolPacket (DBI_INTERFACE_PTR interface, + char *data, unsigned int nob, + int protocolTag, + int target, int toIserver, + int needsFlipping); + + + + + + + + +/* Receive a protocol packet */ +/* Attempts to read a protocol packet from the device associated with the dLink */ +/* device handle passed to the routine. */ +/* Parameters are as follows; + + interface dLink device handle. + data Address of where the data is to be read. + nob Pointer to the number of bytes actually received. + + protocolTag Currently not used. Pass in NULL. + target Pointer to the ID of the sender of the data. + toIserver Pointer saying whether the message was from an Iserver. + 1 will be placed here if the message is from an Iserver, + 0 otherwise. + needsFlipping. Specifies whether the data is affected by machine Endian + properties. If set to 1, dLink will automatically flip + the data on arrival. dLink will only do this if the + host machine is reverse endian to the destination. + If either needsFlipping is 0, or the host machined is the + same endian to the destination, no byte flipping is + performed. +*/ +/* Returns 0 on success, or -1 and a message on error. */ + +extern int dlink_recvProtocolPacket (DBI_INTERFACE_PTR interface, + char *data, unsigned int *nob, + int *protocolTag, + int *target, int *fromIserver, + int needsFlipping); + + + + + + + + + + +/* Switch dLink Error messages to come from the given */ +/* file descriptor. If the descriptor is NULL, then */ +/* error messages will be switched off */ +/* Parameters are as follows; + + fd Pointer to a file descriptor. If the pointer is NULL + then dlink error messages will be switched off, otherwise + dlink error messages will be sent over the given file + descriptor after the call. +*/ + +extern void dlink_setErrorFile (FILE *fd); + + +#if defined __cplusplus +} +#endif + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DM.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DM.H new file mode 100644 index 0000000..4b4c836 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DM.H @@ -0,0 +1,635 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: matrix/linear algebra mosdule + * MODULE: dmtypes.h + * + * File: $RCSfile: dm.h,v $ + * Revision: $Revision: 2.23 $ + * Date: $Date: 1995/05/18 09:46:38 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: dm.h,v 2.23 1995/05/18 09:46:38 jeff beta $ + * + * FUNCTION: + * This file contains the external declarations of the dm library + * routines and types. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DMTYPES_H +#define _DMTYPES_H + +#include + +#if defined(_TRANSPUTER) || defined(_I860) +/* + * These are not defined on transputers. + */ +#define M_E 2.71828182845904523540 +#define M_LOG2E 1.44269504088896340740 +#define M_LOG10E 0.43429448190325182765 +#define M_LN2 0.69314718055994530942 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.78539816339744830962 +#define M_1_PI 0.31830988618379067154 +#define M_2_PI 0.63661977236758134308 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.70710678118654752440 +#endif + +#ifdef _TRANSPUTER +#include +#else +#include +#endif + +#ifdef _I860 +#define const /*broken pgcc doesn't understand const properly*/ +#endif + +/* Windows mathf functions. */ +#if defined(_WIN31) || defined(_DOS) +#define fabsf(x) (float) fabs((double)(x)) +#define sqrtf(x) (float) sqrt((double)(x)) +#define sinf(x) (float) sin((double)(x)) +#define cosf(x) (float) cos((double)(x)) +#define asinf(x) (float) asin((double)(x)) +#define acosf(x) (float) acos((double)(x)) +#endif + + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +/* + * The basic linear algebra types. + */ +typedef enum { + DM_X = 0, + DM_Y = 1, + DM_Z = 2, + DM_W = 3, + DM_PITCH = 0, + DM_YAW = 1, + DM_ROLL = 2 +} dmIndex; + +typedef float32 dmVector[3]; +typedef float32 dmScale[3]; +typedef float32 dmPoint[3]; +typedef float32 dmEuler[3]; +typedef float32 dmQuaternion[4]; +typedef float32 dmMatrix[4][4]; + +typedef struct { + dmMatrix pos; + dmVector linearVel; + dmVector linearAccn; + dmVector angularVel; + dmVector angularAccn; +} dmPosition, *dmPosition_Ptr; + +/* + * Small value used to check floating point values for equality + * or smallness. This number is withing 2 bits of the smallest + * representable relative differance between two numbers. + */ +#define DM_EPSILON ((float32)(FLT_EPSILON * 4.0f)) + +/* + * fast macros for common ops. + */ +#define dmSqr(x) ((x) * (x)) + +#define dmCrossProd3(r,a,b) \ +do { \ + float32 _ax = (a)[DM_X], _bx = (b)[DM_X]; \ + float32 _ay = (a)[DM_Y], _by = (b)[DM_Y]; \ + float32 _az = (a)[DM_Z], _bz = (b)[DM_Z]; \ + \ + (r)[DM_X] = (_ay * _bz) - (_az * _by); \ + (r)[DM_Y] = (_az * _bx) - (_ax * _bz); \ + (r)[DM_Z] = (_ax * _by) - (_ay * _bx); \ +} while (0) + +#define dmDotProd3(x, y) ( ((x)[DM_X] * (y)[DM_X]) \ + + ((x)[DM_Y] * (y)[DM_Y]) \ + + ((x)[DM_Z] * (y)[DM_Z])) + +#define dmDotProd4(x, y) ( ((x)[DM_X] * (y)[DM_X]) \ + + ((x)[DM_Y] * (y)[DM_Y]) \ + + ((x)[DM_Z] * (y)[DM_Z]) \ + + ((x)[DM_W] * (y)[DM_W])) + +#define dmLength3(x) sqrtf( dmSqr(x[DM_X]) \ + +dmSqr(x[DM_Y]) \ + +dmSqr(x[DM_Z])) + +#define dmVectorCrossProd(r,a,b) dmCrossProd3((r),(a),(b)) +#define dmVectorDotProd(a,b) dmDotProd3((a),(b)) +#define dmVectorLength(a) dmLength3(a) + + + +#define dmScaleInvert(d,s) (((d)[DM_X] = 1.0f/(s)[DM_X]), \ + ((d)[DM_Y] = 1.0f/(s)[DM_Y]), \ + ((d)[DM_Z] = 1.0f/(s)[DM_Z])) + +#define dmVectorInvert(d,s) (((d)[DM_X] = -(s)[DM_X]), \ + ((d)[DM_Y] = -(s)[DM_Y]), \ + ((d)[DM_Z] = -(s)[DM_Z])) + + +#define dmDegToRad(x) ((x) * ((float32) M_PI / 180.0)) +#define dmRadToDeg(x) ((x) * ((float32) M_1_PI * 180.0)) + + + +/* + * Optimised and Safe trig functions. + */ +extern void dmSinCosf(float32 *s, + float32 *c, + float32 angle); +extern float32 dmSafeAtan2(float32 opposite, + float32 adjacent); + +/* + * Copy functions + */ +#ifdef _TRANSPUTER +#include +#define dmMatCopy(d,s) memcpy(d,s,sizeof(dmMatrix)) +#define dmQuatCopy(d,s) memcpy(d,s,sizeof(dmQuaternion)) +#define dmEulerCopy(d,s) memcpy(d,s,sizeof(dmEuler)) +#define dmVectorCopy(d,s) memcpy(d,s,sizeof(dmVector)) +#define dmPointCopy(d,s) memcpy(d,s,sizeof(dmPoint)) +#define dmScaleCopy(d,s) memcpy(d,s,sizeof(dmScale)) +#define dmPosCopy(d,s) ((d) = (s)) +#define __dmCopy3(d,s) memcpy(d,s,3 * sizeof(float32)) +#define __dmCopy4(d,s) memcpy(d,s,4 * sizeof(float32)) +#else +#define __dmCopy3(d,s) do { \ + (d)[DM_X] = (s)[DM_X]; \ + (d)[DM_Y] = (s)[DM_Y]; \ + (d)[DM_Z] = (s)[DM_Z]; \ +} while (0) + +#define __dmCopy4(d,s) do { \ + (d)[DM_X] = (s)[DM_X]; \ + (d)[DM_Y] = (s)[DM_Y]; \ + (d)[DM_Z] = (s)[DM_Z]; \ + (d)[DM_W] = (s)[DM_W]; \ +} while (0) + +#define dmMatCopy(d,s) do { \ + __dmCopy4((d)[DM_X],(s)[DM_X]); \ + __dmCopy4((d)[DM_Y],(s)[DM_Y]); \ + __dmCopy4((d)[DM_Z],(s)[DM_Z]); \ + __dmCopy4((d)[DM_W],(s)[DM_W]); \ +} while (0) + +#define dmQuatCopy(d,s) __dmCopy4(d,s) +#define dmEulerCopy(d,s) __dmCopy3(d,s) +#define dmVectorCopy(d,s) __dmCopy3(d,s) +#define dmPointCopy(d,s) __dmCopy3(d,s) +#define dmScaleCopy(d,s) __dmCopy3(d,s) + +#define dmPosCopy(d,s) (*(d) = *(s)) +#endif + +/* + * Ident functions. + */ +#define dmMatIdent(m) dmMatCopy(m, dmIdentM) +#define dmQuatIdent(q) dmQuatCopy(q, dmIdentQ) +#define dmEulerIdent(e) dmEulerCopy(e, dmIdentE) +#define dmVectorIdent(v) dmVectorCopy(v, dmIdentV) +#define dmPointIdent(p) dmPointCopy(p, dmIdentP) +#define dmScaleIdent(s) dmScaleCopy(s, dmIdentS) +#define dmPosIdent(p) dmPosCopy(p, &dmIdentPos) + +extern const dmMatrix dmIdentM; +extern const dmQuaternion dmIdentQ; +extern const dmEuler dmIdentE; +extern const dmVector dmIdentV; +extern const dmPoint dmIdentP; +extern const dmScale dmIdentS; +extern const dmPosition dmIdentPos; + +extern void (dmMatIdent)(dmMatrix mat); +extern void (dmQuatIdent)(dmQuaternion q); +extern void (dmEulerIdent)(dmEuler e); +extern void (dmVectorIdent)(dmVector s); +extern void (dmPointIdent)(dmPoint s); +extern void (dmScaleIdent)(dmScale s); +extern void (dmPosIdent)(dmPosition_Ptr p); + +/* + * initialisation functions + */ +#define dmEulerSet(e,p,y,r) ((e)[DM_PITCH] = (p), \ + (e)[DM_YAW] = (y), \ + (e)[DM_ROLL] = (r)) + +#define dmEulerSetD(e,p,y,r) ((e)[DM_PITCH] = dmDegToRad(p), \ + (e)[DM_YAW] = dmDegToRad(y), \ + (e)[DM_ROLL] = dmDegToRad(r)) + +#define dmQuatSet(q,x,y,z,w) ((q)[DM_X] = (x), \ + (q)[DM_Y] = (y), \ + (q)[DM_Z] = (z), \ + (q)[DM_W] = (w)) + +#define dmPointSet(p,x,y,z) ((p)[DM_X] = (x), \ + (p)[DM_Y] = (y), \ + (p)[DM_Z] = (z)) + +#define dmVectorSet(v,x,y,z) ((v)[DM_X] = (x), \ + (v)[DM_Y] = (y), \ + (v)[DM_Z] = (z)) + +#define dmScaleSet(s,x,y,z) ((s)[DM_X] = (x), \ + (s)[DM_Y] = (y), \ + (s)[DM_Z] = (z)) + + +extern void (dmEulerSet)(dmEuler e, + float32 pitch, + float32 yaw, + float32 roll); +extern void (dmEulerSetD)(dmEuler e, + float32 pitch, + float32 yaw, + float32 roll); +extern void (dmQuatSet)(dmQuaternion q, + float32 x, + float32 y, + float32 z, + float32 w); +extern void (dmPointSet)(dmPoint p, + float32 x, + float32 y, + float32 z); +extern void (dmVectorSet)(dmVector p, + float32 x, + float32 y, + float32 z); +extern void (dmScaleSet)(dmScale p, + float32 x, + float32 y, + float32 z); + +/* + * Matrix generation functions + */ +#define dmMatFromScale(m,s) do { \ + dmMatIdent(m); \ + (m)[DM_X][DM_X] = s[DM_X]; \ + (m)[DM_Y][DM_Y] = s[DM_Y]; \ + (m)[DM_Z][DM_Z] = s[DM_Z]; \ +} while (0) + +#define dmMatFromEuler(m,e) do { \ + dmQuaternion __q; \ + dmQuatFromEuler(__q,e); \ + dmMatFromQuat(m,__q); \ +} while (0) + +#define dmMatFromPoint(m,p) do { \ + dmMatIdent(m); \ + m[DM_W][DM_X] = p[DM_X]; \ + m[DM_W][DM_Y] = p[DM_Y]; \ + m[DM_W][DM_Z] = p[DM_Z]; \ +} while (0) + +#define dmMatFromPointEulerScale(m, p,e,s) do { \ + dmMatFromScale(m,s); \ + dmMatRotEuler(m,e); \ + m[DM_W][DM_X] = p[DM_X]; \ + m[DM_W][DM_Y] = p[DM_Y]; \ + m[DM_W][DM_Z] = p[DM_Z]; \ +} while (0) + +#define dmMatFromPointQuatScale(m, p,q,s) do { \ + dmMatFromScale(m,s); \ + dmMatRotQuat(m,q); \ + m[DM_W][DM_X] = p[DM_X]; \ + m[DM_W][DM_Y] = p[DM_Y]; \ + m[DM_W][DM_Z] = p[DM_Z]; \ +} while (0) + +extern void dmMatFromQuat( dmMatrix mat, + const dmQuaternion quat); +extern void dmMatFromGeneralQuat( dmMatrix mat, + const dmQuaternion quat); +extern void (dmMatFromEuler)( dmMatrix m, + const dmEuler e); +extern void (dmMatFromScale)( dmMatrix m, + const dmScale s); +extern void (dmMatFromPoint)( dmMatrix m, + const dmPoint p); +extern void (dmMatFromPointEulerScale)( dmMatrix m, + const dmPoint p, + const dmEuler e, + const dmScale s); +extern void (dmMatFromPointQuatScale)( dmMatrix m, + const dmPoint p, + const dmQuaternion q, + const dmScale s); + + + +/* + * matrix manipulation functions. + */ +#define dmMatRotQuat(m,q) do { \ + dmMatrix __m; \ + dmMatFromQuat(__m, (q)); \ + dmMatMultH((m),(m),__m); \ +} while (0) + +#define dmMatRotEuler(m, e) do { \ + dmMatrix __m; \ + dmMatFromEuler(__m,e); \ + dmMatMultH((m), (m), __m); \ +} while (0) + + +extern void dmMatRotX(dmMatrix m, + float32 angle); +extern void dmMatRotY(dmMatrix m, + float32 angle); +extern void dmMatRotZ(dmMatrix m, + float32 angle); + +extern void (dmMatRotEuler)( dmMatrix m, + const dmEuler e); +extern void (dmMatRotQuat)( dmMatrix m, + const dmQuaternion q); +extern void dmMatScale( dmMatrix m, + const dmScale s); + +extern void dmMatXlate( dmMatrix m, + const dmVector v); + +extern void dmMatInvertH( dmMatrix inv, + const dmMatrix mat); + +extern void dmMatMultH( dmMatrix res, + const dmMatrix left, + const dmMatrix right); + +extern int dmMatInvert( dmMatrix inv, + const dmMatrix mat); + +extern void dmMatMult( dmMatrix res, + const dmMatrix left, + const dmMatrix right); + +/* + * Quaternion manipulation ops. + */ +#define dmQuatNorm(x) do { \ + if ((x)[DM_W] < 0.0f) { \ + (x)[DM_X] = -(x)[DM_X]; \ + (x)[DM_Y] = -(x)[DM_Y]; \ + (x)[DM_Z] = -(x)[DM_Z]; \ + (x)[DM_W] = -(x)[DM_W]; \ + } \ +}while(0) + +extern void dmQuatInvert( dmQuaternion res, + const dmQuaternion q); +extern void dmQuatMult( dmQuaternion res, + const dmQuaternion left, + const dmQuaternion right); +extern void dmQuatMake( dmQuaternion quat, + const dmVector axis, + float32 angle); +extern void dmQuatMakeUnitAxis( dmQuaternion rot, + const dmVector axis, + float angle); +extern void (dmQuatNorm)(dmQuaternion q); + + +/* + * Conversions between Euler angles and + * quaternions. + */ + +extern void dmQuatFromEuler( dmQuaternion quat, + const dmEuler erot); + +extern void dmEulerFromQuat( dmEuler e, + const dmQuaternion q); + + +/* + * Functions to split matricies in various ways. + */ + +#define dmPointFromMat(p,m) dmPointQuatScaleFromMat((p), NULL, NULL, (m)) +#define dmScaleFromMat(s,m) dmPointQuatScaleFromMat(NULL, NULL, (s), (m)) +#define dmQuatFromMat(q,m) dmPointQuatScaleFromMat(NULL, (q), NULL, (m)) +#define dmEulerFromMat(e,m) dmPointEulerScaleFromMat(NULL, (e), NULL, (m)) + +extern int (dmQuatFromMat)( dmQuaternion quat, + const dmMatrix mat); +extern int (dmEulerFromMat)( dmEuler e, + const dmMatrix m); +extern int (dmPointFromMat)( dmPoint p, + const dmMatrix m); +extern int (dmScaleFromMat)( dmScale s, + const dmMatrix m); + +extern int dmPointQuatScaleFromMat( dmPoint p, + dmQuaternion q, + dmScale s, + const dmMatrix m); + +extern int dmPointEulerScaleFromMat( dmPoint p, + dmEuler e, + dmScale s, + const dmMatrix m); + +/* + * Functions to manipulate vectors and points + * using matricies, quaternions, rotations and scales + */ +#define __dmAdd3(r,a,b) ((r)[DM_X] = (a)[DM_X] + (b)[DM_X], \ + (r)[DM_Y] = (a)[DM_Y] + (b)[DM_Y], \ + (r)[DM_Z] = (a)[DM_Z] + (b)[DM_Z]) +#define __dmSub3(r,a,b) ((r)[DM_X] = (a)[DM_X] - (b)[DM_X], \ + (r)[DM_Y] = (a)[DM_Y] - (b)[DM_Y], \ + (r)[DM_Z] = (a)[DM_Z] - (b)[DM_Z]) +#define __dmScale3(r,a,b) ((r)[DM_X] = (a)[DM_X] * (b)[DM_X], \ + (r)[DM_Y] = (a)[DM_Y] * (b)[DM_Y], \ + (r)[DM_Z] = (a)[DM_Z] * (b)[DM_Z]) + +#define __dmScaleScalar3(r,a,b) ((r)[DM_X] = (a)[DM_X] * b, \ + (r)[DM_Y] = (a)[DM_Y] * b, \ + (r)[DM_Z] = (a)[DM_Z] * b) + + +#define __dmRotEuler3(r,a,b) \ +do { \ + dmQuaternion __q; \ + dmQuatFromEuler(__q,b); \ + __dmRotQuat3((r),(a),__q); \ +} while (0) + +extern void __dmRotQuat3( float32 *r, + const float32 *a, + const dmQuaternion q); + +#define dmVectorAdd(r,a,b) __dmAdd3(r,a,b) +#define dmVectorSub(r,a,b) __dmSub3(r,a,b) +#define dmPointSub(r,a,b) __dmSub3(r,a,b) +#define dmPointAddVector(r,a,b) __dmAdd3(r,a,b) + +#define dmVectorScale(r,a,b) __dmScale3(r,a,b) +#define dmPointScale(r,a,b) __dmScale3(r,a,b) +#define dmVectorScaleScalar(r,a,b) __dmScaleScalar3(r,a,b) +#define dmVectorRotQuat(r,v,q) __dmRotQuat3(r,v,q) +#define dmPointRotQuat(r,p,q) __dmRotQuat3(r,p,q) + +#define dmVectorRotEuler(r,v,e) __dmRotEuler3(r,v,e) +#define dmPointRotEuler(r,p,e) __dmRotEuler3(r,p,e) + + +extern void (dmVectorAdd)( dmVector r, + const dmVector a, + const dmVector b); + +extern void (dmVectorSub)( dmVector r, + const dmVector a, + const dmVector b); + +extern void (dmPointSub)( dmVector r, + const dmPoint a, + const dmPoint b); + +extern void (dmPointAddVector)( dmPoint r, + const dmPoint a, + const dmVector b); + +extern void (dmVectorScale)( dmVector r, + const dmVector a, + const dmScale b); + +extern void (dmVectorScaleScalar)( dmVector r, + const dmVector a, + float32 b); + +extern void (dmPointScale)( dmPoint r, + const dmPoint a, + const dmScale b); + +extern void (dmVectorRotQuat)( dmVector r, + const dmVector v, + const dmQuaternion); + +extern void (dmVectorRotEuler)( dmVector r, + const dmEuler e, + const dmVector v); + + +extern void (dmPointRotQuat)( dmPoint r, + const dmPoint p, + const dmQuaternion q); +extern void (dmPointRotEuler)( dmPoint r, + const dmPoint p, + const dmEuler e); + +extern void dmVectorXformMat( dmVector r, + const dmVector v, + const dmMatrix m); +extern void dmPointXformMat( dmPoint r, + const dmPoint v, + const dmMatrix m); + + + +/* + * Dead reckoning et al. Actually most of these functions only + * deal with zero order stuff. + */ + +#define dmPosFromMat(p,m) do { \ + dmMatCopy((p)->pos, m); \ + dmVectorIdent((p)->linearVel); \ + dmVectorIdent((p)->linearAccn); \ + dmVectorIdent((p)->angularVel); \ + dmVectorIdent((p)->angularAccn); \ +} while (0) + +#define dmPosFromPointEulerScale(p,p2,e,s) do { \ + dmMatFromPointEulerScale((p)->pos,(p2),(e),(s)); \ + dmVectorIdent((p)->linearVel); \ + dmVectorIdent((p)->linearAccn); \ + dmVectorIdent((p)->angularVel); \ + dmVectorIdent((p)->angularAccn); \ +}while(0) + +#define dmPosFromPointQuatScale(p,p2,q,s) do { \ + dmMatFromPointQuatScale((p)->pos,(p2),(q),(s)); \ + dmVectorIdent((p)->linearVel); \ + dmVectorIdent((p)->linearAccn); \ + dmVectorIdent((p)->angularVel); \ + dmVectorIdent((p)->angularAccn); \ +}while(0) + +extern void (dmPosFromMat)( dmPosition_Ptr p, + const dmMatrix m); +extern void (dmPosFromPointEulerScale)( dmPosition_Ptr p, + const dmPoint p2, + const dmEuler e, + const dmScale s); +extern void (dmPosFromPointQuatScale)( dmPosition_Ptr p, + const dmPoint p2, + const dmQuaternion q, + const dmScale s); + +extern void dmDeadReckon( dmMatrix m, + float32 time, + const dmPosition_Ptr pos); +/* + * + * given four points a, b, c, d defining two line segments AB and CD, + * generate a matrix m that will transform AB to CD. + * If the length of either line segment is zero, the results are undefined. + */ +extern void dmPointToPoint(dmMatrix m, + dmPoint a, + dmPoint b, + dmPoint c, + dmPoint d); + + + +/* + * version function + */ +extern void dmVersion(FILE *fp); + + + +#ifdef __cplusplus +} +#endif +#endif /*_DMTYPES_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DP.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DP.H new file mode 100644 index 0000000..c9660c9 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DP.H @@ -0,0 +1,47 @@ +/* + * PROJECT: dVS + * SUBSYSTEM: dp + * MODULE: dp.h + * + * + * File: $RCSfile: dp.h,v $ + * Revision: $Revision: 2.9 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: dp.h,v 2.9 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, photocopied, + * reproduced, translated, or reduced to any electronic medium or + * machine readable form without prior written consent from Division + * Ltd. + */ + +#ifndef _DP_H +#define _DP_H 1 + +#ifdef _cplusplus +extern "C" { +#endif + +#if defined (_UNIX) +#include +#elif defined (_TRANSPUTER) || defined (_I860) +#include +#elif defined (_WIN31) +#include +#else +#error "Unknown processor type " +#endif + +#ifdef _cplusplus +} +#endif + +#endif /* _DP_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DS.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DS.H new file mode 100644 index 0000000..b5fd2f6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DS.H @@ -0,0 +1,48 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: ds.h,v $ + * REVISION: $Revision: 1.6 $ + * Date: $Date: 1995/05/18 09:39:38 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: ds.h,v 1.6 1995/05/18 09:39:38 jeff beta $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#ifndef _DS_H +#define _DS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + char *string; +}DStringTraverseInfo; + +extern void dsVersion(FILE *fp); +char *dStringFromOptions (char *string, int *size, char *name, ...); +char *dStringFirstString (char *string, DStringTraverseInfo *info); +char *dStringNextOption (char *option, DStringTraverseInfo *info); + + +#define DS_END_OF_OPTIONS '\0' + + +#ifdef __cplusplus +} +#endif +#endif /*_DS_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DTCP.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DTCP.H new file mode 100644 index 0000000..54a6fd4 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DTCP.H @@ -0,0 +1,165 @@ +/* + * PROJECT: dvs + * SUBSYSTEM: net + * MODULE: dtcp.h + * + * File: $RCSfile: dtcp.h,v $ + * Revision: $Revision: 1.3 $ + * Date: $Date: 1995/03/10 17:09:52 $ + * Author: $Author: john $ + * RCS Ident: $Id: dtcp.h,v 1.3 1995/03/10 17:09:52 john Exp $ + * + * FUNCTION: + * header file for host independant socket access. + * + * $Log: dtcp.h,v $ + * Revision 1.3 1995/03/10 17:09:52 john + * *** empty log message *** + * + * Revision 1.2 1995/01/13 16:09:46 jeff + * ci for new build system. + * + * Revision 1.1 1994/12/05 09:33:35 jeff + * First post-manager check in. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef __DTCP_H +#define __DTCP_H + +#include +#include +#include +#include +#ifdef _IRIX5 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +# ifdef __cplusplus +extern "C" { +# endif + + +#if defined ( _SYSV42) +#ifdef _DVS_AGENT +#define TCP_TLI + +#else +#define TCP_BSD +#endif +#else +#if defined (_HPUX) || defined (_IRIX) +#define TCP_BSD +#else +#error Undefined system type +#endif +#endif + +#ifdef TCP_TLI +#include +#include + +#define dsock_open dsock_tli_open +#define dsock_bind_listen dsock_tli_bind_listen +#define dsock_buffer_size dsock_tli_buffer_size +#define dsock_select_io dsock_tli_select_io +#define dsock_async_io dsock_tli_async_io +#define dsock_async_signal dsock_tli_async_signal +#define dsock_allow_broadcast dsock_tli_allow_broadcast +#define dsock_set_timeout dsock_tli_set_timeout +#define dsock_sendto dsock_tli_sendto +#define dsock_recvfrom dsock_tli_recvfrom +#define dsock_send dsock_tli_send +#define dsock_recv dsock_tli_recv +#define dsock_getFirst_socket dsock_tli_getFirst_socket +#define dsock_getNext_socket dsock_tli_getNext_socket +#define dsock_connect dsock_tli_connect +#define dsock_connect_addr dsock_tli_connect_addr +#define dsock_listen_accept dsock_tli_listen_accept +#define dsock_acceptClose dsock_tli_acceptClose +#define dsock_recvConnect dsock_tli_recvConnect +#define dsock_enableAsyncWrite dsock_tli_enableAsyncWrite +#define dsock_disableAsyncWrite dsock_tli_diableAsyncWrite +#define dsock_close dsock_tli_close +#define dsock_error dsock_tli_error +#define dsock_errno dsock_tli_errno +#endif + +#include + +#define DTCP_UDP 0x00000001 +#define DTCP_TCP 0x00000002 + +#define DTCP_INET 0x00000001 +#define DTCP_UNIX 0x00000002 + +#define DTCP_READ 1 +#define DTCP_WRITE 2 +#define DTCP_EXCEPTION 3 +#define DTCP_ERR 4 +#define DTCP_HUP 5 + +#define DTCP_LISTEN -2 +#define DTCP_CONNECT -3 +#define DTCP_DATA -4 +#define DTCP_EXDATA -5 +#define DTCP_DISCONNECT -6 +#define DTCP_ERROR -7 +#define DTCP_UDERR -8 +#define DTCP_ORDREL -9 +#define DTCP_TIMEOUT -10 + + +void dsockVersion(FILE *fp); +int dsock_open(int family, int type); +int dsock_bind_listen(int sock, int family, int inet_addr, short *port, int qlength); +int dsock_buffer_size(int sock, int bufferSize); +void dsock_select_io(int sock); +int dsock_async_io(int sock); +int dsock_async_signal(void); +int dsock_allow_broadcast (int sock); +void dsock_set_timeout(struct timeval *t); +int dsock_sendto (int sock, void *msg, int size, struct sockaddr_in *dst); +int dsock_recvfrom (int sock, void *msg, int size, struct sockaddr_in *from); +int dsock_send (int sock, void *msg, int size); +int dsock_recv (int sock, void *msg, int size); +int dsock_getFirst_socket (int *ioType); +int dsock_getNext_socket (int *ioType); +int dsock_connect(int sock, struct sockaddr_in *dst); +int dsock_connect_addr(int sock, int family, int inet_addr, short *port ); +int dsock_listen_accept(int sock, struct sockaddr_in *addr); +int dsock_acceptClose(int fd); +int dsock_recvConnect(int fd); +int dsock_enableAsyncWrite(int fd); +int dsock_disableAsyncWrite(int fd); +int dsock_close(int fd); + + +void dsock_error(char *string); +int32 dsock_flipWord(int32 value); +int16 dsock_flipShort(int16 value); + +extern int dsock_errno; + + +# ifdef __cplusplus +} +# endif +#endif /* DTCP_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/DU.H b/CODE/RP/MUNGA_L4/libDPL/dsys/DU.H new file mode 100644 index 0000000..47a6915 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/DU.H @@ -0,0 +1,214 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: du + * MODULE: du.h + * + * File: $RCSfile: du.h,v $ + * Revision: $Revision: 2.17 $ + * Date: $Date: 1995/05/18 09:40:33 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: du.h,v 2.17 1995/05/18 09:40:33 jeff beta $ + * + * FUNCTION: + * external declarations of functions in the du library. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DU_H +#define _DU_H + +#include + +#include + +#ifdef _WIN31 +#include +#define malloc farmalloc +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * searching fopen/searching flook functions. + */ + +#define SF_READ 1 +#define SF_WRITE 2 +#define SF_EXEC 4 +#define SF_EXIST 8 + +typedef enum { DU_PATH_SYSTEM, DU_PATH_USER, DU_PATH_OFFSET } duPathType; + +typedef struct duPathIterator +{ + void *entry; +} duPathIterator; + +extern void duVersion(FILE *fp); + +extern void *duConvertPathToTable(char *sysPath, + char *userPath, + char *offset); +extern void *duAddPathToTable(void *table, + char *path, + duPathType type); +extern FILE *duSearchingFopen(char *fileName, + void *pathList, + char **extensions, + char *mode, + char *fullPath, + int maxFullPathSize, + int *extensionIndex, + int absolute); +extern int duSearchingFlook(char *fileName, + void *pathList, + char **extensions, + int32 mode, + char *fullPath, + int maxFullPathSize, + int *extensionIndex, + int absolute); +char *duPathIterateInit(duPathIterator *iter, void *table); +char *duPathIterate(duPathIterator *iter); +void *duPathRemoveEntry(void *table, char *entry); +void duPathDelete(void *table); +void duSfSearchPath(char *searchPath); +void duSfSearchVariable(char *searchVariable); + +/* + * Functions for efficient allocation of many identically sized blocks. + */ + +/* + * many small chunks are allocated at once. One of these + * structures manages that. + */ +typedef struct duBlkAllocChunk duBlkAllocChunk; + +/* + * the block header. Contains house keeping info for the block allocator. + */ +typedef struct duBlkCtrl { + duBlkAllocChunk *freeChunks; /* Ptr to linked list of free blocks */ + void *freeList; /* Pointer to the free list */ + uint32 totalItems; /* Total number of block items */ + uint32 freeItems; /* Total number of free items */ + uint32 chunkSize; /* Number of items to alloc at once */ + uint32 itemAlign; /* Alignment of units in bytes. */ + uint32 itemSize; /* Size of items in bytes */ +} duBlkCtrl; +extern void duBlkAllocConstruct(duBlkCtrl *ctrlBlock, + uint32 is, + uint32 cs, + uint32 align); +typedef void* (*duAllocFunc)(uint32); +typedef void (*duFreeFunc)(void*); + +extern void duBlkAllocDestruct(duBlkCtrl *ctrlBlock, + duFreeFunc ffunc); +extern void *duBlkAlloc(duBlkCtrl *ctrlBlock, + duAllocFunc afunc); +extern void duBlkFree(duBlkCtrl *ctrlBlock, void *item); + +/* + * Functions to manipulate hash tables. + */ +typedef int32 (*duHfunc)(void *key, int32 size); +typedef int (*duCfunc)(void *a, void *b); +typedef struct duHashElem duHashElem; +typedef struct duHashTab duHashTab; + +/* + * the following is used if iterating over all the elements in a hash + * table. It keeps track of where in the table you are for use with the + * iteration functions. + */ +typedef struct duHashIterator { + duHashTab *h; + int32 bucket; + duHashElem *e; +} duHashIterator; + +extern void *duHashLookup (duHashTab *t, void *key); +extern void duHashInstall (duHashTab *t, void *key, void *datum); + +#define duHashRemove(t, key) duHashRemoveK((t), (key), NULL) +#define duHashRemoveK(t, key, old) duHashRemoveKDatum ((t), (key), NULL, (old) ) + +extern void *duHashRemoveKDatum (duHashTab *t, void *key, void *d, void **old_key); +extern duHashTab *duNewHashTab (int32 Size, duHfunc hashfun, + duCfunc cmpfun); +extern void duDeleteHashTab (duHashTab *t); + +#define duHashIterateInit(iter, t) \ + duHashIterateInitK(iter, t, NULL) + +#define duHashIterate(iter) \ + duHashIterateK(iter, NULL) + +extern void *duHashIterateInitK (duHashIterator *iter, duHashTab *t, + void **key); +extern void *duHashIterateK (duHashIterator *iter, void **key); + + + + +void __duVerboseStart(int level); +void __duDebugStart(int level, char *file, int line); +void __duVerboseMessage(char *format, ...); +uint32 duVerbose_SetLevel(uint32 level); +uint32 duVerbose_GetLevel(void) ; +uint32 duDebug_SetLevel(uint32 level); +uint32 duDebug_GetLevel(void); +FILE *duDebug_SetLogFile(FILE *, int mode); +char *duDebug_SetName(char *, int mode); +void duDebug_Quiet(void); +void duDebug_VeryQuiet(void); +void duDebug_Noisy(void); +void duWarn(char *format, ...); +void duError(char *format, ...); +void duFatal(char *format, ...); + +extern uint32 __duVerbose_level; +extern uint32 __duDebug_level; + +#define DU_DEBUG_DONT_OVERIDE 0 +#define DU_DEBUG_OVERIDE 1 + +#define duVerbose(x,y) do { \ + if (__duVerbose_level & (x)) \ + { \ + __duVerboseStart(x); \ + __duVerboseMessage y; \ + } \ + } while (0) + +#ifdef NDEBUG +#undef duDebug +#define duDebug(x,y) ((void)0) +#else +#undef duDebug +#define duDebug(x,y) do { \ + if (__duDebug_level & (x)) \ + { \ + __duDebugStart(x, __FILE__, __LINE__); \ + __duVerboseMessage y; \ + } \ + } while (0) +#endif + + +#ifdef __cplusplus +} +#endif +#endif /*_DU_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/FILELIB.H b/CODE/RP/MUNGA_L4/libDPL/dsys/FILELIB.H new file mode 100644 index 0000000..1a5857c --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/FILELIB.H @@ -0,0 +1,315 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: filelib.h,v $ +-- Revision : $Revision: 1.9 $ +-- Date : $Date: 95/05/16 13:46:20 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __FILELIB_H__ +#define __FILELIB_H__ + +#include + +#ifndef _PFILE +#ifdef _PF_LOCAL +#include "pfile.h" +#else +#include +#endif +#endif + +/*****************************************************************************/ +/* filelib error numbers */ +#define dflENO_READ 0x2001 +#define dflENO_WRITE 0x2002 +#define dflENO_CPATH 0x2003 +#define dflENO_CNAME 0x2004 +#define dflENO_PERMIT 0x2005 +#define dflENO_DIR 0x2006 +#define dflENO_RMFILE 0x2007 +#define dflENO_RMDIR 0x2008 +#define dflENO_USAGE 0x2009 + +#define dfl_STDIN_NAME "stdin" +#define dfl_STDOUT_NAME "stdout" + +extern char *progname ; + +#define dfl_SET_TO_LITTLE 0 +#define dfl_SET_TO_BIG 1 + +#define dflPATHDIV '/' +#define dflREPPATHDIV '\\' + +#ifndef _UNIX +#define dflDRIVEDIV ':' +#endif + +/**************************************************************************** + * File reading and writing routines. + */ + +typedef struct dflFILETYPE +{ + char *name ; + FILE *fp ; + int32 endian ; + char *buf, *bufEnd; + int32 remain ; + int32 filePos, endPos ; +} dflFILE, *dflFILEPTR ; + +#define dfl_BUFFER_SIZE 8192 + +void +dflSetEndian(dflFILEPTR file, int32 OutEndian) ; +dflFILEPTR +dflOpen(char *name, char *mode, int32 OutEndian) ; +int32 +dflClose(dflFILEPTR file) ; + +/**************************************************************************** + * File reading routines + */ +int32 +dflSeek(dflFILEPTR fl, int32 offset, int32 whence) ; +int32 +dflUngetc(char c, dflFILEPTR fl); +int32 +_dflGetc(dflFILEPTR fl) ; +int32 +_dflRead(void *ptr, int32 size, dflFILEPTR fl) ; + +#define dflTell(fl) ((fl)->filePos - (fl)->remain) +#define dflGetc(fl) \ + (((fl)->remain) ? \ + ((int32) *((fl)->bufEnd - ((fl)->remain)--)) : \ + _dflGetc(fl)) +#define dflRead(ptr,size,fl) \ + (((fl)->remain >= (size)) ? \ + ( memcpy((ptr),((fl)->bufEnd - (fl)->remain),(size)) , \ + (fl)->remain -= (size), (int32) dpgSUCCESS) : \ + _dflRead(ptr,size,fl)) + +#define dflError(fl) ((int32) ferror(fl->fp)) + + +int32 +dflRead1byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn1byte(dflFILEPTR fl, int32 n, void *dest) ; +int32 +dflRead2byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn2byte(dflFILEPTR fl, int32 n, void *dest) ; +int32 +dflRead4byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn4byte(dflFILEPTR fl, int32 n, void *dest) ; +int32 +dflRead8byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn8byte(dflFILEPTR fl, int32 n, void *dest) ; + +/**************************************************************************** + * File writing routines + */ + +void +dflWriteint8(dflFILEPTR fl, int8 i) ; +void +dflWriteuint8(dflFILEPTR fl, uint8 i) ; +void +dflWriteint16(dflFILEPTR fl, int16 i) ; +void +dflWriteuint16(dflFILEPTR fl, uint16 i) ; +void +dflWriteint32(dflFILEPTR fl, int32 i) ; +void +dflWritefloat32(dflFILEPTR fl, float32 f) ; +void +dflWritefloat64(dflFILEPTR fl, float64 f) ; +void +dflWritestr(dflFILEPTR fl, void *source, int32 size) ; + + +/*************************************************************************** + * File name manipulation routines + * + * Major re-write on 11/2/95 due to the introduction of material files. This + * led to the need of hierarchical break down of files from all geometry + * converters (i.e. dxf2vdi). As they all use the same structure the routines + * have been placed into this library. + */ +/***************************************************************************** +* PLEASE NOTE:- These file name manipulation routines expect unix style * +* names, even on dos, a simple call to dflFormatName should * +* solve any potential problems. * +*****************************************************************************/ + +/**************************************************************************** + * dflFormatName + * + * Converts all file names to unix style, i.e. all '\\' to '/' + * Should be called for every file name! + */ +void +dflFormatName(char *name) ; + +/**************************************************************************** + * dflSplitName - splits the given file name into is 3 constituent parts. + * If path, body or ext are NULL, no problems, that part isn't done. + * returns dymanically allocated strings, the path will have the closing + * '/' and neither the body ext will have the dividing '.' + */ +void +dflSplitName(char *FName, char **path, char **body, char **ext) ; + +/***************************************************************************** + * dflComposeName - Opposite to SplitName, i.e. given the 3 parts, it joins + * them together. Any of them can be NULL. If the body starts with a '/' then + * the path is ignored. if the path doesnt end with a '/' then one is inserted + * if the extension is NULL or "" then no '.' is inserted at the end of body. + */ +char * +dflComposeName(char *path, char *body, char *ext) ; + +/**************************************************************************** + * dflCreateName - same as dflComposeName, only excepts 3 paths and joins + * them together, any can be NULL. + */ +char * +dflCreateName(char *basePath, char *midPath, char *extPath, + char *base, char *ext) ; + +/*************************************************************************** + * dflBackupName - Checks for existance of the file 'filename', if it exists, + * it creates a backup filename 'BackName' by either inserting the + * "division.sav" directory into the path, or if the environment variable + * ${division.sav} is set then it is asumed to be the absolute output path + * and the base name of 'filename' is appended. If the file 'BackName' exists + * then it is removed, and 'filename' is moved to 'BackName'. + * + * Returns -1 if an error occured or the number of paths created. + * 'BackName is a dynamically allocated string which must be freed be the + * user + */ +int32 +dflBackupName(char *filename, char **Backup) ; + +/**************************************************************************** + * dflRemoveBackup - removes everything generated from a call to dflBackupName + * Requires the return value to determine how many directories are to be + * removed. If backing up 2 or more files it is important to Remove the backup + * in an reversed order, soley because the first one will have created any + * required directies and its return value will be non zero, these directies + * can only be removed after all the the backup files have been removed. + * returns dpgERROR if failed to remove something, else returns dpgSUCCESS + */ +int32 +dflRemoveBackup(char *backName, int32 noDirs) ; + +/**************************************************************************** + * dflTempName - Creates a temporary file name based on the given file name. + * returns NULL on failure, dynamically allocated string otherwise. + */ +char * +dflTempName(char *fname) ; + +#define dflUSEMID 0x01 +#define dflASCII 0x02 +#define dflLIBRARY 0x04 +char * +dflCreateVtxName(char *basePath, int32 useMid, char *extPath, char *base) ; +char * +dflCreateBgfName(char *basePath, int32 useMid, char *extPath, char *base, + dpfFILETYPE OutMode) ; +char * +dflCreateBmfName(char *basePath, int32 useMid, char *extPath, char *base, + dpfFILETYPE OutMode, int libOut) ; +char * +dflCreateVdiName(char *basePath, int32 useMid, char *extPath, char *base, + int libOut) ; + +/************************************************************************** + * Create Path + * creates a single path given the path string, last path must terminate in + * a '/' else it will not be tested for. + * + * Return -1 on an error (dpgERROR), else the number of directories created. + */ +int32 +dflCreatePath(char *path) ; +/************************************************************************** + * dflCreatePaths - Sets up the division path structure given the base and + * extended paths and whether to use mid paths, all required + * paths are created, which includes material, geometry, texture, vdifiles + * and the vdi library path. + */ +int32 +dflCreatePaths(char *basePath, int32 useMid, char *extPath) ; + +/************************************************************************ + * dflCreateBaseName + * creates a base name (bit between the path and the extension) ready + * for a Compose or CreateName. if the numb is less than zero, it is + * ignored, if dosName is non-zero then the output name will be no long + * than 8 chars. + */ +char * +dflCreateBaseName(char *base, int32 numb, int32 dosName) ; + + +#define byte8_flip(p) do { \ + char ___t; \ + ___t=p[0]; \ + p[0]=p[7]; \ + p[7]=___t; \ + ___t=p[1]; \ + p[1]=p[6]; \ + p[6]=___t; \ + ___t=p[2]; \ + p[2]=p[5]; \ + p[5]=___t; \ + ___t=p[3]; \ + p[3]=p[4]; \ + p[4]=___t; \ +} while (0) + +#define byte4_flip(p) do { \ + char ___t; \ + ___t=p[0]; \ + p[0]=p[3]; \ + p[3]=___t; \ + ___t=p[1]; \ + p[1]=p[2]; \ + p[2]=___t; \ +} while (0) + +#define byte2_flip(p) do { \ + char ___t; \ + ___t=p[0]; \ + p[0]=p[1]; \ + p[1]=___t; \ +} while (0) + + +#endif /* __FILELIB_H__ */ + diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/GETPARAM.H b/CODE/RP/MUNGA_L4/libDPL/dsys/GETPARAM.H new file mode 100644 index 0000000..4bb85b9 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/GETPARAM.H @@ -0,0 +1,73 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: getparam.h,v $ +-- Revision : $Revision: 1.6 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __GETPARAM_H__ +#define __GETPARAM_H__ + +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +/*****************************************************************************/ +/* getparam error numbers */ +#define dgpENO_STREXP 0x3001 +#define dgpENO_UNKOPT 0x3002 +#define dgpENO_USAGE 0x3003 +#define dgpENO_RSRCF 0x3004 + +/**************************************************************************** + * getparam monitor numbers */ +#define dgpMON_OPTIONS 0x00001000 +#define dgpMON_FILES 0x00002000 + + +#define dgp_END 0 +#define dgp_NO_STR 1 +#define dgp_D_STR 2 +#define dgp_DJOIN_STR 3 +#define dgp_DAFTER_STR 4 +#define dgp_DBOTH_STR 5 +#define dgp_O_STR 6 +#define dgp_OJOIN_STR 7 +#define dgp_OAFTER_STR 8 +#define dgp_OBOTH_STR 9 + +typedef struct { + char optname[15] ; + int32 opttype ; + int32 optreturn ; +} dgpTABLE, *dgpTABLEPTR ; + +extern char *progname ; + +int32 +dgpGetopt(int32 argc, char *argv[], dgpTABLEPTR table, + int32 *NoFiles, char **files[], char **str1, char **str2) ; + +void +dgpFreeFiles(int32 NoFiles, char *files[]) ; + +#endif /* __GETPARAM_H__ */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/MAPFILE.H b/CODE/RP/MUNGA_L4/libDPL/dsys/MAPFILE.H new file mode 100644 index 0000000..4c13dcd --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/MAPFILE.H @@ -0,0 +1,99 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1994 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: mapfile.h,v $ +-- Revision : $Revision: 1.3 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __MAPFILE_H__ +#define __MAPFILE_H__ + +#ifdef _PF_LOCAL +#include "ptool.h" +#else +#include +#endif + +/* Error Numbers */ +#define dmpENO_OPEN 0x50001 +#define dmpENO_FORM 0x50002 + +typedef struct dmpMATFILETYPE +{ + char *name ; + dpfFILEPTR file ; + struct dmpMATFILETYPE *next ; +} dmpMATFILE, *dmpMATFILEPTR ; + +typedef struct dmpBLOCKTYPE +{ + char *name ; + int32 ignore ; + struct dmpBLOCKTYPE *next ; +} dmpBLOCK, *dmpBLOCKPTR ; + +typedef struct dmpMAPPINGTYPE +{ + char *from, *to ; + int32 gotMat ; + int32 gotText ; + dptTEXTURE text ; + struct dmpMAPPINGTYPE *next ; +} dmpMAPPING, *dmpMAPPINGPTR ; + +typedef struct +{ + dmpMATFILEPTR materials ; + dmpMAPPINGPTR mappings ; + dmpBLOCKPTR blocks ; +} dmpFILE, *dmpFILEPTR ; + +dmpFILEPTR +dmpCreateFile(void) ; +dmpMATFILEPTR +dmpCreateMatFile(void) ; +int32 +dmpAddMatFile(dmpFILEPTR mp, dmpMATFILEPTR mat) ; +dmpBLOCKPTR +dmpCreateBlock(void) ; +int32 +dmpAddBlock(dmpFILEPTR mp, dmpBLOCKPTR blk) ; +dmpMAPPINGPTR +dmpCreateMapping(void) ; +int32 +dmpAddMapping(dmpFILEPTR mp, dmpMAPPINGPTR map) ; +void +dmpFreeFile(dmpFILEPTR mp) ; +dmpMAPPINGPTR +dmpFindMapping(dmpFILEPTR mp, char *name) ; +dpfMATERIALPTR +dmpFindMaterial(dmpFILEPTR mp, char *name) ; +dpfTEXTUREPTR +dmpFindTexture(dmpFILEPTR mp, char *name) ; +dmpBLOCKPTR +dmpFindBlock(dmpFILEPTR mp, char *name) ; + +int32 +dmpGetMapFile(dmpFILEPTR mp, char *fileName) ; +int32 +dmpSaveFile(char *name, dmpFILEPTR file) ; + + +#endif /* __MAPFILE */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/PARSER.H b/CODE/RP/MUNGA_L4/libDPL/dsys/PARSER.H new file mode 100644 index 0000000..29fb536 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/PARSER.H @@ -0,0 +1,122 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: parser.h,v $ + * REVISION: $Revision: 1.8 $ + * Date: $Date: 1995/05/18 09:41:31 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: parser.h,v 1.8 1995/05/18 09:41:31 jeff beta $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _PARSER_H +#define _PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif +#define PARSER_MAX_TOKEN_SIZE 2048 +#define PARSER_MATCH_CASE 0 +#define PARSER_ANY_CASE 1 + +/* + * macros for testing char classes + */ +#define PARSER_LEX_START 1 +#define PARSER_LEX_CONTINUE 2 +#define parserStartChar(f,x) ((f)->LexClass[(x)] & PARSER_LEX_START ) +#define parserContinueChar(f,x) ((f)->LexClass[(x)] & PARSER_LEX_CONTINUE ) + +/* + * tokens returned by parser functions + */ +#define PARSER_OK 0 +#define PARSER_ERR -1 +#define PARSER_EOF -2 +#define PARSER_STRING -3 +#define PARSER_INT -4 +#define PARSER_FLOAT -5 +#define PARSER_PUSH -6 +#define PARSER_POP -7 +#define PARSER_QUOTED_STRING -8 + +/* + * used to hold pre-processing state info. + * Contents are not made public. + */ +typedef struct pprocState pprocState; + +typedef struct dParseKeyTab +{ + int tok; + char *name; + int matchCase; +} dParseKeyTab; + + +typedef struct dParseFile +{ + int errorFlag; + int seeIncludes; + int pushedBackToken; + float fpNumber; + long iNumber; + char *buffer; + int bufSize; + int bufPos; + dParseKeyTab *keyTab; + int charNo; + pprocState *ppstate; + char LexClass[128]; +} dParseFile, *dParseFilePtr; + +extern void parserVersion(FILE *openfp); +extern dParseFilePtr parserCreate(char *name, + FILE *openfp, + dParseKeyTab *keyTable, + int bufferSize, + FILE *(*fileFinder)(const char *), + const char *startChars, + const char *continueChars, + int seeIncludes); +extern void parserDestroy(dParseFilePtr fptr); + +extern dParseFilePtr parserOpenFile(char *name, + FILE *fp, + dParseKeyTab *keyTable, + int bufferSize, + FILE *(*fileFinder)(const char *), + const char *startChars, + const char *continueChars, + int seeIncludes); +extern void parserCloseFile(dParseFilePtr fPtr); + +extern int parserGetc(dParseFilePtr fptr); +extern int parserUngetc(dParseFilePtr fptr, char c); + +extern char *parserTokenToString(dParseFilePtr fptr, const int token); +extern int parserPushToken(dParseFilePtr fptr, const int token); +extern int parserNextToken(dParseFilePtr fptr); + +extern char *parserMatchString(dParseFilePtr fptr); +extern int parserMatchInt(dParseFilePtr fptr, int *num); +extern int parserMatchFloat(dParseFilePtr fptr, float *num); +extern int parserMatchCharacter(dParseFilePtr fptr, char c); + +extern const char *parserCurrentFile(dParseFilePtr fptr); +extern int parserCurrentLine(dParseFilePtr fptr); +#ifdef __cplusplus +} +#endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/PFBIZTAG.H b/CODE/RP/MUNGA_L4/libDPL/dsys/PFBIZTAG.H new file mode 100644 index 0000000..3f2f10c --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/PFBIZTAG.H @@ -0,0 +1,197 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * File: $RCSfile: pfbiztag.h,v $ + * Revision: $Revision: 1.13 $ + * Date: $Date: 1995/10/06 10:47:30 $ + * Author: $Author: bill $ + * RCS Ident: $Id: pfbiztag.h,v 1.13 1995/10/06 10:47:30 bill Exp $ + * + * FUNCTION: + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef __PFBIZTAG_H__ +#define __PFBIZTAG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* PUBLIC DEFINES =======================================*/ +/* Biz v1.0 tag defines */ +#define dpf_BIZ_PATCH 34 +#define dpf_BIZ_STRIP 35 +#define dpf_BIZ_TRISTRIP 0 +#define dpf_BIZ_POLYSTRIP 1 +#define dpf_BIZ_DONE 37 + +/* Biz v2.x tag defines */ +#define dpfB_0_COMMENT_TAG 0x0000 +#define dpfB_HEADER_TAG 0x0003 +#define dpfB_PROPAGATED_COMMENT_TAG 0x0004 +#define dpfB_BIZ_DONE 0x0005 +#define dpfB_TEXTURE_TAG 0x0010 +#define dpfB_TEXTURE_MAP_TAG 0x0011 +#define dpfB_TEXTURE_MINIFY_TAG 0x0012 +#define dpfB_TEXTURE_MAGNIFY_TAG 0x0013 +#define dpfB_TEXTURE_ALPHA_TAG 0x0014 +#define dpfB_TEXTURE_WRAP_U_TAG 0x0015 +#define dpfB_TEXTURE_WRAP_V_TAG 0x0016 +#define dpfB_TEXTURE_DETAIL_TAG 0x0017 +#define dpfB_TEXTURE_BITSLICE_TAG 0x0018 +#define dpfB_MATERIAL_TAG 0x0020 +#define dpfB_MATERIAL_TEXTURE_TAG 0x0021 +#define dpfB_MATERIAL_ENVIRONMENT_TAG 0x0022 +#define dpfB_MATERIAL_AMBIENT_TAG 0x0023 +#define dpfB_MATERIAL_DIFFUSE_TAG 0x0024 +#define dpfB_MATERIAL_SPECULAR_TAG 0x0025 +#define dpfB_MATERIAL_EMISSIVE_TAG 0x0026 +#define dpfB_MATERIAL_OPACITY_TAG 0x0027 +#define dpfB_MATERIAL_RAMP_TAG 0x0028 +#define dpfB_RAMP_TAG 0x0030 +#define dpfB_RAMP_DATA_TAG 0x0031 +#define dpfB_OBJECT_TAG 0x0040 +#define dpfB_LOD_TAG 0x0041 +#define dpfB_PATCH_TAG 0x0042 +#define dpfB_POLYGON_TAG 0x0043 +#define dpfB_TRISTRIP_TAG 0x0044 +#define dpfB_POLYSTRIP_TAG 0x0045 +#define dpfB_PMESH_TAG 0x0046 +#define dpfB_CONNECTION_LIST_TAG 0x0047 +#define dpfB_SPHERE_LIST_TAG 0x0048 +#define dpfB_SPHERE_TAG 0x0049 +#define dpfB_LINE_TAG 0x004a +#define dpfB_TEXT_TAG 0x004b +#define dpfB_TEXT_STRING_TAG 0x004c +#define dpfB_PCONN_LIST_TAG 0x004d +#define dpfB_PSTRIP_LIST_TAG 0x004e +#define dpfB_POINT_LIST_TAG 0x0050 + +#define dpfB_BOUND_TAG 0x0070 +#define dpfB_BBOX_TAG 0x0071 +#define dpfB_BSPHERE_TAG 0x0072 + +#define dpfB_LINE_NODE_TAG 0x0080 +#define dpfB_VERTEX_XYZ_TAG 0x0080 +#define dpfB_VERTEX_XYZ_N_TAG 0x0081 +#define dpfB_VERTEX_XYZ_RGBA_TAG 0x0082 +#define dpfB_VERTEX_XYZ_UV_TAG 0x0088 +#define dpfB_VERTEX_XYZ_N_UV_TAG 0x0089 +#define dpfB_VERTEX_XYZ_RGBA_UV_TAG 0x008A + +#define dpfB_2_COMMENT_TAG 0x2000 +#define dpfB_VERSION_TAG 0x2002 +#define dpfB_DATE_TAG 0x2003 +#define dpfB_TIME_TAG 0x2004 +#define dpfB_SCALE_TAG 0x2005 +#define dpfB_PRECISION_TAG 0x2006 +#define dpfB_FILETYPE_TAG 0x2007 +#define dpfB_SV_NAME_TAG 0x2008 +#define dpfB_MATERIAL_NAME_TAG 0x2008 +#define dpfB_RAMP_NAME_TAG 0x2008 +#define dpfB_TEXTURE_NAME_TAG 0x2008 +#define dpfB_UNIT_TAG 0x2009 +#define dpfB_SCOPE_TAG 0x200a +#define dpfB_SV_F_MATERIAL_TAG 0x2030 +#define dpfB_SV_B_MATERIAL_TAG 0x2031 +#define dpfB_SV_PLANE_TAG 0x2032 +#define dpfB_SV_DRAW_MODE_TAG 0x2033 +#define dpfB_SV_DECAL_TAG 0x2034 +#define dpfB_SV_FACETED_TAG 0x2035 +#define dpfB_SV_VERTEX_TAG 0x2036 +#define dpfB_SV_SPECIAL_TAG 0x2037 +#define dpfB_SV_LOCK_TAG 0x2039 +#define dpfB_SPHERE_DICE_V_TAG 0x2040 +#define dpfB_SPHERE_DICE_U_TAG 0x2041 +#define dpfB_LINE_THICKNESS_TAG 0x2042 +#define dpfB_TEXT_FONT_TAG 0x2043 +#define dpfB_TEXT_SCALE_TAG 0x2044 +#define dpfB_TEXT_ORIENTATION_TAG 0x2045 + +#define dpfB_LOD_DISTANCE_TAG 0x2046 +#define dpfB_LOD_REFERENCE_TAG 0x2047 +#define dpfB_LOD_TRANSITION_TAG 0x2048 + +#define dpfB_POINT_SIZE_TAG 0x2049 + +#define dpfB_BAUTO_TAG 0x2070 +#define dpfB_BLODNAME_TAG 0x2071 +#define dpfB_BOBJNAME_TAG 0x2072 + +#define dpfB_NO_DEF_TAGS 256 +#define dpfB_NO_CON_TAGS 256 + +#define dpfValidTag(tag) \ + ((((tag) & 0x1fff) > 0x00ff) ? 0 : \ + ((tag) & 0x2000) ? dpfB_CON_TAG_INFO[(tag) & 0x00ff] : \ + dpfB_DEF_TAG_INFO[(tag) & 0x00ff] ) + +/* PUBLIC TYPES =========================================*/ + + +/* PUBLIC VARIABLES ======================================*/ + + +extern uint8 dpfB_DEF_TAG_INFO[dpfB_NO_DEF_TAGS] ; +extern uint8 dpfB_CON_TAG_INFO[dpfB_NO_DEF_TAGS] ; + + +#ifdef _dpf_INCLUDE_BIZ_TABLE + +uint8 dpfB_DEF_TAG_INFO[dpfB_NO_DEF_TAGS] = { + 1, 1, 1, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, 3, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +} ; +uint8 dpfB_CON_TAG_INFO[dpfB_NO_DEF_TAGS] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +} ; + +#endif + +/* PUBLIC FUNCTIONS ======================================*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*__PFBIZTAG_H__ */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/PFILE.H b/CODE/RP/MUNGA_L4/libDPL/dsys/PFILE.H new file mode 100644 index 0000000..2794741 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/PFILE.H @@ -0,0 +1,1166 @@ +/**************************************************************************** + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: pfile.h,v $ + * Revision : $Revision: 1.15 $ + * Date : $Date: 95/05/16 13:46:35 $ + * Author : $Author: bill $ + * Last Modified : <110595.1427> + * + * Description + * + * Notes + * + * History + * + * $Log: pfile.h,v $ + * Revision 1.15 95/05/16 13:46:35 bill + * Added 1) dos. 2) STRIP_LIST. 3) POINTLIST. 4) biz->bgf + * + * Revision 1.14 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * + **************************************************************************** + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + ****************************************************************************/ + +#ifndef __PFILE_H__ +#define __PFILE_H__ + +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +#include + +/*****************************************************************************/ +/* pfile error numbers */ +#define dpfENO_ROPEN 0x8001 +#define dpfENO_READ 0x8002 +#define dpfENO_WOPEN 0x8003 +#define dpfENO_WRITE 0x8004 +#define dpfENO_CLOSE 0x8005 +#define dpfENO_FORM 0x8006 +#define dpfENO_VALUE 0x8007 +#define dpfENO_USAGE 0x8008 +#define dpfENO_NULL 0x8009 +#define dpfENO_CONV 0x800A + +/*****************************************************************************/ +/* pfile warning levels */ +#define dpfWARN_BADFILE 2 +#define dpfWARN_PROBLEM 3 +/*****************************************************************************/ +/* pfile monitor flags */ +#define dpfMON_READ 0x00100000 +#define dpfMON_WRITE 0x00200000 + +/*****************************************************************************/ +/* Useful constants */ +#define dpf_ALLOW_B2Z 1 +#define dpf_ALLOW_BMF 2 +#define dpf_ALLOW_ALL 3 + +/* max min ranges for types */ +#define dpfRGB_MAX (float32) 1.0 +#define dpfRGB_MIN (float32) 0.0 +#define dpfALPHA_MAX (float32) 1.0 +#define dpfALPHA_MIN (float32) 0.0 +#define dpfV1POWER_MAX (float32) 32.0 +#define dpfV1POWER_MIN (float32) 1.0 +#define dpfV2POWER_MAX (float32) 128.0 +#define dpfV2POWER_MIN (float32) 1.0 +#define dpfOPACITY_MAX (float32) 1.0 +#define dpfOPACITY_MIN (float32) 0.0 +#define dpfDICE_MAX 65565 +#define dpfDICE_MIN 3 +#define dpfDICE_DETER 0 +#define dpfTHICK_MAX 255 +#define dpfTHICK_MIN 1 + +/*****************************************************************************/ +/* Different vertex types */ +#define dpf_VERT_NONE (uint8) 0x0000 +#define dpf_VERT_NORMALS (uint8) 0x0001 +#define dpf_VERT_RGBA (uint8) 0x0002 +#define dpf_VERT_LUMINANCE (uint8) 0x0004 +#define dpf_VERT_TEXTURE (uint8) 0x0008 +#define dpf_VERT_THREED_TEXTURE (uint8) 0x0010 + +/*****************************************************************************/ +/* Different Geometry Types */ +#define dpf_GEOM_UNDEFINED (int32) 0x0000 +#define dpf_GEOM_POLYGON (int32) 0x0043 +#define dpf_GEOM_TRISTRIP (int32) 0x0044 +#define dpf_GEOM_POLYSTRIP (int32) 0x0045 +#define dpf_GEOM_PMESH (int32) 0x0046 +#define dpf_GEOM_SPHERE (int32) 0x0048 +#define dpf_GEOM_LINE (int32) 0x004A +#define dpf_GEOM_TEXT (int32) 0x004B +#define dpf_GEOM_POINT (int32) 0x0050 + +/*****************************************************************************/ +/* Unit conversion scaling factors */ +#define dpfINCHtoMM 25.4 +#define dpfMMtoINCH (1.0/dpfINCHtoMM) +#define dpfINCHtoM 0.0254 +#define dpfMtoINCH (1.0/dpfINCHtoM) + +/*****************************************************************************/ +/* types. */ +/* must never have double precision without global changes */ +/* +#define dpf_DOUBLE_PRECISION +*/ + +typedef enum +{ /* used for indexing arrays, identifying axies etc etc */ + dpf_PITCH = 0, dpf_YAW = 1, dpf_ROLL = 2, + dpfERGBA = 4, dpf_R = 0, dpf_G = 1, dpf_B = 2, + dpf_A = 3, dpf_POWER=3, dpf_LUM = 0, + dpfETEXT = 2, dpf_U = 0, dpf_V = 1, + dpfETHREEDTEXT = 3 +} coord; + +typedef int32 dpfIVECTOR[3] ; /* Generic 4 elem vector. */ +typedef float32 dpfRGBA[dpfERGBA]; +typedef float32 dpfTEXT[dpfETEXT] ; +typedef float32 dpfTHREEDTEXT[dpfETHREEDTEXT] ; + +typedef enum {dpf_B2Z_FILE, dpf_V2Z_FILE, + dpf_VIZ_FILE, dpf_BIZ_FILE, + dpf_UNKNOWN_FILE } dpfFILETYPE; + +typedef enum {dpf_FILE_GEOMETRY=0, dpf_FILE_MATERIAL=1 } dpfFILEFORMAT; + +typedef enum {dpfREAD, dpfWRITE} dpfFILEMODE; + +/* New enumerated types */ +typedef enum { dpf_MIN_DEFAULT=0, dpf_MIN_POINT_SAMPLED=1, + dpf_MIN_BILINEAR=2, dpf_MIN_TRILINEAR=3, + dpf_MIN_MIP_MAP_LINEAR=4, dpf_MIN_MIP_MAP_BILINEAR=5, + dpf_MIN_MIP_MAP_TRILINEAR=6, dpf_MIN_MIP_MAP_QUADLINEAR=7, + dpf_MIN_MIP_MAP_POINT_SAMPLED=8 } dpfMINIFY; +typedef enum { dpf_MAG_DEFAULT=0, dpf_MAG_POINT_SAMPLED=1, + dpf_MAG_BILINEAR=2, dpf_MAG_TRILINEAR=3, + dpf_MAG_BICUBIC=4, dpf_MAG_SHARPEN=5 } dpfMAGNIFY; +typedef enum { dpf_ALPHA_BLEND=0, dpf_ALPHA_CUT=1, + dpf_ALPHA_BLEND_CUT=2 } dpfALPHA ; +typedef enum { dpf_WRAP_REPEAT=0, dpf_WRAP_CLAMP=1, dpf_WRAP_SELECT=2 } dpfWRAP ; +typedef enum { dpf_DETAIL_NONE=0, dpf_DETAIL_ADD=1, + dpf_DETAIL_MODULATE=2 } dpfDETAIL ; +typedef enum { dpf_TRANS_SNAP=0, dpf_TRANS_BLEND=1 } dpfTRANSITION ; +typedef enum { dpf_MAT_NONE=0, dpf_MAT_NAMED=1, + dpf_MAT_DEFAULT=2, dpf_MAT_F_MATERIAL=3 } dpfMATTYPE ; +typedef enum { dpf_MATTXT_NONE=0, dpf_MATTXT_DEFAULT=1, + dpf_MATTXT_NAMED=2 } dpfMATTXTTYPE ; +typedef enum { dpf_PLANE_NORMAL=0, dpf_PLANE_UNDERLAY=1, + dpf_PLANE_OVERLAY=2 } dpfPLANE ; +typedef enum { dpf_FACET_NONE=0, dpf_FACET_BACKFACE=1, + dpf_FACET_FRONTFACE=2, dpf_FACET_TWOFACED=3 } dpfFACET ; +typedef enum { dpf_DM_FILLED=0, dpf_DM_WIREFRAME=1, dpf_DM_DOTTED=2 } dpfDRAWMODE ; +typedef enum { dpf_PREC_SINGLE=0, dpf_PREC_DOUBLE=1 } dpfPRECISION ; +typedef enum { dpf_UNIT_INCH=0, dpf_UNIT_METRE=1 } dpfUNIT ; +typedef enum { dpf_FONT_QUICK=0, dpf_FONT_BITMAP=1, dpf_FONT_VECTOR=2, + dpf_FONT_POLY_2D=3, dpf_FONT_POLY_3D=4, dpf_FONT_TEXTURE=5 } dpfFONT ; +typedef enum { dpf_AUTO_OFF=0, dpf_AUTO_ON=1 } dpfAUTO ; +typedef enum { dpf_LOCK_OFF=0, dpf_LOCK_ON=1 } dpfLOCK ; + +struct dpfSTRINGTYPE ; +typedef struct dpfSTRINGTYPE *dpfSTRINGPTR ; + +struct dpfSURFACETYPE ; +typedef struct dpfSURFACETYPE *dpfSURFACEPTR; + +struct dpfBOUNDTYPE ; +typedef struct dpfBOUNDTYPE *dpfBOUNDPTR ; + +struct dpfTEXTURETYPE ; +typedef struct dpfTEXTURETYPE *dpfTEXTUREPTR ; + +struct dpfRAMPTYPE ; +typedef struct dpfRAMPTYPE *dpfRAMPPTR ; + +struct dpfMATERIALTYPE ; +typedef struct dpfMATERIALTYPE *dpfMATERIALPTR ; + +struct dpfVERTEXTYPE ; +typedef struct dpfVERTEXTYPE *dpfVERTEXPTR ; + +struct dpfSLISTTYPE; +typedef struct dpfSLISTTYPE *dpfSLISTPTR ; + +struct dpfCLISTTYPE; +typedef struct dpfCLISTTYPE *dpfCLISTPTR ; + +struct dpfSPHERENODETYPE ; +typedef struct dpfSPHERENODETYPE *dpfSPHERENODEPTR ; + +struct dpfTEXTNODETYPE ; +typedef struct dpfTEXTNODETYPE *dpfTEXTNODEPTR ; + +struct dpfPOLYGONTYPE ; +typedef struct dpfPOLYGONTYPE *dpfPOLYGONPTR ; + +struct dpfGEOMETRYTYPE ; +typedef struct dpfGEOMETRYTYPE *dpfGEOMETRYPTR ; + +struct dpfPATCHTYPE ; +typedef struct dpfPATCHTYPE *dpfPATCHPTR ; + +struct dpfLODTYPE ; +typedef struct dpfLODTYPE *dpfLODPTR ; + +struct dpfOBJECTTYPE ; +typedef struct dpfOBJECTTYPE *dpfOBJECTPTR ; + +struct dpfHEADERTYPE ; +typedef struct dpfHEADERTYPE *dpfHEADERPTR ; + +struct dpfFILE_TYPE ; +typedef struct dpfFILE_TYPE *dpfFILEPTR ; + +/* ptools declaration */ + +struct dptTRIANGLETYPE ; +typedef struct dptTRIANGLETYPE *dptTRIANGLEPTR ; +struct dptMESHTYPE ; +typedef struct dptMESHTYPE *dptMESHPTR ; + +/*****************************************************************************/ +/* Externally callable Functions. */ +/*****************************************************************************/ +/* Useful macros */ + +#define dpfRGBCmp(a,b) memcmp(a, b, sizeof(float32)*3) +#define dpfRGBACmp(a,b) memcmp(a, b, sizeof(dpfRGBA)) +#define dpfTextCmp(a,b) memcmp(a, b, sizeof(float32)*2) +#define dpfRGBACpy(a,b) memcpy(a, b, sizeof(dpfRGBA)) +#define dpfTextCpy(a,b) memcpy(a, b, sizeof(dpfTEXT)) + +#define dpfBadFloat(f) (((*(long *)&(f) & 0x7f800000L)==0x7f800000L)) + +/*****************************************************************************/ +/* pfsurfac Surfaces */ +void +dpfInitSurface(dpfSURFACEPTR); /* Set to dpfINITSURFACE */ +void +dpfReinitSurface(dpfSURFACEPTR surf); +void +dpfCpySurface(dpfSURFACEPTR surf1, dpfSURFACEPTR surf2) ; +int32 +dpfCmpSurface(dpfSURFACEPTR s1, dpfSURFACEPTR s2) ; +/* if s1 == s2 then return 0, else return non-zero */ + + +/* Set surface characturistics */ +void +dpfSetSurface(dpfSURFACEPTR surf, dpfSURFACEPTR source) ; +/* Set material name literally sets the name to the given pointer, +** so make sure it dynamically allocated and not used by anything else! +** If in doubt use copy name which creates a new dynamically allocated name. +*/ +void +dpfSetSurfaceName(dpfSURFACEPTR surf, char *name) ; +void +dpfSetSurfaceF_Material(dpfSURFACEPTR surf, dpfMATTYPE Material, char *MatName) ; +void +dpfSetSurfaceB_Material(dpfSURFACEPTR surf, dpfMATTYPE Material, char *MatName) ; +void +dpfSetSurfaceVertex(dpfSURFACEPTR surf, uint8 Characturistic, uint8 State) ; +void +dpfSetSurfacePlane(dpfSURFACEPTR surf, dpfPLANE Plane) ; +void +dpfSetSurfaceFacet(dpfSURFACEPTR surf, dpfFACET Facet) ; +void +dpfSetSurfaceDecal(dpfSURFACEPTR surf, int32 decal) ; +void +dpfSetSurfaceDrawMode(dpfSURFACEPTR surf, dpfDRAWMODE DrawMode, uint8 Width) ; +void +dpfSetSurfaceLock(dpfSURFACEPTR surf, dpfLOCK lock) ; +void +dpfSetSurfaceSpecial(dpfSURFACEPTR surf, dpfSTRINGPTR Special) ; + +/* Get surface characturistics */ +/* Returns a pointer to THE name. so don't destroy */ +char * +dpfGetSurfaceName(dpfSURFACEPTR surf) ; +dpfMATTYPE +dpfGetSurfaceF_Material(dpfSURFACEPTR surf, char **MatName) ; +dpfMATTYPE +dpfGetSurfaceB_Material(dpfSURFACEPTR surf, char **MatName) ; +uint8 +dpfGetSurfaceVertex(dpfSURFACEPTR surf) ; +dpfPLANE +dpfGetSurfacePlane(dpfSURFACEPTR surf) ; +dpfFACET +dpfGetSurfaceFacet(dpfSURFACEPTR surf) ; +int32 +dpfGetSurfaceDecal(dpfSURFACEPTR surf) ; +dpfDRAWMODE +dpfGetSurfaceDrawMode(dpfSURFACEPTR surf, uint8 *Width) ; +dpfLOCK +dpfGetSurfaceLock(dpfSURFACEPTR surf) ; +dpfSTRINGPTR +dpfGetSurfaceSpecial(dpfSURFACEPTR surf) ; + + +/* pfvertex Vertices & VertLists */ +/* Vertices */ +void +dpfSetVertexFlag(uint8 vflag, uint8 textCook, uint8 overRide) ; +uint8 +dpfCheckVertexFlag(uint8 vflag, uint8 useOverRide) ; +dpfVERTEXPTR +dpfCreateVertex(void); +dpfVERTEXPTR +dpfCreateVertexBlock(int32 numVerts); +int32 +dpfCreateVertexTable(dpfGEOMETRYPTR geom, dpfVERTEXPTR **table) ; +int32 +dpfAddVertex(dpfGEOMETRYPTR geom, dpfVERTEXPTR vertex) ; +int32 +dpfUnlinkVertex(dpfVERTEXPTR); +int32 +dpfFreeVertex(dpfVERTEXPTR); +int32 +dpfFreeVertexList(dpfVERTEXPTR vert) ; +void +dpfKillVertices() ; + +/* The following calls are used to loop through all the vertices in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetVertexCount(dpfGEOMETRYPTR geom) ; +dpfVERTEXPTR +dpfGetFrstVertex(dpfGEOMETRYPTR geom) ; +dpfVERTEXPTR +dpfGetNextVertex(dpfVERTEXPTR vertex) ; +dpfVERTEXPTR +dpfGetPrevVertex(dpfVERTEXPTR vertex) ; +dpfVERTEXPTR +dpfGetNthVertex(dpfGEOMETRYPTR geom, int32 Nth) ; + + +/* Vertex info */ +void +dpfGetVertexPoint(dpfVERTEXPTR, dmVector) ; +void +dpfGetVertexNormal(dpfVERTEXPTR, dmVector) ; +void +dpfGetVertexColour(dpfVERTEXPTR, dpfRGBA) ; +void +dpfGetVertexTexture(dpfVERTEXPTR, dpfTEXT) ; + +void +dpfSetVertexPoint(dpfVERTEXPTR, dmVector) ; +void +dpfSetVertexNormal(dpfVERTEXPTR, dmVector) ; +void +dpfSetVertexColour(dpfVERTEXPTR, dpfRGBA) ; +void +dpfSetVertexTexture(dpfVERTEXPTR, dpfTEXT) ; + +/* Pmesh functions */ +/* Connection List's */ +dpfCLISTPTR +dpfCreateCList(int32 pcount, int32 fcount); +int32 +dpfAddCList(dpfGEOMETRYPTR geom, dpfCLISTPTR cList) ; +int32 +dpfUnlinkCList(dpfCLISTPTR); +int32 +dpfFreeCList(dpfCLISTPTR); +int32 +dpfFreeCListList(dpfCLISTPTR cList) ; + +/* The following calls are used to loop through all the vertLists in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetCListCount(dpfGEOMETRYPTR geom) ; +dpfCLISTPTR +dpfGetFrstCList(dpfGEOMETRYPTR geom) ; +dpfCLISTPTR +dpfGetNextCList(dpfCLISTPTR cList) ; +dpfCLISTPTR +dpfGetPrevCList(dpfCLISTPTR cList) ; + +/* VertList Info */ +int32 +dpfGetCListPCount(dpfCLISTPTR cList) ; +int32 +dpfGetCListFCount(dpfCLISTPTR cList) ; +int32 * +dpfCreateCListFace(dpfCLISTPTR cList) ; +int32 * +dpfGetCListFace(dpfCLISTPTR cList, int32 fno) ; +void +dpfSetCListFace(dpfCLISTPTR cList, int32 fno, int32 *verts) ; +int32 +dpfFreeCListFace(dpfCLISTPTR cList, int32 fno) ; + +/* Strip List's */ +dpfSLISTPTR +dpfCreateSList(int32 pcount, int32 vcount); +int32 +dpfAddSList(dpfGEOMETRYPTR geom, dpfSLISTPTR sList) ; +int32 +dpfUnlinkSList(dpfSLISTPTR); +int32 +dpfFreeSList(dpfSLISTPTR); +int32 +dpfFreeSListList(dpfSLISTPTR sList) ; + +/* The following calls are used to loop through all the Strip Lists in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetSListCount(dpfGEOMETRYPTR geom) ; +dpfSLISTPTR +dpfGetFrstSList(dpfGEOMETRYPTR geom) ; +dpfSLISTPTR +dpfGetNextSList(dpfSLISTPTR sList) ; +dpfSLISTPTR +dpfGetPrevSList(dpfSLISTPTR sList) ; + +/* Strip List Info */ +int32 +dpfGetSListPCount(dpfSLISTPTR sList) ; +int32 +dpfGetSListVCount(dpfSLISTPTR sList) ; +int32 +dpfAddSListVertex(dpfSLISTPTR sList, int32 vertNo) ; +int32 * +dpfGetSListVertex(dpfSLISTPTR sList, int32 vno) ; +void +dpfSetSListVertex(dpfSLISTPTR sList, int32 vno, int32 vertNo) ; + + +/* Sphere's */ +dpfSPHERENODEPTR +dpfCreateSphereNode(void); +dpfSPHERENODEPTR +dpfCreateSphereNodeBlock(int32 numVLists) ; +int32 +dpfAddSphereNode(dpfGEOMETRYPTR geom, dpfSPHERENODEPTR vertex) ; +int32 +dpfUnlinkSphereNode(dpfSPHERENODEPTR); +int32 +dpfFreeSphereNode(dpfSPHERENODEPTR); +int32 +dpfFreeSphereNodeList(dpfSPHERENODEPTR vertList) ; + + +/* The following calls are used to loop through all the spheres in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetSphereNodeCount(dpfGEOMETRYPTR geom) ; +dpfSPHERENODEPTR +dpfGetFrstSphereNode(dpfGEOMETRYPTR geom) ; +dpfSPHERENODEPTR +dpfGetNextSphereNode(dpfSPHERENODEPTR vertList) ; +dpfSPHERENODEPTR +dpfGetPrevSphereNode(dpfSPHERENODEPTR vertList) ; + +/* Sphere Info */ +void +dpfGetSphereDice(dpfGEOMETRYPTR geom, uint8 *u_dice, uint8 *v_dice) ; +void +dpfSetSphereDice(dpfGEOMETRYPTR geom, uint8 u_dice, uint8 v_dice) ; + +float32 +dpfGetSphereNodeData(dpfSPHERENODEPTR vertList, dmVector point) ; +void +dpfSetSphereNodeData(dpfSPHERENODEPTR vertList, float32 radius, + dmVector point) ; + +/* Text */ +dpfTEXTNODEPTR +dpfCreateTextNode(void) ; +dpfTEXTNODEPTR +dpfCreateTextNodeBlock(int32 numTexts) ; +int32 +dpfUnlinkTextNode(dpfTEXTNODEPTR text) ; +int32 +dpfAddTextNode(dpfGEOMETRYPTR geom, dpfTEXTNODEPTR text) ; +int32 +dpfFreeTextNode(dpfTEXTNODEPTR text) ; +int32 +dpfFreeTextNodeList(dpfTEXTNODEPTR text) ; + +/* move through text list */ +int32 +dpfGetTextNodeCount(dpfGEOMETRYPTR geom) ; +dpfTEXTNODEPTR +dpfGetFrstTextNode(dpfGEOMETRYPTR geom) ; +dpfTEXTNODEPTR +dpfGetNextTextNode(dpfTEXTNODEPTR text) ; +dpfTEXTNODEPTR +dpfGetPrevTextNode(dpfTEXTNODEPTR text) ; + +/* Get and set text global info */ +dpfFONT +dpfGetTextFont(dpfGEOMETRYPTR geom) ; +void +dpfGetTextOrientation(dpfGEOMETRYPTR geom, dmVector orn) ; +void +dpfGetTextScale(dpfGEOMETRYPTR geom, dmVector scale) ; +void +dpfSetTextFont(dpfGEOMETRYPTR geom, dpfFONT font) ; +void +dpfSetTextOrientation(dpfGEOMETRYPTR geom, dmVector orn) ; +void +dpfSetTextScale(dpfGEOMETRYPTR geom, dmVector scale) ; + +/* get and set text node info */ +void +dpfGetTextNodePoint(dpfTEXTNODEPTR text, dmVector point) ; +char * +dpfGetTextNodeString(dpfTEXTNODEPTR text) ; +void +dpfSetTextNodePoint(dpfTEXTNODEPTR text, dmVector point) ; +void +dpfSetTextNodeString(dpfTEXTNODEPTR text, char *str1) ; + +/* Get and set line global info */ +uint8 +dpfGetLineThickness(dpfGEOMETRYPTR geom) ; +void +dpfSetLineThickness(dpfGEOMETRYPTR geom, uint8 thickness) ; + +/* pfgeomet Geometry & strips & pmeshes etc */ +dpfGEOMETRYPTR +dpfCreatePoint(void) ; +dpfGEOMETRYPTR +dpfCreatePolygon(void) ; +dpfGEOMETRYPTR +dpfCreateTristrip(void); +dpfGEOMETRYPTR +dpfCreatePolystrip(void); +dpfGEOMETRYPTR +dpfCreatePmesh(void); +dpfGEOMETRYPTR +dpfCreateSphere(void); +dpfGEOMETRYPTR +dpfCreateLine(void) ; +dpfGEOMETRYPTR +dpfCreateText(void) ; +int32 +dpfAddGeometry(dpfPATCHPTR patch, dpfGEOMETRYPTR geom) ; +int32 +dpfUnlinkGeometry(dpfGEOMETRYPTR geometry) ; +int32 +dpfFreeGeometry(dpfGEOMETRYPTR); +int32 +dpfFreeFileGeometries(dpfFILEPTR file) ; +int32 +dpfTurnGeometry2Pmesh(dpfGEOMETRYPTR geom) ; + +/* The following calls are used to loop through all the geometries in a +** file. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfPATCHPTR +dpfGetGeometryParent(dpfGEOMETRYPTR geom) ; +dpfGEOMETRYPTR +dpfGetFrstGeometry(dpfPATCHPTR patch) ; +dpfGEOMETRYPTR +dpfGetNextGeometry(dpfGEOMETRYPTR geom) ; +dpfGEOMETRYPTR +dpfGetPrevGeometry(dpfGEOMETRYPTR geom) ; + +/* Geometry info */ +int32 +dpfGetGeometryType(dpfGEOMETRYPTR geom) ; + +/* pfpatch patches */ +dpfPATCHPTR +dpfCreatePatch(void) ; +int32 +dpfAddPatch(dpfLODPTR lod, dpfPATCHPTR patch) ; +int32 +dpfJoinPatch(dpfPATCHPTR patch1, dpfPATCHPTR patch2) ; +int32 +dpfUnlinkPatch(dpfPATCHPTR) ; +int32 +dpfFreePatch(dpfPATCHPTR) ; + +/* The following calls are used to loop through all the patches in an +** LOD. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfLODPTR +dpfGetPatchParent(dpfPATCHPTR patch) ; +dpfPATCHPTR +dpfGetFrstPatch(dpfLODPTR object) ; +dpfPATCHPTR +dpfGetNextPatch(dpfPATCHPTR patch) ; +dpfPATCHPTR +dpfGetPrevPatch(dpfPATCHPTR patch) ; + +/* Get surface pointer for the surface setting and getting calls */ +dpfSURFACEPTR +dpfGetPatchSurface(dpfPATCHPTR patch) ; + +/* pflod LODs */ +dpfLODPTR +dpfCreateLOD(void) ; +int32 +dpfAddLOD(dpfOBJECTPTR object, dpfLODPTR lod) ; +int32 +dpfJoinLOD(dpfLODPTR lod1, dpfLODPTR lod2) ; +int32 +dpfUnlinkLOD(dpfLODPTR) ; +int32 +dpfFreeLOD(dpfLODPTR) ; +int32 +dpfCmpLOD(dpfLODPTR lod1, dpfLODPTR lod2) ; + +/* The following calls are used to loop through all the lods in a +** file. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfOBJECTPTR +dpfGetLODParent(dpfLODPTR) ; +dpfLODPTR +dpfGetFrstLOD(dpfOBJECTPTR) ; +dpfLODPTR +dpfGetNextLOD(dpfLODPTR) ; +dpfLODPTR +dpfGetPrevLOD(dpfLODPTR) ; + +/* LOD info */ +char * +dpfGetLODName(dpfLODPTR lod) ; +void +dpfGetLODDistance(dpfLODPTR lod, float32 *InDist, float32 *OutDist) ; +dpfTRANSITION +dpfGetLODTransition(dpfLODPTR lod) ; +int32 +dpfGetLODReference(dpfLODPTR lod, dmVector reference) ; + +void +dpfSetLODName(dpfLODPTR lod, char *name) ; +void +dpfSetLODDistance(dpfLODPTR lod, float32 InDist, float32 OutDist) ; +void +dpfSetLODTransition(dpfLODPTR lod, dpfTRANSITION Transition) ; +void +dpfSetLODReference(dpfLODPTR lod, int32 referenceFlag, dmVector reference) ; + + +/* pfobject objects */ +dpfOBJECTPTR +dpfCreateObject(void) ; +int32 +dpfAddObject(dpfFILEPTR file, dpfOBJECTPTR object) ; +int32 +dpfJoinObject(dpfOBJECTPTR object1, dpfOBJECTPTR object2) ; +int32 +dpfUnlinkObject(dpfOBJECTPTR) ; +int32 +dpfFreeObject(dpfOBJECTPTR) ; + +/* The following calls are used to loop through all the objects in a +** file. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfFILEPTR +dpfGetObjectParent(dpfOBJECTPTR) ; +dpfOBJECTPTR +dpfGetFrstObject(dpfFILEPTR) ; +dpfOBJECTPTR +dpfGetNextObject(dpfOBJECTPTR) ; +dpfOBJECTPTR +dpfGetPrevObject(dpfOBJECTPTR) ; + +/* Get surface pointer for the surface setting and getting calls */ +dpfSURFACEPTR +dpfGetObjectSurface(dpfOBJECTPTR object) ; + +/* pffile file structure */ +int32 +dpfGetAllFile(char *name, dpfFILEPTR *file, uint8 verMajor, uint8 verMinor) ; +dpfFILEPTR +dpfOpenAllFile(char *name, uint8 verMajor, uint8 verMinor) ; +int32 +dpfGetAllFileBody(dpfFILEPTR file) ; +int32 +dpfGetFile(char *name, dpfFILEPTR *file) ; +dpfFILEPTR +dpfOpenFile(char *name) ; +int32 +dpfGetFileBody(dpfFILEPTR file) ; + +int32 +dpfPutAllFile(char *name, dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutAllFileBody(dpfFILEPTR Dfile,dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutFile(char *name, dpfFILEPTR Sfile) ; +int32 +dpfPutFileBody(dpfFILEPTR Dfile,dpfFILEPTR Sfile) ; +dpfFILEPTR +dpfOpenNewFile(char *name, dpfFILEFORMAT form, dpfFILETYPE fileType) ; + +dpfFILEPTR +dpfCreateFile(char *name) ; +int32 +dpfJoinFile(dpfFILEPTR file1, dpfFILEPTR file2) ; +int32 +dpfCloseFile(dpfFILEPTR file) ; +int32 +dpfFreeFile(dpfFILEPTR) ; +int32 +dpfKillFile(dpfFILEPTR file) ; + +/* File info */ +dpfFILETYPE +dpfGetFileType(dpfFILEPTR file) ; +dpfFILEFORMAT +dpfGetFileFormat(dpfFILEPTR file) ; +char * +dpfGetFileName(dpfFILEPTR file) ; + +/* File info */ +void +dpfSetFileType(dpfFILEPTR file, dpfFILETYPE type) ; +void +dpfSetFileFormat(dpfFILEPTR file,dpfFILEFORMAT format) ; + +/* pfinfo information on struction, read and written */ +int32 +dpfCountFileContent(dpfFILEPTR file) ; +int32 +dpfGetFileNoMaterials(dpfFILEPTR file) ; +int32 +dpfGetFileNoTextures(dpfFILEPTR file) ; +int32 +dpfGetFileNoRamps(dpfFILEPTR file) ; +int32 +dpfGetFileNoObjects(dpfFILEPTR file) ; +int32 +dpfGetFileNoLODs(dpfFILEPTR file) ; +int32 +dpfGetFileNoPatches(dpfFILEPTR file) ; +int32 +dpfGetFileNoGeometries(dpfFILEPTR file) ; +int32 +dpfGetFileNoPolystrips(dpfFILEPTR file) ; +int32 +dpfGetFileNoTristrips(dpfFILEPTR file) ; +int32 +dpfGetFileNoPmeshes(dpfFILEPTR file) ; +int32 +dpfGetFileNoSLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoSFaces(dpfFILEPTR file) ; +int32 +dpfGetFileSFtimesP(dpfFILEPTR file) ; +int32 +dpfGetFileNoCLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoCFaces(dpfFILEPTR file) ; +int32 +dpfGetFileCFtimesP(dpfFILEPTR file) ; +int32 +dpfGetFileNoVertices(dpfFILEPTR file) ; +int32 +dpfGetFileNoTriangles(dpfFILEPTR file) ; +int32 +dpfGetFileTotNoTriangles(dpfFILEPTR file) ; +int32 +dpfGetFileNoSphereLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoSpheres(dpfFILEPTR file) ; +int32 +dpfGetFileNoPointLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoPoints(dpfFILEPTR file) ; +int32 +dpfGetFileNoLines(dpfFILEPTR file) ; +int32 +dpfGetFileNoLineNodes(dpfFILEPTR file) ; +int32 +dpfGetFileNoTexts(dpfFILEPTR file) ; +int32 +dpfGetFileNoTextStrings(dpfFILEPTR file) ; +int32 +dpfGetFileNoPolygons(dpfFILEPTR file) ; +int32 +dpfGetFileNoPolygonVertices(dpfFILEPTR file) ; + + +/* pfmaterl materials */ +dpfMATERIALPTR +dpfCreateMaterial(void) ; +char * +dpfCreateMaterialName(char *extPath, char *library, char *mname) ; +void +dpfCpyMaterial(dpfMATERIALPTR mat1, dpfMATERIALPTR mat2) ; +int32 +dpfCmpMaterial(dpfMATERIALPTR mat1, dpfMATERIALPTR mat2) ; +dpfMATERIALPTR +dpfAddMaterial(dpfFILEPTR file, dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfAddV1Material(dpfFILEPTR file, dpfMATERIALPTR mat) ; +int32 +dpfFreeMaterial(dpfMATERIALPTR mat) ; + +dpfFILEPTR +dpfGetMaterialParent(dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfGetFrstMaterial(dpfFILEPTR file) ; +dpfMATERIALPTR +dpfGetNextMaterial(dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfGetPrevMaterial(dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfFindMaterial(dpfFILEPTR fp, char *matName) ; + +/* Set material name literally sets the name to the given pointer, +** so make sure it dynamically allocated and not used by anything else! +** If in doubt use copy name which creates a new dynamically allocated name. +*/ +void +dpfSetMaterialName(dpfMATERIALPTR mat, char *name) ; +void +dpfSetMaterialTexture(dpfMATERIALPTR mat, dpfMATTXTTYPE TxtType, char *name) ; +void +dpfSetMaterialRamp(dpfMATERIALPTR mat, char *name) ; +void +dpfSetMaterialAmbient(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialDiffuse(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialSpecular(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialEmissive(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialOpacity(dpfMATERIALPTR mat,dpfRGBA colour) ; + +/* Returns a pointer to THE name. so don't destroy */ +char * +dpfGetMaterialName(dpfMATERIALPTR mat) ; +dpfMATTXTTYPE +dpfGetMaterialTexture(dpfMATERIALPTR mat, char **name) ; +char * +dpfGetMaterialRamp(dpfMATERIALPTR mat) ; +void +dpfGetMaterialAmbient(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialDiffuse(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialSpecular(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialEmissive(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialOpacity(dpfMATERIALPTR mat,dpfRGBA colour) ; + + +/* pfile General file loading calls */ +void +dpfErrorOn(void) ; +void +dpfErrorOff(void) ; +void +dpfDebugOn(void) ; +void +dpfDebugOff(void) ; + +/* Names and Strings and things */ +char * +dpfCreateName(char *name) ; +char * +dpfDuplicateName(char *name) ; +void +dpfFreeName(char *name) ; +/* the return from cmp is similar to strcmp, ie 0 if the same, else non-zero */ +int32 +dpfCmpName(char *name1, char *name2) ; + +/* Strings can have '\0' in them, so the first byte is the string length */ +/* Create uses the str as its string, copy mallocs more space and copies +** in the string str +*/ +dpfSTRINGPTR +dpfCreateString(void) ; +dpfSTRINGPTR +dpfDuplicateString(dpfSTRINGPTR str) ; +int32 +dpfSetString(dpfSTRINGPTR str, int32 Length, uint8 *theStr) ; +void +dpfFreeString(dpfSTRINGPTR str) ; +/* the return from cmp is similar to strcmp, ie 0 if the same, else non-zero */ +int32 +dpfCmpString(dpfSTRINGPTR str1, dpfSTRINGPTR str2) ; +int32 +dpfGetStringLength(dpfSTRINGPTR str) ; +uint8 * +dpfGetStringString(dpfSTRINGPTR str) ; + +/* pfcheck checks input values */ +float32 +dpfCheckRGB(float32 colour) ; +float32 +dpfCheckAlpha(float32 alpha) ; +float32 +dpfCheckV1Power(float32 power) ; +float32 +dpfCheckPower(float32 power) ; +float32 +dpfCheckOpacity(float32 opacity) ; +uint16 +dpfCheckDice(uint16 dice) ; + +/* ramp stuff */ +dpfRAMPPTR +dpfCreateRamp(void); +int32 +dpfCmpRamp(dpfRAMPPTR r1, dpfRAMPPTR r2) ; +dpfRAMPPTR +dpfAddRamp(dpfFILEPTR file, dpfRAMPPTR r) ; +int32 +dpfFreeRamp(dpfRAMPPTR r) ; + +dpfFILEPTR +dpfGetRampParent(dpfRAMPPTR mat) ; +dpfRAMPPTR +dpfGetFrstRamp(dpfFILEPTR file) ; +dpfRAMPPTR +dpfGetNextRamp(dpfRAMPPTR mat) ; +dpfRAMPPTR +dpfGetPrevRamp(dpfRAMPPTR mat) ; +dpfRAMPPTR +dpfFindRamp(dpfFILEPTR fp, char *rampName) ; + +void +dpfSetRampName(dpfRAMPPTR r, char *a); +void +dpfSetRampData(dpfRAMPPTR r, dpfRGBA a, dpfRGBA b); +char * +dpfGetRampName(dpfRAMPPTR r); +void +dpfGetRampData(dpfRAMPPTR r, dpfRGBA data0, dpfRGBA data1) ; + +/* new boundary stuff */ +dpfBOUNDPTR +dpfCreateBound(void) ; +int32 +dpfUnlinkBound(dpfBOUNDPTR bound) ; +int32 +dpfAddFileBound(dpfFILEPTR file, dpfBOUNDPTR bound) ; +int32 +dpfAddBoundBound(dpfBOUNDPTR prnt, dpfBOUNDPTR bound) ; +int32 +dpfFreeBound(dpfBOUNDPTR bound) ; +dpfFILEPTR +dpfGetBoundFile(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetBoundParent(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetFileBound(dpfFILEPTR file) ; +dpfBOUNDPTR +dpfGetFrstBound(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetNextBound(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetPrevBound(dpfBOUNDPTR bound) ; +void +dpfSetBoundSphere(dpfBOUNDPTR bound, int32 present, float32 radius, + dmVector point) ; +void +dpfSetBoundBox(dpfBOUNDPTR bound,int32 present,dmVector bMin,dmVector bMax, dmVector orien) ; +void +dpfSetBoundPmesh(dpfBOUNDPTR bound, dpfGEOMETRYPTR pmesh) ; +void +dpfSetBoundAuto(dpfBOUNDPTR bound, uint8 Auto) ; +void +dpfSetBoundLODName(dpfBOUNDPTR bound, char *name) ; +void +dpfSetBoundObjectName(dpfBOUNDPTR bound, char *name) ; +int32 +dpfGetBoundSphere(dpfBOUNDPTR bound, float32 *radius, dmVector point) ; +int32 +dpfGetBoundBox(dpfBOUNDPTR bound, dmVector bMin, dmVector bMax, dmVector orien) ; +dpfGEOMETRYPTR +dpfGetBoundPmesh(dpfBOUNDPTR bound) ; +uint8 +dpfGetBoundAuto(dpfBOUNDPTR bound) ; +void +dpfCalcBBoxInitialize(dpfBOUNDPTR bound) ; +void +dpfCalcPointBBox(dmVector vec, dmVector MinVec, dmVector MaxVec) ; +int32 +dpfCalcGeometryBBox(dpfGEOMETRYPTR geom, dpfBOUNDPTR bound) ; +int32 +dpfCalcPatchBBox(dpfPATCHPTR patch, dpfBOUNDPTR bound) ; +int32 +dpfCalcLODBBox(dpfLODPTR lod, dpfBOUNDPTR bound) ; +int32 +dpfCalcBBox(dpfFILEPTR file, dpfBOUNDPTR bound) ; +int32 +dpfCalcGeometryBSphere(dpfGEOMETRYPTR geom, dpfBOUNDPTR bound) ; +int32 +dpfCalcPatchBSphere(dpfPATCHPTR patch, dpfBOUNDPTR bound) ; +int32 +dpfCalcBSphere(dpfFILEPTR file, dpfBOUNDPTR bound) ; +int32 +dpfCheckBound(dpfFILEPTR file) ; + +/*** texture stuff ***/ +dpfTEXTUREPTR +dpfCreateTexture(void); +int32 +dpfCpyTexture(dpfTEXTUREPTR txt1, dpfTEXTUREPTR txt2) ; +int32 +dpfCmpTexture(dpfTEXTUREPTR txt1, dpfTEXTUREPTR txt2) ; +dpfTEXTUREPTR +dpfAddTexture(dpfFILEPTR file, dpfTEXTUREPTR txt) ; +int32 +dpfUnlinkTexture(dpfTEXTUREPTR txt) ; +int32 +dpfFreeTexture(dpfTEXTUREPTR txt) ; + +dpfFILEPTR +dpfGetTextureParent(dpfTEXTUREPTR txt) ; +dpfTEXTUREPTR +dpfGetFrstTexture(dpfFILEPTR file) ; +dpfTEXTUREPTR +dpfGetNextTexture(dpfTEXTUREPTR txt) ; +dpfTEXTUREPTR +dpfGetPrevTexture(dpfTEXTUREPTR txt) ; +dpfTEXTUREPTR +dpfFindTexture(dpfFILEPTR fp, char *txtName) ; + +void +dpfSetTextureName(dpfTEXTUREPTR t, char *a); +void +dpfSetTextureMap(dpfTEXTUREPTR t, char *a); +void +dpfSetTextureWrap(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureUWrap(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureVWrap(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureDetail(dpfTEXTUREPTR t, dpfDETAIL detail, char *name) ; +void +dpfSetTextureMinify(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureMagnify(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureAlpha(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureBitslice(dpfTEXTUREPTR t, uint8 a); + +char * +dpfGetTextureName(dpfTEXTUREPTR t) ; +char * +dpfGetTextureMap(dpfTEXTUREPTR t) ; +void +dpfGetTextureWrap(dpfTEXTUREPTR t, int32 a) ; +dpfWRAP +dpfGetTextureUWrap(dpfTEXTUREPTR t) ; +dpfWRAP +dpfGetTextureVWrap(dpfTEXTUREPTR t) ; +dpfDETAIL +dpfGetTextureDetail(dpfTEXTUREPTR t, char **name) ; +dpfMINIFY +dpfGetTextureMinify(dpfTEXTUREPTR t) ; +dpfMAGNIFY +dpfGetTextureMagnify(dpfTEXTUREPTR t) ; +dpfALPHA +dpfGetTextureAlpha(dpfTEXTUREPTR t) ; +uint8 +dpfGetTextureBitslice(dpfTEXTUREPTR t) ; + + +/*** header stuff ***/ +void +dpfSetFileVersion(dpfFILEPTR f, uint8 i, uint8 j); +void +dpfSetFileDate(dpfFILEPTR f, uint8 i, uint8 j, uint8 k); +void +dpfSetFileTime(dpfFILEPTR f, uint8 i, uint8 j); +void +dpfSetFileUnit(dpfFILEPTR f, dpfUNIT i); +void +dpfSetFileScale(dpfFILEPTR f, float32 i); +void +dpfSetFilePrecision(dpfFILEPTR f, dpfPRECISION i); +void +dpfSetHeaderComment(dpfFILEPTR f, dpfSTRINGPTR i); + +void +dpfGetLibraryVersion(uint8 *i, uint8 *j) ; +int32 +dpfGetFileVersion(dpfFILEPTR f, uint8 *verMajor, uint8 *verMinor) ; +int32 +dpfGetFileDate(dpfFILEPTR f, uint8 *dpfday, uint8 *dpfmonth, uint8 *dpfyear) ; +int32 +dpfGetFileTime(dpfFILEPTR f, uint8 *dpfhours, uint8 *dpfminutes) ; +dpfUNIT +dpfGetFileUnit(dpfFILEPTR f) ; +float32 +dpfGetFileScale(dpfFILEPTR f) ; +dpfPRECISION +dpfGetFilePrecision(dpfFILEPTR f) ; +dpfSTRINGPTR +dpfGetFileComment(dpfFILEPTR f) ; + +/**************** callbacks *******************/ +/* The following functions are used to set callbacks + * for each of several structures. They are called when + * a structure has been completed and would normally be + * linked into the file structure. The procedure is passed + * a pointer to the structure to do with as it wishes and + * returns an integer value. If the return value is 1 the + * structure is freed, otherwise it is linked into the + * file structure as usual. + */ + + +/* new whizzy v1.0 -> v2.0 texture name converter stuff */ +struct dpfVISTEXTURETYPE ; +typedef struct dpfVISTEXTURETYPE *dpfVISTEXTUREPTR; + +dpfVISTEXTUREPTR +dpfCreateV1TextureList(char *mazName) ; +void +dpfSetFileVisList(dpfFILEPTR file, dpfVISTEXTUREPTR visList) ; +void +dpfConvertV1Texture(dpfFILEPTR Sfp, dpfMATERIALPTR Fmat, dpfMATERIALPTR Bmat) ; +void +dpfFreeV1TextureList(dpfVISTEXTUREPTR visList) ; + + +int32 +dpfCheckFile(dpfFILEPTR file) ; + + +#endif /* __PFILE_H__ */ + diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/PFPARSER.H b/CODE/RP/MUNGA_L4/libDPL/dsys/PFPARSER.H new file mode 100644 index 0000000..426483b --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/PFPARSER.H @@ -0,0 +1,97 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: pfparser.h,v $ + * REVISION: $Revision: 1.3 $ + * Date: $Date: 95/04/27 23:01:16 $ + * Author: $Author: bill $ + * RCS Ident: $Id: pfparser.h,v 1.3 95/04/27 23:01:16 bill Exp $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#ifndef __PFPARSER_H__ +#define __PFPARSER_H__ + +#include +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +#define dpp_MATCH_CASE 0 +#define dpp_ANY_CASE 1 + +/* On calls which either succeed or fail, dpgSUCCESS (0) or dpgERROR (-1) + * is returned. On calls to get next token however the following + * return values are also used + */ +#define dppEOF -2 +#define dppSTRING -3 +#define dppNUMBER -4 + +typedef struct dppKEYTAB +{ + int32 tok; + char *name; + int32 matchCase; +} dppKEYTAB ; + + +typedef struct dppFILE +{ + int32 lineNo; + int32 errorFlag; + char *fileName; + FILE *file; + char *whites ; + char comment ; + int32 pushedBackToken; + float number; + char *buffer; + int32 bufSize; + int32 bufPos; + dppKEYTAB *keyTab; +} dppFILE, *dppFILEPTR ; + + + +dppFILEPTR +dppOpenFile (char *name, FILE *fp, const char *whites, char comment, + dppKEYTAB *keyTable, int32 bufferSize); +void +dppCloseFile (dppFILEPTR fPtr); +char * +dppTokenToString (dppFILEPTR fptr, const int32 token); +int32 +dppPushToken (dppFILEPTR fptr, const int32 token); +int32 +dppNextToken (dppFILEPTR fptr); +int32 +dppReadToNextChar(dppFILEPTR fPtr, char endChr) ; +char * +dppMatchString (dppFILEPTR fptr); +int32 +dppMatchInt (dppFILEPTR fptr, int32 *num); +int32 +dppMatchFloat (dppFILEPTR fptr, float *num); +int32 +dppMatchCharacter (dppFILEPTR fptr, char c); +void +dppMoveToNextLine(dppFILEPTR fptr) ; + + +#endif /* __PFPARSER_H__ */ + diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/PGENERAL.H b/CODE/RP/MUNGA_L4/libDPL/dsys/PGENERAL.H new file mode 100644 index 0000000..7d390d7 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/PGENERAL.H @@ -0,0 +1,183 @@ +/* + * ---------------------------------------------------------------------------- + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: pgeneral.h,v $ + * Revision : $Revision: 1.1 $ + * Date : $Date: 95/04/27 23:01:16 $ + * Author : $Author: bill $ + * Last Modified : <260495.2024> + * + * Description + * + * Notes + * + * History + * + * + * ---------------------------------------------------------------------------- + */ + +/* + * The following functions are provided in this module + * + * Return flags - to be used in all libs and converters + * dpgSUCCESS=0, dpgERROR=-1 + * + * Verbose output setup (special "stderr" & "stdout") + * dpgSetOutput(n) + * + * Verbose warning setup and usage + * dpgSetWarnLevel(n) + * dpgWarn(n,(print stuff)) + * + * Verbose error setup and usage + * variable dpgErrNo - set to the last error num ; + * dpgSetErrorLevel(n) + * dpgError(num, n,(print stuff)) + * + * Verbose monitering setup and usage + * dpgSetMonitorFlag(n) + * dpgMonitor(flag,(print stuff)) + * + * Verbose bad parameter passed error handler + * dpgBadAddress(addr,String) + * + * Dying routine, outputs to the log and if not stderr, out to stderr + * dpgDie(level,(print stuff)) + * + * malloc and calloc routines that print out an error and exit on failure. + * dpgMalloc(size,string) + * dpgRealloc(pnt,size,string) + * dpgCalloc(nel,size,string) + * + * dm macro Extensions + * + */ + +#ifndef __PGENERAL_H__ +#define __PGENERAL_H__ + +#include +#include + +/* The program name must be defined and setup by the program */ +extern char *progname ; + +#define dpgSUCCESS 0 +#define dpgERROR -1 + +/* General error numbers */ + +#define dpgENO_NULL 0x1001 +#define dpgENO_ROPEN 0x1002 +#define dpgENO_READ 0x1003 +#define dpgENO_WOPEN 0x1004 +#define dpgENO_WRITE 0x1005 + +/* Verbose output setup (special "stderr" & "stdout") - returns dpgERROR + * if couldn't open the file, SUCCESS otherwise + */ +extern FILE *dpgLog ; + +int32 +dpgSetOutput(char *name) ; +#define dpgFlush() fflush(dpgLog) +/* internal functions */ + +/* If the next variable is non-zero then when any printing is done, a new + * line will be inserted and the variable will be reset to 0 */ +extern int32 dpgNewLine ; +#define dpgSetNewLine(v) (dpgNewLine=(v)) + +/* Verbose warning setup and usage */ +extern int32 dpgWarnLvl ; + +/* general printing routine */ +extern void dpgPrint(char *format, ...) ; +void +dpgPrintActivity(int32 Cur, int32 Tot) ; + +#define dpgIncWarnLevel() (dpgWarnLvl++) +#define dpgSetWarnLevel(n) (dpgWarnLvl = n) + +extern int32 __dpgWarn(char *format, ...) ; +#define dpgWarn(lvl,p) \ +((lvl <= dpgWarnLvl) ? (__dpgWarn p):dpgSUCCESS) + +/* Verbose error setup and usage */ +extern int32 dpgErrorLvl ; +extern int32 dpgErrNo ; + +#define dpgIncErrorLevel() (dpgErrorLvl++) +#define dpgSetErrorLevel(n) (dpgErrorLvl = n) +extern int32 __dpgError(char *format, ...) ; +#define dpgError(num,lvl,p) \ +((dpgErrNo = num),((lvl <= dpgErrorLvl) ? (__dpgError p):dpgERROR)) + +/* Verbose monitor setup and usage */ +extern int32 dpgMonitorFlg ; + +#define dpgSetMonitorFlag(n) (dpgMonitorFlg = n) +extern int32 __dpgMonitor(char *format, ...) ; +#define dpgMonitor(flag,p) \ +((flag & dpgMonitorFlg) ? (__dpgMonitor p):dpgSUCCESS) +#define dpgTestMonitor(flag) \ +((flag & dpgMonitorFlg) ? dpgERROR:dpgSUCCESS) + +/* Dying routine, outputs to the log and if not stderr, out to stderr - exits + */ +extern void dpgDie(char *format, ...) ; + +#define dpgQDie() \ +do { \ + fprintf(stderr,"Press q to quit.\n") ; \ + if(getchar() == 'q') \ + dpgDie("User requested death\n") ; \ +} while(0) + +/* Verbose bad parameter passed error handler - returns ERROR if addr is + * NULL also does dpgError, returns SUCCESS otherwise + */ +int32 +__dpgBadAddress(char *posStr) ; +#define dpgBadAddress(addr,posStr) \ +((addr == NULL) ? __dpgBadAddress(posStr) : dpgSUCCESS) + + + +/* malloc and calloc routines that print out an error and exit on failure. */ +void * +dpgMalloc(size_t size, char *posStr) ; +void * +dpgRealloc(void *pnt, size_t size, char *posStr) ; +void * +dpgCalloc(size_t noElm, size_t size, char *posStr) ; + + +/* The following are useful dm extensions */ + +#define dmVectorSqrLen(a) \ + (dmSqr((a)[DM_X]) + dmSqr((a)[DM_Y]) + dmSqr((a)[DM_Z])) + +#define dmVectorLen(a) dmVectorLength(a) + +#define dmVectorUnit(a) \ +do { \ + float32 mod ; \ + mod = dmLength3(a) ; \ + (a)[DM_X] /= mod ; \ + (a)[DM_Y] /= mod ; \ + (a)[DM_Z] /= mod ; \ +} while (0) + +#define dmVectorCmp(a,b) memcmp(a,b,sizeof(dmVector)) + + +#endif /* __PGENERAL_H__ */ + diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/PIMAGE.H b/CODE/RP/MUNGA_L4/libDPL/dsys/PIMAGE.H new file mode 100644 index 0000000..885c49c --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/PIMAGE.H @@ -0,0 +1,199 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * File: $RCSfile: pimage.h,v $ + * Revision: $Revision: 1.5 $ + * Date: $Date: 95/04/27 23:01:16 $ + * Author: $Author: bill $ + * RCS Ident: $Id: pimage.h,v 1.5 95/04/27 23:01:16 bill Exp $ + * + * FUNCTION: + * + * + * $Log: pimage.h,v $ + * Revision 1.5 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * Revision 1.4 95/03/21 14:50:22 bill + * Adding the global opacity setter + * + * Revision 1.3 1995/03/10 19:03:01 bill + * Ci for beta release of v2.1 dvs -> dsys change + * + * Revision 1.2 1995/03/10 18:43:29 bill + * Ci for beta release of v2.1 + * + * Revision 1.1 1995/03/06 10:24:34 bill + * Initial revision + * + * Revision 1.4 1994/11/09 17:49:06 bill + * texture type was int32 instead of uint8, read wronge + * + * Revision 1.3 1994/08/30 17:18:09 bill + * Altered -t so it sets the background opacity to a given value (-ve is + * default and preserves inta, rgba and svt opacity values, sets rest to + * 255). + * Also added sgi save -> rgba format. + * + * Revision 1.2 1994/05/13 12:08:51 bill + * File name changing for release. pfile.h->pfile2.h, __pfile.h->__pfile2.h, ptools.h->ptools2.h, __ptools.h->__ptools2.h, filelib.h->filelib2.h, getparam.h->getprm.h. + * + * Revision 1.1 1994/04/15 15:43:18 bill + * new pfile and ptools that cope with spheres lines text and polygons, also uses new FL extension pfl & PF extension dpf + * + * Revision 1.1 1994/02/16 20:30:34 bill + * General edit + * + * + * Copyright (c) 1992 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef __PIMAGE_H__ +#define __PIMAGE_H__ + +#include + +extern char *progname ; + +/**************************************************************************** + * pimage error numbers */ +#define dpiENO_OPEN 0x7001 +#define dpiENO_READ 0x7002 +#define dpiENO_WRITE 0x7003 +#define dpiENO_CLOSE 0x7004 +#define dpiENO_NULL 0x7005 +#define dpiENO_FORM 0x7006 + +/**************************************************************************** + * pimage error numbers */ +#define dpiWARN_PROB 2 + +/**************************************************************************** + * pimage monitor numbers */ +#define dpiMON_POS 0x00010000 +#define dpiMON_PALLET 0x00020000 +#define dpiMON_IMAGE 0x00040000 + +#define VTX_ALLOW_VTX 1 +#define VTX_ALLOW_SVT 2 +#define VTX_ALLOW_OTHER 4 +#define VTX_ALLOW_DIV 3 +#define VTX_ALLOW_ALL 7 + +#define VTX_WIDTH_EIGHT (uint8)1 + +#define VTXcmpIRGB(s1,s2) memcmp(s1,s2,3) +#define VTXcmpIRGBA(s1,s2) memcmp(s1,s2,4) +#define VTXcpyIRGBA(dd,ss) memcpy(dd,ss,sizeof(VTXIRGBA)) + +typedef enum { VTX_GIF_FILE, VTX_BMP_FILE, VTX_SGI_FILE, + VTX_SVT_FILE, VTX_TGA_FILE, VTX_TIF_FILE, + VTX_VTX_FILE, VTX_BSL_FILE, VTX_UNKNOWN_FILE } VTX_IMG_TYPE ; + +typedef enum { VTX_PREC_SINGLE=0, VTX_PREC_DOUBLE=1 } VTXPRECISION ; +/* bsl types */ +#define dpiBSLNOTYPES 9 +typedef enum {dpiBSLTYPE_MONO0=0, dpiBSLTYPE_MONO1=1, dpiBSLTYPE_MONO2=2, + dpiBSLTYPE_MONO3=3, dpiBSLTYPE_MONO4=4, dpiBSLTYPE_MONO5=5, + dpiBSLTYPE_BILINEAR=6, + dpiBSLTYPE_RGB=7, dpiBSLTYPE_RGBA=8 } dpiBSLTYPE ; + +typedef enum VTXcoord { /* used for indexing arrays, identifying axies etc */ + VTXERGBA = 4, VTX_R = 0, VTX_G = 1, VTX_B = 2, VTX_A=3 +} VTXcoord; + +typedef struct +{ + uint8 col[VTXERGBA]; +}VTXIRGBA ; + +typedef struct +{ + float32 col[VTXERGBA]; +}VTXFRGBA ; + +typedef float32 VTXBOXFILTER[3][3] ; + + +struct VTXTEXTURETYPE ; +typedef struct VTXTEXTURETYPE *VTXTEXTUREPTR ; + +struct VTXHEADERTYPE ; +typedef struct VTXHEADERTYPE *VTXHEADERPTR ; + +struct VTXFILETYPE ; +typedef struct VTXFILETYPE *VTXFILEPTR ; + +int32 +VTXgetFile(char *name, VTXFILEPTR *file, int32 allowFile) ; +VTXFILEPTR +VTXopenFile(char *name, int32 allowFile) ; +int32 +VTXgetFileBody(VTXFILEPTR file) ; +int32 +VTXcloseFile(VTXFILEPTR file) ; +int32 +VTXfreeFile(VTXFILEPTR file) ; + +int32 +VTXputFile(char *name, VTXFILEPTR Sfile, VTX_IMG_TYPE fileType) ; +VTXFILEPTR +VTXopenNewFile(char *name, VTX_IMG_TYPE fileType) ; +int32 +VTXputFileBody(VTXFILEPTR Dfile, VTXFILEPTR Sfile) ; + +VTXFILEPTR +VTXcreateFile(char *name) ; +VTXTEXTUREPTR +VTXcreateTexture(void) ; +void +VTXcreateData(VTXTEXTUREPTR texture) ; + +VTXTEXTUREPTR +VTXgetTexture(VTXFILEPTR file) ; +void +VTXgetTextureSize(VTXTEXTUREPTR vtx, int32 *u, int32 *v) ; +uint8 +VTXgetTextureType(VTXTEXTUREPTR vtx) ; +void +VTXgetTextureBgColour(VTXTEXTUREPTR vtx, VTXIRGBA *col) ; +void +VTXsetTextureType(VTXTEXTUREPTR vtx, uint8 type) ; +void +VTXsetTextureBgColour(VTXTEXTUREPTR vtx, VTXIRGBA *col) ; +int32 +VTXaddTexture(VTXFILEPTR file, VTXTEXTUREPTR text) ; + +void +VTXfreeTexture(VTXTEXTUREPTR texture) ; + + +/* returns non-zero on error, zero otherwise. new_quads points to the same or +** a new array of quads. +*/ +int32 +VTXinterpolate(VTXTEXTUREPTR vtx, int32 new_width, int32 new_height) ; +int32 +VTXboxFilter(VTXTEXTUREPTR file, VTXBOXFILTER BoxF) ; +/* if Opacity is < 0 then the alpha is just initialised, else it is set to + * it (range 0 -> 255) + */ +int32 +VTXsetTransparency(VTXTEXTUREPTR vtx, int32 glOpacity, int32 bgOpacity) ; + + +VTXFILEPTR +VTXcreateBSL(char *name, int32 u, int32 v, int32 w) ; +int32 +VTXmergeBSL(VTXFILEPTR Dfp, int32 type, VTXFILEPTR Sfp) ; + +#endif /* __PIMAGE_H__ */ + diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/PTOOL.H b/CODE/RP/MUNGA_L4/libDPL/dsys/PTOOL.H new file mode 100644 index 0000000..49ba459 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/PTOOL.H @@ -0,0 +1,666 @@ +/**************************************************************************** + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: ptool.h,v $ + * Revision : $Revision: 1.18 $ + * Date : $Date: 95/05/16 13:47:00 $ + * Author : $Author: bill $ + * Last Modified : <150595.1203> + * + * Description + * + * Notes + * + * History + * + * $Log: ptool.h,v $ + * Revision 1.18 95/05/16 13:47:00 bill + * Added 1) dos. 2) STRIP_LIST. 3) POINTLIST. 4) biz->bgf + * + * Revision 1.17 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * + **************************************************************************** + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + ****************************************************************************/ + +#ifndef __PTOOL_H__ +#define __PTOOL_H__ + +#ifdef _PF_LOCAL +#include "pfile.h" +#else +#include +#endif + +/*****************************************************************************/ +/* pfile error numbers */ +#define dptENO_NOTIMP 0x8001 +#define dptENO_FORM 0x8002 +#define dptENO_VALUE 0x8003 +#define dptENO_USAGE 0x8004 +#define dptENO_NULL 0x8005 +#define dptENO_INTER 0x8006 +#define dptENO_GRAPH 0x8007 + +/*****************************************************************************/ +/* ptool monitor flags */ +#define dptMON_ALL 0x01000000 + +void +dptGetLibraryVersion(uint8 *M, uint8 *m) ; + +/* returns 0 if the triangle is small, 1 and the normal otherwise +*/ +int32 +dptCalcVTriNorm(dmVector pnt1, dmVector pnt2, dmVector pnt3, + dmVector normal) ; +int32 +dptCalcTriNorm(dpfVERTEXPTR vert1, dpfVERTEXPTR vert2, dpfVERTEXPTR vert3, + dmVector normal) ; +void +dptMatMultVector(dmVector OutVec, dmVector vec, dmMatrix mat) ; + + +/* + * FILE __ptmesh.c + * Creates and saves meshes + */ +#define dpt_OPT_PMESH 0x010000 +#define dpt_OPT_PSTRIP 0x020000 + +dptMESHPTR +dptCreateMesh(int32 hash_size, int32 normals) ; +void +dptFreeMesh(dptMESHPTR mesh) ; +void +dptGetMeshStats(dptMESHPTR mesh) ; +int32 +dptGetMeshNoTriangles(dptMESHPTR mesh) ; +int32 +dptGetMeshNoVertices(dptMESHPTR mesh) ; +int32 +dptGetMeshNoDropTri(dptMESHPTR mesh) ; + +int32 +dptMeshLoadFile(dptMESHPTR mesh, dpfFILEPTR file) ; +int32 +dptMeshLoadObject(dptMESHPTR mesh, dpfOBJECTPTR object) ; +int32 +dptMeshLoadLOD(dptMESHPTR mesh, dpfLODPTR LOD) ; +int32 +dptMeshLoadPatch(dptMESHPTR mesh, dpfPATCHPTR patch) ; +int32 +dptMeshLoadGeometry(dptMESHPTR mesh, dpfGEOMETRYPTR geom) ; +int32 +dptMeshLoadTriangle(dptMESHPTR mesh, dpfVERTEXPTR vert1, dpfVERTEXPTR vert2, + dpfVERTEXPTR vert3) ; + +int32 +dptMeshCalcFaceNormals(dptMESHPTR mesh) ; +void +dptMeshSetVertexPoint(dptMESHPTR mesh, dpfVERTEXPTR vert, dmVector point) ; + +int32 +dptMeshUnloadPatch(dpfPATCHPTR patch, dptMESHPTR mesh, int32 usePmesh) ; +int32 +dptMeshUnloadLOD(dpfLODPTR LOD, dptMESHPTR mesh, int32 usePmesh) ; +int32 +dptMeshUnloadMesh(dptMESHPTR mesh, int32 usePmesh) ; + +/* +** Octize utilitises +** +** must load the file into a mesh using dptMeshLoadFile etc. +** Then use dptOctizeMesh to octize followed by +** dptUnloadOctizedMeshSingle or dptUnloadOctizedMeshMulti +** for single and All file outputs. +*/ +int32 +dptOctizeMesh(dptMESHPTR mesh, dpfIVECTOR div, dmVector Min, dmVector Dif) ; +int32 +dptSpatialiseMesh(dptMESHPTR mesh) ; + +int32 +dptUnloadDividedMeshSingle(dptMESHPTR mesh, int32 octPos, + int32 usePmesh, int32 *noTriangles) ; +int32 +dptUnloadOctizedMeshSingle(dptMESHPTR mesh, dpfIVECTOR pos, + int32 usePmesh, int32 *noTriangles) ; +int32 +dptUnloadDividedMeshAll(dptMESHPTR mesh, int32 usePmesh) ; + + +/* + * File ptbbox + * Gets bounding box of files, objects, patches & geoms + * + * dpfBbox??? must have the MaxVec and MinVec initialized by the user + * before it is first called. + * dpfGetbbox??? Initializes itself, and gets the bounding box and + * difference vector for the structure. + */ +int32 +dptGetBBoxGeometry(dpfGEOMETRYPTR geom, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; +int32 +dptGetBBoxPatch(dpfPATCHPTR patch, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; +int32 +dptGetBBoxLOD(dpfLODPTR LOD, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; +int32 +dptGetBBoxFile(dpfFILEPTR file, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; + +/* + * File ptscale + * scales files, objects, patches & geoms + */ +/* NOTE! :- If dptScaleGeometry or Patch is used it is up to the USER to +** scale all LOD reference points !!! DON'T FORGET. +*/ +int32 +dptScaleGeometry(dpfGEOMETRYPTR geom, int32 normals, dmVector scale) ; +int32 +dptScalePatch(dpfPATCHPTR patch, dmVector scale) ; +int32 +dptScaleObject(dpfOBJECTPTR object, dmVector scale) ; +int32 +dptScaleFile(dpfFILEPTR file, dmVector scale) ; +int32 +dptChangeFileUnit(dpfFILEPTR file, dpfUNIT unit) ; + +int32 +dptScaleNPGeometry(dpfGEOMETRYPTR geom, dmVector scale, dpfIVECTOR NP) ; +int32 +dptScaleNPPatch(dpfPATCHPTR patch, dmVector scale, dpfIVECTOR NP) ; +int32 +dptScaleNPObject(dpfOBJECTPTR object, dmVector scale, dpfIVECTOR NP) ; +int32 +dptScaleNPFile(dpfFILEPTR file, dmVector scale, dpfIVECTOR NP) ; + +/* + * File ptxlate + * translates files, objects, patches & geoms + */ +/* NOTE! :- If dptTranslateGeometry or Patch is used it is up to the USER to +** scale all LOD reference points !!! DON'T FORGET. +*/ +int32 +dptTranslateGeometry(dpfGEOMETRYPTR geom, dmVector trn) ; +int32 +dptTranslatePatch(dpfPATCHPTR patch, dmVector trn) ; +int32 +dptTranslateLOD(dpfLODPTR LOD, dmVector trn) ; +int32 +dptTranslateObject(dpfOBJECTPTR object, dmVector trn) ; +int32 +dptTranslateFile(dpfFILEPTR file, dmVector trn) ; + +/* + * File ptcentre + * Centre's given file + */ +int32 +dptCentreFile(dpfFILEPTR file) ; + +/* + * File ptcoales + * coalesces short patches into longer ones + * reduces file size, execution time + */ +int32 +dptCoalesceLOD(dpfLODPTR LOD) ; +int32 +dptCoalesceObject(dpfOBJECTPTR obj, int32 coalesceLODs, int32 coalesceGEOMs) ; +int32 +dptCoalesceFile(dpfFILEPTR file, int32 coalesceLODs, int32 coalesceGEOMs) ; + +/* + * File pttextur + * Places planar texture co-ordinates on given file + */ +#define dpt_TEXTURE_PLANE 0 +#define dpt_TEXTURE_AXIAL 1 +#define dpt_TEXTURE_CYLINDER 2 + +typedef struct +{ + int32 method ; + int32 noWraps ; + int32 gotSize, gotRef ; + int32 Cswap ; + int32 Uco, Vco ; + int32 axes[3] ; + float32 Usize, Vsize ; + float32 Cangle, Coffset ; + dmVector reference ; + + int32 distort ; +} dptTEXTURE, *dptTEXTUREPTR ; + + +void +dptCorrectTriangleTexture(dptMESHPTR mesh, dpfPATCHPTR patch, + dpfVERTEXPTR vert1, dpfVERTEXPTR vert2, + dpfVERTEXPTR vert3, int32 noWraps, int32 *distort) ; +dpfGEOMETRYPTR +dptCorrectGeometryTexture(dpfGEOMETRYPTR geom, int32 noWraps, int32 *distort) ; + +int32 +dptTextureInit(dptTEXTUREPTR txt, int32 method, int32 NoWraps, int32 gotSize, + int32 gotRef, dmVector MinVec, dmVector differ, + float32 Usize, float32 Vsize, dmVector reference, int32 Uco, + int32 Vco, int32 *axes, int32 Cswap, float32 Cangle) ; +int32 +dptTextureFileInit(dpfFILEPTR file, dptTEXTUREPTR txt, int32 method, + int32 NoWraps, int32 gotSize, int32 gotRef, float32 Usize, + float32 Vsize, dmVector reference, int32 Uco, int32 Vco, + int32 *axes, int32 Cswap, float32 Cangle) ; +dpfGEOMETRYPTR +dptTextureGeometry(dpfGEOMETRYPTR geom, dptTEXTUREPTR txt) ; +int32 +dptTexturePatch(dpfPATCHPTR ptch, dptTEXTUREPTR txt) ; +int32 +dptTextureLOD(dpfLODPTR LOD, dptTEXTUREPTR txt) ; +int32 +dptTextureFile(dpfFILEPTR file, dptTEXTUREPTR txt) ; + +/* + * File __ptrot.c + * rotates files, objects, patches & geoms + * Order the rotations are performed are the same as MAZ + * ie Z, X then Y + */ +/* Matrix point transformers. + * Transforms (Xforms) files using a 4x4 homogeneous matrix, + * Note that translations are performed, hence the use of dmPntXformMat + * + * Used directly by the dptRotate functions. + */ +#define dptVectorXformMat(OutVec,vec,mat) dmPointXformMat(OutVec,vec,mat) +extern void +(dptVectorXformMat)(dmVector OutVec, dmVector vec, dmMatrix mat) ; +int32 +dptXformGeometry(dpfGEOMETRYPTR geom, int32 Normals, dmMatrix rotate) ; +int32 +dptXformPatch(dpfPATCHPTR patch, dmMatrix rotate) ; +int32 +dptXformObject(dpfOBJECTPTR object, dmMatrix rotate) ; +int32 +dptXformFile(dpfFILEPTR file, dmMatrix rotate) ; + +/***************************************************************************** +* NOTE! :- If dptRotateGeometry or Patch is used it is up to the USER to * +* scale all LOD reference points !!! DON'T FORGET. * +*****************************************************************************/ +/* + * Rotation functions use the Xform functions directly, so error messages + * will be dptXform's. + */ +extern void +dptRotateSetup(dmMatrix outMat, dmVector inRot) ; +#define dptRotateGeometry(geom,Normals,rotate) \ + dptXformGeometry(geom,Normals,rotate) +#define dptRotatePatch(patch,rotate) \ + dptXformPatch(patch,rotate) +#define dptRotateObject(object,rotate) \ + dptXformObject(object,rotate) +#define dptRotateFile(file,rotate) \ + dptXformFile(file,rotate) + +/* + * File __pticon.h + * Centre's and scales a given file to produce an icon + */ + +#define dpt_ICONSIZE 1.0 + +int32 +dptIconizeFile(dpfFILEPTR file, float32 size) ; + +/* + * File __ptrond.h + * Rounds given file to the given number of sig. figures + * if the given number is <= 0 then default is used. + */ + +#define dpt_DEFAULTSIGFIG 6 +#define dpt_DEFAULTDPS 4 +#define dpt_DEFAULTWRAP 1 + +int32 +dptRoundFvertex(dpfFILEPTR file, int32 SigFig, int32 dps) ; + +int32 +dptFuzzyJoinFile(dpfFILEPTR file, float32 Dist, int32 WarnDis) ; + +int32 +dptJoinMeshTriangles(dptMESHPTR mesh, float32 distTol, float32 angTol, + int32 *joinCount, int32 Verbose) ; +int32 +dptJoinPatchTriangles(dpfPATCHPTR patch, int32 hash_size, int32 usePmesh, + float32 distTol, float32 angTol, int32 *joinCount, + int32 Verbose) ; + + +typedef struct +{ + /* Check setup parameters */ + int32 dps ; /* decimal places to check to */ + int32 NoWraps ; /* maximum no. of texture wraps */ + int32 autoFix ; /* autoFix on if non-zero */ + int32 disableText ; /* don't fix textures if non-zero */ + int32 splitGeom ; /* if non-zero the split triangle */ + /* rather than distort texture */ + int32 Verbose ; /* run with verbose */ + + /* Things calculated on setup */ + float32 MulFac ; /* Normal modulus accuracy mul factor*/ + + /* No. things found empty */ + int32 emptyLod ; + int32 emptyPatch ; + int32 emptyGeom ; + + /* LOD error report */ + int32 badDummy ; /* got a dummy with other lods */ + int32 badOrder ; /* lods in wrong order - flag only */ + int32 distSame ; /* switch-in == out count */ + int32 distSwap ; /* switch-in > out count */ + int32 overLap ; /* lod switch in overlaps others out */ + + /* geometry bad report */ + int32 badPmeshT ; /* No of bad pmesh triangle connects */ + int32 badSphere ; /* No of spheres with bad radii */ + int32 badLine ; /* No of 0 length lines */ + int32 badPoint ; /* No. points with nans, inc. lod ref*/ + int32 badNorm ; /* No. normals with bad mod */ + int32 badCook ; /* No. rgb's out of range */ + int32 badText ; /* no. nan | text co-ords out of wrap*/ + float32 maxText ; /* the maximum range of a texture */ + + /* boundary report */ + int32 badBBox ; + int32 badBSphere ; + int32 badBPmesh ; + + int32 isBad ; /* Summary flag - if true then error found */ + + /* auto-fix output */ + int32 dropLod ; /* No dropped lods as empty */ + int32 dropPatch ; /* No dropped patches as empty */ + int32 dropGeom ; /* No dropped geometries as empty */ + int32 dropTri ; /* No tri's dropped because duff */ + /* duff cos nan's or pmesh connect */ + int32 dropLine ; /* No lines's dropped cos len = 0 */ + int32 dropSphere ; /* No tri's dropped cos radius = 0 */ + + int32 dropBPart ; /* No B box, sphere and pmeshes drop */ + int32 dropBound ; /* No bounds dropped */ + + int32 normDistort ; /* No normal 0 or nan mods */ + int32 textDistort ; /* No texture distorts (0 if split) */ + int32 newTriCnt ; /* No new tris created from splitting*/ + + int32 isAwful ; /* Summary flag - if true then Distortion */ + +} dptCHECK, *dptCHECKPTR ; + + +int32 +dptCheckLODs(dpfFILEPTR file, dptCHECKPTR check) ; +int32 +dptCheckPatch(dpfPATCHPTR patch, dptCHECKPTR check) ; +void +dptCheckSetup(dptCHECKPTR check, int32 dps, int32 NoWraps, int32 autoFix, + int32 disableText, int32 verbose) ; +int32 +dptCheckFile(dpfFILEPTR file, dptCHECKPTR check, int32 dps, int32 NoWraps, + int32 autoFix, int32 disableText, int32 verbose) ; + +int32 +dptNormalizeMesh(dptMESHPTR mesh, float32 Tolerence, int32 Verbose) ; +int32 +dptNormalPatch(dpfPATCHPTR patch, int32 hash_size, float32 Tolerence, + int32 usePmesh, int32 *DropTri, int32 Verbose) ; + + +/* reduce a patch + * NOTE :- + * Method is a bit field using the following #defines + * verbose is a bit field 0x02=Prompt, 0x04=GL, non-zero=% + */ +#define dptRDC_DUPS 0x0001 +#define dptRDC_DUPD 0x0002 +#define dptRDC_SQUR 0x0004 +#define dptRDC_180 0x0008 +#define dptRDC_360 0x0010 + +int32 +dptReducePatch(dpfPATCHPTR patch, int32 hash_size, float32 Cook_Tol, + float32 Norm_Tol, float32 Tri_Tol, float32 Edge_Tol, + int32 *DropTri, int32 NoIter, int32 usePmesh, int32 Method, + int32 Verbose, float32 WarmInc) ; + +/* +** Reduces the number of faces in a cylinder. +** Tolerences :- +** MaxRadiusTol +** RatioTol - The maximum ratio between the largest and +** smallest end edges. +** NormTol - How correctly shaped the pairs are. +** MaxNoFaces - Max faces in a cylinder -> 2* no of trian. +** MinNoFaces - Min faces in a cylinder +** FinNoFaces - Final no faces. +*/ + + +/* The cylinder structure + * The following rules must be adhered to if blast is to correctly re-create + * them. + * 1) there are 2 different types of cylinders, flat (disks and ring) and + * non-flat (cones and tubes). + * 2) flat cylinders must have a length of 0.0, the larger ring must be + * stored in slot 0 and inner ring or centre in slot 1. PlnNorm and + * CenLine must be the same and point in the direction it is facing. + * Flipping the centLine direction and facing bit in flags (bit 1) + * can be used to change its orientation + * 3) Non-flat tubes have a non-zero length, the CentLine is the direct + * needed to go for the centre point of ring in slot 0 to the centre + * of ring in slot 1. Bit 1 of flags indicates where the cylinder is + * in or outwardly facing, set if in. + * 4) flat disk cylinders are automatically converted to cylinder ends if + * an apropriate cylinder is found. + * 5) Bit 2 of flags gives the orientation of the cylinder in the pipe, if + * set then it is facing the other way. + * 6) Bit 3-5 of flags indicates the part got of a cylinder + * 7) the plane normals must point outwards of a tube if inwardly facing, + * or inwardly if inwardly facing. With a ring, the large radius ring must + * point in the direction the ring faces and it will join that way, the + * smaller must point the oposite way. + */ +#define dptBLAST_FACE 0x0001 +#define dptBLAST_DIR 0x0002 +#define dptBLAST_BODY 0x0004 +#define dptBLAST_END1 0x0008 +#define dptBLAST_END2 0x0010 +#define dptBLAST_DISK 0x0020 +#define dptBLAST_CONE 0x0040 +#define dptBLAST_RING 0x0080 +#define dptBLAST_TUBE 0x0100 + +typedef struct dptCYLINDER_str +{ + int32 noFaces ; + int32 flags ; + float32 Length ; + dmVector CentLine ; + + float32 Radius[2] ; + dmVector Centre[2] ; + dmVector PlnNorm[2] ; + + struct dptCYLINDER_str *next ; + +} dptCYLINDER, *dptCYLINDER_ptr ; + + +typedef struct dptCYLLIST_str +{ + int32 flags[2] ; + int32 NoVert ; + float32 maxRadius ; + float32 minRadius ; + float32 Radius[2] ; + dmVector Centre[2] ; + dmVector PlnNorm[2] ; + dptCYLINDER_ptr EndCyl[2] ; + + struct dptCYLLIST_str *next ; +} dptCYLLIST, *dptCYLLIST_ptr ; + + +typedef struct +{ + dptMESHPTR curMesh ; + dpfPATCHPTR curPatch ; + + int32 BBlast ; + float32 BMaxSideTol ; + float32 BRatioTol ; + float32 BEdgeTol ; + float32 BNormTol ; + + int32 CBlast ; + int32 CStats ; + int32 CMinFcs ; + int32 CMaxFcs ; + int32 CNoRanges ; + float32 *CMinRad ; + float32 *CMaxRad ; + int32 *CFinFcs ; + + /* to be filled */ + int32 KeepParts ; + float32 CRatioTol ; + float32 CNormTol ; + float32 CCentDif ; + float32 CRadDif ; + float32 CTurnTol ; + + /* to be left alone */ + float32 TurnTol ; + float32 cNorm0Tol ; + float32 cNorm90Tol ; + dptCYLLIST_ptr CList_hd, CList_tl ; + dpfVERTEXPTR *TopVerts, *BotVerts ; + +} dptBLAST, *dptBLASTPTR ; + + +int32 +dptBlastPatch(dpfPATCHPTR patch, int32 hash_size, dptBLASTPTR blast, + int32 usePmesh, int32 *DropTri, int32 Verbose) ; + + +int32 +dptTinyKillMesh(dptMESHPTR mesh,float32 Angl_Tol, + int32 Verbose, int32 *SmallTri) ; +int32 +dptTinyKillPatch(dpfPATCHPTR patch, int32 hash_size, + float32 Angl_Tol, int32 usePmesh, + int32 *DropTri, int32 Verbose) ; + + +/* +** ptflip - module to flip the trangle direction face +*/ +int32 +dptFlipAllGeometry(dpfGEOMETRYPTR geom, int32 flipNormals) ; +int32 +dptFlipAllPatch(dpfPATCHPTR patch, int32 flipNormals) ; +int32 +dptFlipAllObject(dpfOBJECTPTR object, int32 flipNormals) ; +int32 +dptFlipAllFile(dpfFILEPTR file, int32 flipNormals) ; + +int32 +dptFlipRightMesh(dptMESHPTR mesh, int32 *flipCount, int32 Verbose) ; +int32 +dptFlipRightPatch(dpfPATCHPTR patch, int32 hash_size, int32 usePmesh, + int32 *DropTri, int32 *flipCount, int32 Verbose) ; + +/* +** hedgehog a given file +*/ +int32 +dptCreateVisualMaterials(dpfFILEPTR file) ; +int32 +dptAddVertexNormalVisual(dpfFILEPTR file, char *matLib, float32 Pscale, + float32 Bscale) ; +int32 +dptAddBoundBoxVisual(dpfFILEPTR file, char *matLib) ; +int32 +dptAddBoundSphereVisual(dpfFILEPTR file, char *matLib, + int32 udice, int32 vdice) ; +int32 +dptAddBoundPmeshVisual(dpfFILEPTR file, char *matLib) ; + +int32 +dptRmvVertexNormalVisual(dpfFILEPTR file) ; +int32 +dptRmvBoundBoxVisual(dpfFILEPTR file) ; +int32 +dptRmvBoundSphereVisual(dpfFILEPTR file) ; +int32 +dptRmvBoundPmeshVisual(dpfFILEPTR file) ; + +int32 +dptCookGeometry(dpfGEOMETRYPTR geom, dpfRGBA col) ; +int32 +dptCookFile(dpfFILEPTR file) ; + +/* Boundary stuff */ +int32 +dptCalcMinBBox(dpfFILEPTR file, int32 res, dpfBOUNDPTR bound) ; +int32 +dptCreateBoundary(dpfFILEPTR file, int32 minBBoxRes, int32 doHierarchy, + int32 keepPmesh, int32 hashSize) ; + +/* Tessellate a polygon, allowing for concavity. + * + * The pmesh must already contain all the required vertices, noPnts is + * a count of the number of points in the polygon (doesnt have to be the + * number of vertices), and vrtlst is an int array of size noPnts giving + * the pmesh vert numbr for the nth point. + * Assumes that the polygon is closed, so vrtlst[0] != vrtLst[noPnts-1] + * should be true. + */ +int32 +dptPolyTessellate(dpfGEOMETRYPTR pmesh, int32 noPnts, int32 *vrtLst) ; + +/* graphics routines */ +int32 +dptInitGraphics(char *name) ; +int32 +dptInitView(dmVector boxMin, dmVector boxDif) ; +int32 +dptEndView(void) ; + +#endif /* __PTOOL_H__ */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/VDIFILE.H b/CODE/RP/MUNGA_L4/libDPL/dsys/VDIFILE.H new file mode 100644 index 0000000..2cd11f9 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/VDIFILE.H @@ -0,0 +1,229 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: vdifile.h,v $ +-- Revision : $Revision: 1.4 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __VDIFILE_H__ + +#define __VDIFILE_H__ + +#ifdef _PF_LOCAL +#include "pfile.h" +#else +#include +#endif + +/* vdifile error numbers */ + + +#define dvf_OBJECT_TYPE 0x01 /* if flag bit set then obj in scene */ +#define dvf_PARENT_TYPE 0x02 /* if flag bit set then obj is parent */ +#define dvf_OBJECT_LIB 0x04 /* if flag bit set obj is a library */ + +#define dvf_TABSIZE 4 + +typedef enum { dvfLIGHT_AMBIENT, dvfLIGHT_DIRECT } dvfLIGHTTYPE ; +typedef enum { dvfSTATE_ON=0, dvfSTATE_OFF } dvfSTATE ; + +extern char *progname ; + +typedef struct dvfMFILETYPE +{ + char *name ; + dpfFILEPTR file ; + struct dvfMFILETYPE *next ; +} dvfMFILE, *dvfMFILEPTR ; + +typedef struct +{ + /* lighting stuff */ + dvfLIGHTTYPE lightType ; + dvfSTATE lightState ; + dpfRGBA colour ; +} dvfLIGHT, *dvfLIGHTPTR ; + +typedef struct dvfOBJECTTYPE +{ + /* Object name, library file name, template name and comment */ + char *name ; + char *libName ; + char *tempName ; + char *comment ; + + /* position in the world relative to parent */ + dmPoint point ; + dmScale scale ; + dmEuler orien ; + + /* visual info */ + char *geomName ; + dpfFILEPTR geometry ; + dvfSTATE geomState ; /* if ON then visible else invisble */ + + /* Light setting of the object */ + dvfLIGHTPTR light ; + + /* User data - do what you want with these. + * Guaranteed to be initialised to 0s and NULLs + */ + int32 userFlags ; + void *userData ; + int32 userFlags2 ; + void *userData2 ; + + /* internal flags */ + int32 flags ; + struct dvfOBJECTTYPE *child_hd, *child_tl ; + struct dvfOBJECTTYPE *next, *objParent ; + struct dvfFILETYPE *fileParent ; +} dvfOBJECT, *dvfOBJECTPTR ; + + +typedef struct dvfFILETYPE +{ + char *fileName, *sceneName ; + char *basePath, *extPath ; + FILE *fp ; + int32 useMid, type ; + int32 disLight ; + int32 tab ; + + int32 userFlags ; + void *userData ; + + dvfOBJECTPTR defs_hd, defs_tl ; + dvfOBJECTPTR scene_hd, scene_tl ; + dvfMFILEPTR mfile_hd ; + dpfFILETYPE outType ; +} dvfFILE, *dvfFILEPTR ; + + +/* Copies sname into dname, correcting any bad characters to '_' + * + * Note:- if the name starts with a non alpha character (inc numeric), + * it is illegal so a pre-pending 'A' is added. For this reason + * dname must be 1 character bigger than sname. + * + * dname can been sname! (if so ensure sname is 1 character bigger) + */ +void +dvfCorrectName(char *dname, char *sname) ; + +/* File setup and saving ****************************************************/ +dvfFILEPTR +dvfCreateFile(void) ; +int32 +dvfSaveFile(dvfFILEPTR file) ; +int32 +dvfFreeFile(dvfFILEPTR file) ; + + +int32 +dvfSetFileName(dvfFILEPTR file, char *name) ; +/* if type is non-zero then the file is a library and saved with the + * extension of .vdl + */ +#define dvfSetFileType(f,t) ((f)->type = t) +#define dvfDisableDefaultLighting(f) ((f)->disLight = 1) +int32 +dvfSetFilePaths(dvfFILEPTR file, dpfFILETYPE outType, char *basePath, + int32 useMid, char *extPath) ; +#define dvfGetFileSceneName(f) ((f)->sceneName) +#define dvfGetFileFileName(f) ((f)->fileName) + +/* Material File calls ******************************************************/ +dvfMFILEPTR +dvfCreateMaterialFile(void) ; +int32 +dvfAddMaterialFile(dvfFILEPTR file, dvfMFILEPTR mfile) ; +int32 +dvfSetMaterialFileName(dvfMFILEPTR mfile, char *name) ; + +/* OBJECT Functions *********************************************************/ +dvfOBJECTPTR +dvfCreateObject(void) ; +void +dvfUnlinkObject(dvfOBJECTPTR object) ; + +/* adding object to the hierarchy */ +int32 +dvfAddDefinitionObject(dvfFILEPTR file, dvfOBJECTPTR object) ; +int32 +dvfAddSceneObject(dvfFILEPTR file, dvfOBJECTPTR object) ; +int32 +dvfAddObjectObject(dvfOBJECTPTR parent, dvfOBJECTPTR object) ; + +/* setting object information */ +int32 +dvfSetObjectName(dvfOBJECTPTR object, char *name) ; +int32 +dvfSetObjectGeometryName(dvfOBJECTPTR object, char *name) ; +#define dvfSetObjectGeometryState(o,s) ((o)->geomState = s) +int32 +dvfSetObjectGeometryFile(dvfOBJECTPTR object, dpfFILEPTR file) ; +int32 +dvfSetObjectLight(dvfOBJECTPTR object, dvfLIGHTPTR light) ; +#define dvfSetObjectPoint(o,p) dmVectorCopy((o)->point,p) +#define dvfSetObjectScale(o,s) dmVectorCopy((o)->scale,s) +#define dvfSetObjectOrien(o,r) dmVectorCopy((o)->orien,r) + +/* Getting information back again */ +#define dvfGetObjectName(o) ((o)->name) +#define dvfGetObjectObjectParent(o) ((o)->objParent) +#define dvfGetObjectFileParent(o) ((o)->fileParent) +#define dvfGetObjectGeometryName(o) ((o)->geomName) +#define dvfGetObjectGeometryFile(o) ((o)->geometry) +#define dvfGetObjectLight(o) ((o)->light) +#define dvfGetObjectPoint(o,p) dmVectorCopy(p,(o)->point) +#define dvfGetObjectScale(o,s) dmVectorCopy(s,(o)->scale) +#define dvfGetObjectOrien(o,r) dmVectorCopy(r,(o)->orien) +#define dvfGetObjectGeometryState(o) ((o)->geomState) + +/* The next makes it a UseLibrary if the file name is not NULL or + * a defineLibrary if NULL + */ +int32 +dvfSetObjectLibrary(dvfOBJECTPTR object, char *filename) ; +/* Sets the library name and object name the use as a Template */ +int32 +dvfSetObjectTemplate(dvfOBJECTPTR object, char *library, char *oname) ; +int32 +dvfSaveFreeGeometry(dvfFILEPTR file, dvfOBJECTPTR object) ; +int32 +dvfFreeObject(dvfOBJECTPTR object) ; +/* Dont use the following as it doesnt up-date pointers */ +int32 +dvfFreeObjectList(dvfOBJECTPTR object) ; + +/* Light Functions **********************************************************/ +dvfLIGHTPTR +dvfCreateLight(void) ; + +#define dvfGetLightType(l) ((l)->lightType) +#define dvfGetLightState(l) ((l)->lightState) +#define dvfGetLightColour(l,c) (dpfRGBCpy(c,(l)->light)) + +#define dvfSetLightType(l,t) ((l)->lightType = t) +#define dvfSetLightState(l,s) ((l)->lightState = s) +#define dvfSetLightColour(l,c) (dpfRGBACpy((l)->colour,c)) + +#endif /* __VDIFILE_H__ */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/__PFILE.H b/CODE/RP/MUNGA_L4/libDPL/dsys/__PFILE.H new file mode 100644 index 0000000..45d8905 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/__PFILE.H @@ -0,0 +1,603 @@ +/**************************************************************************** + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: __pfile.h,v $ + * Revision : $Revision: 1.15 $ + * Date : $Date: 95/05/16 13:46:17 $ + * Author : $Author: bill $ + * Last Modified : <120595.1125> + * + * Description + * + * Notes + * + * History + * + * $Log: __pfile.h,v $ + * Revision 1.15 95/05/16 13:46:17 bill + * Added 1) dos. 2) STRIP_LIST. 3) POINTLIST. 4) biz->bgf + * + * Revision 1.14 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * + **************************************************************************** + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + ****************************************************************************/ + +#ifndef ____PFILE_H__ +#define ____PFILE_H__ + +#include + +#ifdef _PF_LOCAL +#include "filelib.h" +#include "pfile.h" +#else +#include +#include +#endif + + +/* Constant ID strings */ +#define dpfBIZIDstrLen 31 +#define dpfBIZIDstr "biz v1.0 (c) DIVISION Ltd 1992" +#define dpfVIZIDstr "/* viz v1.0 (c) DIVISION Ltd 1992 */\n" + +#define dpfB2ZIDstrLen 8 +#define dpfB2ZIDstr "DIV-BIZ2" +#define dpfV2ZIDstrLen 8 +#define dpfV2ZIDstr "DIV-VIZ2" +#define dpfBMFIDstrLen 8 +#define dpfBMFIDstr "DIV-BMF2" +#define dpfVMFIDstrLen 8 +#define dpfVMFIDstr "DIV-VMF2" + +/* ver change */ +/* 2.00 Initial pfile version */ +/* 2.01 Replairs to pmesh tag and section length tests */ +/* 2.02 pmesh extended to have polygons of upto 255 faces */ +/* 2.03 boundary information added */ +/* 2.04 Line definition change, can now be textured cooked & normalized */ +/* 2.05 Introduction of material libraries */ +/* 2.06 pgeneral way of doing things */ +/* 2.07 STRIP_LISTs and POINTLISTs added to format */ +#define dpf_LIBRARY_MAJOR_VER 2 +#define dpf_LIBRARY_MINOR_VER 07 + +#define dpfSTDINName "Std In" +#define dpfSTDOUTName "Std Out" + +/* new biz v2 max depth constant */ +#define dpf_MAX_DEPTH 10 + +/* load in basic types, struct names and procedure heading which +** can be externally called. +*/ + +#define dpfVBLKSIZE 1024 + +extern uint8 dpfVERTFLAG ; +extern uint8 dpfVERTSIZE ; +extern uint8 dpfVERTNORM ; +extern uint8 dpfVERTRGBA ; +extern uint8 dpfVERTTEXT ; +extern uint8 dpfVERTOVER ; + +/* Now define all the internal structures */ +typedef int32 dpfTOKEN ; + +/* The following is for the new wizzy v1.0 -> v2.0 texture converter */ +typedef struct dpfVISTEXTURETYPE +{ + char *visName ; + char *F_textName, *F_textMap ; + char *B_textName, *B_textMap ; + + struct dpfVISTEXTURETYPE *next ; +} dpfVISTEXTURE ; + + +typedef struct dpfSTRINGTYPE +{ + int32 length ; + uint8 *string ; +} dpfSTRING ; + +typedef struct dpfTEXTURETYPE +{ + char *textName ; + char *fileName ; + + dpfMINIFY minify ; + dpfMAGNIFY magnify ; + dpfALPHA alpha ; + dpfWRAP wrap_U, wrap_V ; + dpfDETAIL detail ; + char *detailName; + uint8 bitslice ; + dpfSTRINGPTR special ; + int32 dataLength ; + struct dpfFILE_TYPE *file; + struct dpfTEXTURETYPE *next ; + +} dpfTEXTURE ; + + +typedef struct dpfRAMPTYPE +{ + char *name ; + dpfRGBA data[2] ; + + dpfSTRINGPTR special ; + int32 dataLength ; + + struct dpfFILE_TYPE *file; + struct dpfRAMPTYPE *next ; +} dpfRAMP ; + +typedef struct dpfMATERIALTYPE +{ + char *name ; + + dpfMATTXTTYPE textureType ; + char *textureName ; + char *rampName ; + dpfRGBA ambient, + diffuse, + specular, + emissive, + opacity ; + dpfSTRINGPTR special ; + int32 dataLength ; + struct dpfFILE_TYPE *file; + struct dpfMATERIALTYPE *next ; + +} dpfMATERIAL ; + + +typedef struct dpfSURFACETYPE +{ + char *name ; + dpfMATTYPE F_Material ; + dpfMATTYPE B_Material ; + char *F_MatName ; + char *B_MatName ; + + dpfPLANE plane ; + dpfFACET facet ; + int32 decal ; + dpfDRAWMODE drawMode ; + uint8 width ; + uint8 vertex ; + dpfLOCK lock ; + dpfSTRINGPTR special ; + +} dpfSURFACE ; + +typedef struct dpfVERTEXTYPE { + struct dpfVERTEXTYPE *next ; + union { + struct dpfGEOMETRYTYPE *geom ; + struct dptTRILISTTYPE *triList ; + } ptr ; + uint8 vertex ; + uint8 flag ; + unsigned short count ; + float32 data[3] ; +} dpfVERTEX ; + +typedef struct dpfVERTBLK { + struct dpfVERTBLK *next ; + dpfVERTEX vert[dpfVBLKSIZE] ; +} dpfVERTBLK, *dpfVERTBLKPTR ; + + +/************************************************************* +* The Following are type defs for the ptmesh utility * +*************************************************************/ + +typedef struct dptTRILISTTYPE +{ + struct dptTRIANGLETYPE *triangle ; + struct dptTRILISTTYPE *next ; +} dptTRILIST, *dptTRILISTPTR ; + +typedef struct dptCONNECTTYPE +{ + struct dptTRIANGLETYPE *connection ; + int32 p1 ; + struct dptCONNECTTYPE *next ; +} dptCONNECT, *dptCONNECTPTR ; + +typedef struct dptTRIANGLETYPE +{ + dpfPATCHPTR patch ; + dpfVERTEXPTR points[3] ; + dptCONNECTPTR connections ; + dmVector normal ; + /* Beware of using the octPos flag. it is used in the flipper, octize, + ** spatial divide and the unloading of meshes + */ + int32 octPos ; + struct dptTRIANGLETYPE *next, *prev ; +} dptTRIANGLE ; + +typedef struct +{ + dpfPATCHPTR patch ; + dptTRIANGLEPTR LTrian, RTrian ; + int32 LVertNo, RVertNo ; + int32 ROrient, LOrient ; + int32 noVerts ; + int32 octPos ; +} dptSAVEBLOCK, *dptSAVEBLOCKPTR ; + +typedef struct dptMESHTYPE { + dpfVERTEXPTR *hash_tbl ; + dptTRIANGLEPTR trian_hd, trian_tl ; + dpfGEOMETRYPTR geom_hd, geom_tl ; + duBlkCtrl conBC, trilBC, trisBC ; + int32 hash_size, normals ; + int32 No_trian, No_verts ; + int32 noGroups ; + int32 DropTri ; +} dptMESH ; + + +/************************************************************/ + + +typedef struct dpfCLISTTYPE +{ + int32 pcount ; + int32 fcount ; + int32 DataLength ; + struct dpfGEOMETRYTYPE *geom; + struct dpfCLISTTYPE *next ; + int32 *faces ; +} dpfCLIST ; + +typedef struct dpfSLISTTYPE +{ + int32 pcount ; + int32 vcount ; + int32 DataLength ; + struct dpfGEOMETRYTYPE *geom; + struct dpfSLISTTYPE *next ; + int32 *faces ; +} dpfSLIST ; + +/* 4th float of point (point[dpf_U]) is used as radius */ +typedef struct dpfSPHERENODETYPE +{ + dmVector point ; + float32 radius ; + struct dpfGEOMETRYTYPE *geom; + struct dpfSPHERENODETYPE *next ; + int32 *block ; +} dpfSPHERENODE ; + +typedef struct dpfTEXTNODETYPE +{ + dmVector point ; + char *string ; + struct dpfGEOMETRYTYPE *geom; + struct dpfTEXTNODETYPE *next ; + int32 *block ; +} dpfTEXTNODE ; + +typedef struct dpfSTRIPTYPE { + dpfVERTEXPTR point_hd, point_tl ; + union + { + uint8 thickness ; + float32 size ; + } data ; + int32 noVertex, pDataLength ; +} dpfSTRIP, *dpfSTRIPPTR ; + +typedef struct dpfPMESHTYPE { + dpfVERTEXPTR point_hd, point_tl ; + dpfCLISTPTR cList_hd, cList_tl ; + dpfSLISTPTR sList_hd, sList_tl ; + int32 noVertex, pDataLength ; + int32 noCList, clDataLength ; + int32 noSList, slDataLength ; +} dpfPMESH, *dpfPMESHPTR ; + +typedef struct dpfSPHERETYPE { + uint16 dice_u, dice_v ; + dpfSPHERENODEPTR sphere_hd, sphere_tl ; + int32 noSphereNode, sDataLength ; +} dpfSPHERE, *dpfSPHEREPTR ; + +typedef struct dpfLETTEXTTYPE { + dpfFONT font ; + dmVector scale, orientation ; + dpfTEXTNODEPTR text_hd, text_tl ; + int32 noTextNode, tDataLength ; +} dpfLETTEXT, *dpfLETTEXTPTR ; + +typedef struct dpfGEOMETRYTYPE +{ + int32 geomType ; + union + { + dpfSTRIPPTR strip ; + dpfPMESHPTR pmesh ; + dpfSPHEREPTR sphere ; + dpfLETTEXTPTR text ; + } u_data ; + int32 dataLength ; + struct dpfPATCHTYPE *patch; + struct dpfGEOMETRYTYPE *next ; +} dpfGEOMETRY ; + + +typedef struct dpfPATCHTYPE { + dpfSURFACE surface; + dpfGEOMETRYPTR geom_hd; + dpfGEOMETRYPTR geom_tl; + int32 dataLength ; + struct dpfLODTYPE *LOD ; + struct dpfPATCHTYPE *next; +} dpfPATCH ; + +typedef struct dpfLODTYPE +{ + char *name ; + float32 inDist, outDist ; + dpfTRANSITION transition ; + int32 referenceFlag ; + dmVector reference ; + dpfPATCHPTR patch_hd; + dpfPATCHPTR patch_tl; + dpfSTRINGPTR special ; + int32 dataLength ; + struct dpfOBJECTTYPE *object; + struct dpfLODTYPE *next ; +} dpfLOD ; + +typedef struct dpfOBJECTTYPE { + dpfSURFACE surface; + dpfLODPTR LOD_hd; + dpfLODPTR LOD_tl; + int32 dataLength ; + struct dpfOBJECTTYPE *next; + struct dpfFILE_TYPE *file; +} dpfOBJECT ; + +typedef struct dpfHEADERTYPE +{ + uint8 verMajor, verMinor; + uint8 day, month, year ; + uint8 hours, minutes ; + uint8 headerLoaded ; + float32 scale ; + dpfPRECISION precision ; + dpfSTRINGPTR comment ; + dpfUNIT unit ; + dpfSTRINGPTR special ; + int32 dataLength ; + dpfFILEFORMAT type; +} dpfHEADER ; + + +typedef struct dpfBOUNDTYPE +{ + char *objectName ; + char *LODName ; + dpfAUTO Auto ; + + uint8 gotBSphere ; + dmVector sphPoint ; + float32 sphRadius ; + + uint8 gotBBox ; + dmVector boxMax, boxMin ; + dmVector boxOrien ; + + dpfGEOMETRYPTR pmesh ; + + dpfSTRINGPTR special ; + int32 dataLength ; + + dpfBOUNDPTR child_hd ; + dpfBOUNDPTR child_tl ; + + dpfBOUNDPTR next ; + dpfBOUNDPTR parent ; + dpfFILEPTR file ; +} dpfBOUND ; + + +/* dpfFILETYPE => dpfFILE_TYPE to stop conflict */ +typedef struct dpfFILE_TYPE +{ + dpfHEADER header ; + + dpfFILETYPE type; + dpfFILEMODE mode; + char *fileName ; + dflFILEPTR fl ; + int32 lineNo, newMaterialCount ; + int32 dataLength, blockDepth, blockEnd[dpf_MAX_DEPTH] ; + + dpfTEXTUREPTR texture_hd ; + dpfTEXTUREPTR texture_tl ; + dpfMATERIALPTR material_hd ; + dpfMATERIALPTR material_tl ; + dpfRAMPPTR ramp_hd ; + dpfRAMPPTR ramp_tl ; + + dpfBOUNDPTR bound ; + + dpfOBJECTPTR object_hd; + dpfOBJECTPTR object_tl; + + dpfTOKEN curtok; + int32 curtag; + float32 semfloat ; + int32 semint ; + + int32 noMaterials, noTextures, noRamps ; + int32 noObjects, noLODs, noPatches ; + int32 noGeometries, noPmeshes ; + int32 noCLists, noCFaces, cFtimesP ; + int32 noSLists, noSFaces, sFtimesP ; + int32 noPolystrips, noTristrips ; + int32 noPolygons, noPolyVerts ; + int32 noVertices, noVertLists, noTriangles ; + int32 noSphereLists, noSpheres ; + int32 noPointLists, noPoints ; + int32 noLineLists, noLines ; + int32 noTextLists, noTexts ; + + dpfVISTEXTUREPTR visList ; + int32 mazSearched ; + char *FtextName, *BtextName ; + uint8 forceVer ; +} dpfFILE ; + +/*****************************************************************************/ +/* Global variables and macros */ +/*****************************************************************************/ + +/* Internal functions */ + +extern int32 (*dpfReadFloatP)(dpfFILEPTR file,float32 *dest); +extern int32 (*dpfReadnFloatP)(dpfFILEPTR file, int32 n, float32 *dest); + +/* Reading data */ +int32 +dpfReadFloatPSS(dpfFILEPTR file,float32 *dest) ; +int32 +dpfReadFloatPSD(dpfFILEPTR file,float32 *dest) ; +int32 +dpfReadFloatPDS(dpfFILEPTR file,float64 *dest) ; +int32 +dpfReadFloatPDD(dpfFILEPTR file,float64 *dest) ; + +int32 +dpfReadnFloatPSS(dpfFILEPTR file,int32 n, float32 *dest) ; +int32 +dpfReadnFloatPSD(dpfFILEPTR file,int32 n, float32 *dest) ; +int32 +dpfReadnFloatPDS(dpfFILEPTR file,int32 n, float64 *dest) ; +int32 +dpfReadnFloatPDD(dpfFILEPTR file,int32 n, float64 *dest) ; + +#define dpfRead1byte(file,dest) dflRead1byte(file->fl,(void *)(dest)) +#define dpfReadn1byte(file,n,dest) dflReadn1byte(file->fl,n,(void *)(dest)) +#define dpfRead2byte(file,dest) dflRead2byte(file->fl,(void *)(dest)) +#define dpfReadn2byte(file,n,dest) dflReadn2byte(file->fl,n,(void *)(dest)) +#define dpfRead4byte(file,dest) dflRead4byte(file->fl,(void *)(dest)) +#define dpfReadn4byte(file,n,dest) dflReadn4byte(file->fl,n,(void *)(dest)) +#define dpfRead8byte(file,dest) dflRead8byte(file->fl,(void *)(dest)) +#define dpfReadn8byte(file,n,dest) dflReadn8byte(file->fl,n,(void *)(dest)) + +/* Writing data */ +#define dpfFwriteint8(file,i) dflWriteint8(file->fl,i) +#define dpfFwriteuint8(file,i) dflWriteuint8(file->fl,i) +#define dpfFwriteint16(file,i) dflWriteint16(file->fl,i) +#define dpfFwriteuint16(file,i) dflWriteuint16(file->fl,i) +#define dpfFwriteint32(file,i) dflWriteint32(file->fl,i) +#define dpfFwritefloat32(file,f) dflWritefloat32(file->fl,f) +#define dpfFwritefloat64(file,f) dflWritefloat64(file->fl,f) +void +dpfFwriteFloatP(dpfFILEPTR file, float32 f) ; + +/* pfcheck checks input values */ +int32 +dpfRgbNotUnit(dpfRGBA r) ; +int32 +dpfRgbNotZero(dpfRGBA r) ; +float32 +dpfCheckRGBValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckAlphaValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckV1PowerValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckV2PowerValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckOpacityValue(dpfFILEPTR file, float32) ; +#define dpfV12v2PowerConvert(p) p +#define dpfV22v1PowerConvert(p) \ + ((p > dpfV1POWER_MAX) ? dpfV1POWER_MAX:p) + +/* Dirty data structure stuff */ +/* Does not unlink from structure so be careful */ +int32 +dpfFreeVertexList(dpfVERTEXPTR vert) ; +int32 +dpfFreeCListList(dpfCLISTPTR cList) ; +int32 +dpfFreeGeometryList(dpfGEOMETRYPTR geometry) ; +int32 +dpfFreeSurfaceNames(dpfSURFACEPTR surface) ; +int32 +dpfFreePatchList(dpfPATCHPTR patch) ; +int32 +dpfFreeLODList(dpfLODPTR lod) ; +int32 +dpfFreeObjectList(dpfOBJECTPTR object) ; + +int32 +dpfFreeBoundList(dpfBOUNDPTR bound) ; +int32 +dpfFreeTextureList(dpfTEXTUREPTR txt) ; +int32 +dpfFreeMaterialList(dpfMATERIALPTR mat) ; +int32 +dpfFreeRampList(dpfRAMPPTR ramp) ; + + +/* Use setSurface, not copySurface, does not free name memory if +** dest suface has already got names +*/ +void +dpfCopySurface(dpfSURFACEPTR dest, dpfSURFACEPTR source); + +dpfFILETYPE +dpfIdentifyFile(dflFILEPTR fp) ; + + +int32 +dpfGetB1FileBody(dpfFILEPTR file) ; +int32 +dpfGetV1FileBody(dpfFILEPTR file) ; +int32 +dpfGetB2FileBody(dpfFILEPTR file) ; +int32 +dpfGetV2FileBody(dpfFILEPTR file) ; +int32 +dpfPutB1FileBody(dpfFILEPTR Dfile, dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutV1FileBody(dpfFILEPTR Dfile, dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutB2FileBody(dpfFILEPTR dest, dpfFILEPTR infile) ; +int32 +dpfPutV2FileBody(dpfFILEPTR dest, dpfFILEPTR infile) ; + +void +dpfConvertV1Texture(dpfFILEPTR Sfp, dpfMATERIALPTR Fmat, dpfMATERIALPTR Bmat) ; + +void +VIZsetLexdfl(dflFILEPTR fl); + +#endif /* ____PFILE_H__ */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/__PTOOL.H b/CODE/RP/MUNGA_L4/libDPL/dsys/__PTOOL.H new file mode 100644 index 0000000..6741a49 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dsys/__PTOOL.H @@ -0,0 +1,84 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: __ptool.h,v $ +-- Revision : $Revision: 1.11 $ +-- Date : $Date: 95/05/16 13:46:18 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ +/* __ptools2.h */ +#ifndef ____PTOOL_H__ +#define ____PTOOL_H__ + +#ifdef _PF_LOCAL +#include "ptool.h" +#else +#include +#endif + +/* ver change */ +/* 2.01 Initial version for tools library */ +/* 2.02 New line definitions and coping with texture etc */ +/* 2.03 New material stuff */ +/* 2.04 New STRIP_LIST and POINTLIST */ +#define dpt_LIBRARY_MAJOR_VER 2 +#define dpt_LIBRARY_MINOR_VER 04 + +#define dpt_TINY_float32 1.0e-24 + + + +/************************************************************* +* ptmesh Routines used by other dptOols * +*************************************************************/ + +dpfVERTEXPTR +dptCreateVertex(void) ; +dpfVERTEXPTR +dptMeshAddVertex ( dptMESHPTR mesh, dpfVERTEXPTR Fvert ) ; +dpfVERTEXPTR +dptMeshAddNewVertex(dptMESHPTR mesh, dpfPATCHPTR patch, dmVector point, + dmVector norm, dpfRGBA col, dpfTEXT text) ; +dptTRIANGLEPTR +dptMeshAddTriangle(dptMESHPTR mesh, dpfPATCHPTR patch, dpfVERTEXPTR vert1, + dpfVERTEXPTR vert2, dpfVERTEXPTR vert3) ; +void +dptMeshRemoveTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptMeshUnloadGeometry(dptTRIANGLEPTR start, dptMESHPTR mesh, dpfPATCHPTR patch, + int32 usePmesh) ; +void +dptMeshDisconnectTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptMeshConnectTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptAddGeometryPatch(dptMESHPTR mesh, dpfGEOMETRYPTR geom) ; + + +/* reduce a mesh, used in ptbound */ +int32 +dptrReduceMesh(dptMESHPTR mesh, float32 Norm_tol, float32 Edge_tol, + int32 Verbose) ; + +/* defined in ptreduce, used also in ptflip */ +dptTRIANGLEPTR +dptGetTriangleDuplicate(dptTRIANGLEPTR tri) ; + +#endif /* ____PTOOL_H__ */ + + diff --git a/CODE/RP/MUNGA_L4/libDPL/dsys/vssver.scc b/CODE/RP/MUNGA_L4/libDPL/dsys/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..72c019d129aeeb371319ffa22449c10e1ba7edbc GIT binary patch literal 384 zcmXpJVq`d2=P%iL-obO(RqsctpMq*OUvyIGvSI*(ZXkX9z}K#Pp=F;Kfg(LX{^Q9- zQp)~|!Teqz|M$wq$jk;>9!2Et7-^{aZ<-_FdVEzOkf0|&_sn1sX z!2F3o{uP@^n#;>~gZYzyeCyMN1%E|d!TiZUK9lXMgpGbqVEz;!e-C#`>iIXmVE$Af zKYZtuu$#w2!2D@I{_>O~;^nDfVE%L<|E6QbSx1{#Fn +#include +#endif /*_DVS_DM_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/DMELEM.H b/CODE/RP/MUNGA_L4/libDPL/dvs/DMELEM.H new file mode 100644 index 0000000..e327747 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/DMELEM.H @@ -0,0 +1,132 @@ +/* + * WARNING: machine generated code. + * + * do NOT edit this file, edit the + * original '.epp' file and regenerate this + * one. + */ + +#ifndef ____DMELEM_H +#define ____DMELEM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Instance number access macros. + */ + + + +/* + * Generated function declarations. + */ +extern int32 ModuleDmInit ( void ); + +extern InstanceNo (VLCreate_dmVector)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmVector)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmVector)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmVector)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmPoint)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmPoint)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmPoint)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmPoint)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmEuler)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmEuler)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmEuler)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmEuler)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmQuaternion)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmQuaternion)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmQuaternion)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmQuaternion)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmScale)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmScale)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmScale)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmScale)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmMatrix)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmMatrix)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmMatrix)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmMatrix)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmPosition)(dmPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmPosition)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmPosition)(InstanceNo ino, dmPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmPosition)(InstanceNo ino , dmPosition *data, VLTime *utime); + +#ifdef __VL_INLINE_ACCESS__ +#define VLCreate_dmVector( d, t, m) vlCreateInstance(el_dmVector, 0, (d),(t),(m)) +#define VLDelete_dmVector(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmVector( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmVector(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmPoint( d, t, m) vlCreateInstance(el_dmPoint, 0, (d),(t),(m)) +#define VLDelete_dmPoint(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmPoint( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmPoint(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmEuler( d, t, m) vlCreateInstance(el_dmEuler, 0, (d),(t),(m)) +#define VLDelete_dmEuler(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmEuler( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmEuler(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmQuaternion( d, t, m) vlCreateInstance(el_dmQuaternion, 0, (d),(t),(m)) +#define VLDelete_dmQuaternion(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmQuaternion( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmQuaternion(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmScale( d, t, m) vlCreateInstance(el_dmScale, 0, (d),(t),(m)) +#define VLDelete_dmScale(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmScale( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmScale(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmMatrix( d, t, m) vlCreateInstance(el_dmMatrix, 0, (d),(t),(m)) +#define VLDelete_dmMatrix(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmMatrix( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmMatrix(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmPosition( d, t, m) vlCreateInstance(el_dmPosition, 0, (d),(t),(m)) +#define VLDelete_dmPosition(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmPosition( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmPosition(i,d,t) vlExtractInstance((i),(d),(t)) + +#endif +/* + * Symbolic element names. + */ +extern const ElementHandle el_dmVector; +extern const ElementHandle el_dmPoint; +extern const ElementHandle el_dmEuler; +extern const ElementHandle el_dmQuaternion; +extern const ElementHandle el_dmScale; +extern const ElementHandle el_dmMatrix; +extern const ElementHandle el_dmPosition; + +static const int ElCountDm = 7; + +/* + * Epp declaraions. NOT 'C' - hence the ifdef guard! + */ +#ifdef __EPP__ +%% +extern atomic element dmVector; +extern atomic element dmPoint; +extern atomic element dmEuler; +extern atomic element dmQuaternion; +extern atomic element dmScale; +extern atomic element dmMatrix; +extern atomic element dmPosition; +%% +#endif/* __EPP__ */ +#ifdef __cplusplus +} +#endif +#endif /* ____DMELEM_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VC.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VC.H new file mode 100644 index 0000000..a6bbad8 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VC.H @@ -0,0 +1,818 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vctools.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:08 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctools.h,v 0.10 1994/10/05 12:51:14 john Exp jon $ + * + * FUNCTION: + * + * Copyright (c) 1992 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine reable form without prior + * written consent from Division Ltd. + */ + +#ifndef _VCTOOLS_H_ +#define _VCTOOLS_H_ +#ifdef NDEBUG +#define NVCDEBUG 1 +#endif + +#include +#include +#include +#include /* VL definitions */ +#include +#include +#include +#include +#include + +# ifdef __cplusplus +extern "C" { +# endif + +#ifdef _LIB_VC +#include /* VC constant defintions */ +#include "_vcdefs.h" +#include "_vctypes.h" +#include /* VC Type definitions */ +#include +#include +#include + + +#if !defined ( __EPP__) && !defined (_VCELEMEN_C) +#include /* VC Element definitions */ +#endif + +#include "_vcstruct.h" +#include "vcstruct.h" +#include /* Object definitions */ +#include /* Verbose reporting. */ +#include +#include +#include +#include +#include "_vctools.h" +#include "vcmacros.h" +#else + +#include /* VC constant defintions */ +#include +#include /* VC Type definitions */ +#include /* VC Type definitions */ +#include +#include +#if !defined ( __EPP__) && !defined (_VCELEMEN_C) +#include /* VC Element definitions */ +#endif +#include +#include +#include /* Object definitions */ +#include /* Verbose reporting. */ +#include +#include +#include +#include +#include +#endif +/* + * Function definitions + */ +/* + *Create & Initialisation routines + */ +void vcVersion (FILE *fp); + +ActorId VC_InitActor(int *argc, char **argv, char *actorName, + VCActorConfig *actorConfig, uint32 mode, + VC_VersionFunc versionFunc); + +ActorId VC_InitApplication(int *argc, char **argv, VC_VersionFunc versionFunc); +int VCErrorInit(char *agentName, char *actorName, int verboseLevel, int debugLevel, + int log, char *log_ext); + + +/* + * Callback routines + */ + +void VC_MainLoop (void); +void VC_ProcessEvent (VLAction action, VLEventData *eventData); + + +void *VC_GetCallbackHandle(void); + +void *VCSignal_AttachCallback (int sigNum, VC_SignalFunc callback, void *data); +void *VC_AttachExitCallback(VC_ExitFunc function, void *data); +void *VCTimer_AttachPeriodicCallback (float t, VCTimer_Func function, void *data); +void *VCTimer_AttachExpiringCallback (float t, VCTimer_Func function, void *data) ; +int VCTimer_DetachCallback(void *callbackHandle); + +void *VCTimer_AttachCallback (VLTime *time, VLTimerMode mode, + VCTimer_Func function, void *data); +void *VCStream_AttachCallback (int streamId, VC_StreamFunc function, void *data); +void *_VC_AttachCreateCallback (ElementHandle elem, InstanceNo inst, VC_CallbackFunc callback, void *data); +void *_VC_AttachDeleteCallback (ElementHandle elem, InstanceNo inst, VC_CallbackFunc callback, void *data); +void *_VC_AttachUpdateCallback (ElementHandle elem, InstanceNo inst, VC_CallbackFunc callback, void *data); +int VCSignal_DetachCallback (int sigNum, void *callbackHandle); +int VC_DetachExitCallback(void *callbackHandle); +int VCStream_DetachCallback (int streamId, void *callbackHandle); +int _VC_DetachCreateCallback (void *callbackHandle, ElementHandle Element, InstanceNo inst); +int _VC_DetachUpdateCallback (void *callbackHandle, ElementHandle element, InstanceNo instNo); +int _VC_DetachDeleteCallback (void *callbackHandle, ElementHandle element, InstanceNo inst); + +/* + * Miscellaneous routines + */ +int VCPosition_MakePointEulerScale (VCPositionData *pos, dmPoint p, dmEuler e, dmScale s); +int VCPosition_ChangePointEulerScale (VCPositionData *pos, dmPoint p, dmEuler e, dmScale s); +uint32 VC_GetNewVcId(void); +void vcInitEnvironment(void); + + +/* + * Name table stuff + */ +duHashTab *VCInstanceTable_Create(int numEntries); +void VCInstanceTable_Delete(duHashTab *table); +void *VCInstanceTable_Get(duHashTab *table, InstanceNo inst, + int *status); +int VCInstanceTable_Attach(duHashTab *table, InstanceNo inst, void + *data, int flags); +void *VCInstanceTable_Detach(duHashTab *table, InstanceNo inst, + int *status); + + +int VCActor_InitResource (char *nameExtension, char *type, uint32 mode, + VCResource_AllocateFunc allocateFunc, + VCAttribute_InvalidFunc deAllocateFunc, + VCAttribute_RelocateFunc relocateFunc, + VCAttribute_Func updateFunc, void *data); + + +/* + * Body handling functions + */ + +int VCBody_Link (VCBody *body, VCEntity *entity, uint32 linkMode); +int VCBody_Unlink(VCBody *body, uint32 unlinkMode); +VCAttribute *VCBody_GetBodyPart (VCBody *body, char *limbName); +int VCBody_Set (VCBody *body, VCBodyFlyInfoData *flyForward, VCBodyFlyInfoData *flyBackward, + VCBodyFlyInfoData *flyUp, VCBodyFlyInfoData *flyDown, VCBodyFlyInfoData *flyLeft, + VCBodyFlyInfoData *flyRight, VCBodyFlyInfoData *rotLeft, VCBodyFlyInfoData *rotRight, + VCBodyFlyInfoData *rotUp, VCBodyFlyInfoData *rotDown, uint32 *verticalFlyKeyCode, + uint32 *altFlyKeyCode, VCEntity *flyDirectionLimb, VCEntity *altFlyDirectionLimb, + VCEntity *altFlyLimb, uint32 setFlyMode, uint32 clearFlyMode); +int VCBody_Get (VCBody *body, uint32 *actorId, VCBodyFlyInfoData *flyForward, VCBodyFlyInfoData *flyBackward, + VCBodyFlyInfoData *flyUp, VCBodyFlyInfoData *flyDown, VCBodyFlyInfoData *flyLeft, + VCBodyFlyInfoData *flyRight, VCBodyFlyInfoData *rotLeft, VCBodyFlyInfoData *rotRight, + VCBodyFlyInfoData *rotUp, VCBodyFlyInfoData *rotDown, uint32 *verticalFlyKeyCode, + uint32 *altFlyKeyCode, VCEntity **flyDirectionLimb, VCEntity **altFlyDirectionLimb, + VCEntity **altFlyLimb, uint32 *flyMode, char **name, + char **user, char **role); +int VCBody_SetData (VCBody *body, VCBodyData *bodyData); +int VCBody_GetData (VCBody *body, VCBodyData *bodyData); + + + +int VCBody_GetAbsolutePosition(VCBody *body, dmMatrix mat); +int VCBody_SetPosition(VCBody *body, VCAttribute *bodyPart, dmPoint point, dmEuler rotation, dmScale scale, + VCEntity *entity, uint32 flags); + +int VCBody_SetSlowSpeed(VCBody *body, float minSpeed); +int VCBody_SetMaxSpeed(VCBody *body, float maxSpeed); +int VCBody_SetFastSpeed(VCBody *body, float fastSpeed); +int VCBody_SetAcceleration(VCBody *body, float acceleration); +int VCBody_SetSlowRotation(VCBody *body, float minRot); +int VCBody_SetFastRotation(VCBody *body, float fastRot); +int VCBody_SetMaxRotation(VCBody *body, float maxRot); +int VCBody_SetRotateAcceleration(VCBody *body, float acceleration); +int VCBody_SetFlyForwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyBackwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetVerticalFlyKeyCode(VCBody *body, uint32 keyCode); +int VCBody_SetAltFlyKeyCode(VCBody *body, uint32 keyCode); +int VCBody_SetFlyDirectionLimb(VCBody *body, VCEntity *flyLimb); +int VCBody_SetAltFlyDirectionLimb(VCBody *body, VCEntity *flyLimb); +int VCBody_SetAltFlyLimb(VCBody *body, VCEntity *flyLimb); +int VCBody_SetFlyMode(VCBody *body, uint32 flyMode); +int VCBody_ModifyFlyMode(VCBody *body, uint32 setFlyMode, uint32 clearFlyMode); +int VCBody_GetActorId(VCBody *body, uint32 *actorId); +int VCBody_GetFlyForwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyBackwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetVerticalFlyKeyCode(VCBody *body, uint32 *keyCode); +int VCBody_GetAltFlyKeyCode(VCBody *body, uint32 *keyCode); +int VCBody_GetFlyDirectionLimb(VCBody *body, VCEntity **flyLimb); +int VCBody_GetAltFlyDirectionLimb(VCBody *body, VCEntity **flyLimb); +int VCBody_GetAltFlyLimb(VCBody *body, VCEntity **flyLimb); +int VCBody_GetFlyMode(VCBody *body, uint32 *flyMode); +int VCBody_GetName(VCBody *body, char **name); +int VCBody_GetUser(VCBody *body, char **user); +int VCBody_GetRole(VCBody *body, char **role); +int VCBody_SetVisualResourceBackgroundColour(VCBody *body, VCColour colour); +int VCBody_SetVisualResourceNearClip(VCBody *body, float32 nearClip); +int VCBody_SetVisualResourceFarClip(VCBody *body, float32 farClip); +int VCBody_SetVisualResourceFogColour(VCBody *body, VCColour colour, uint32 fogType, uint32 fogMode); +int VCBody_SetVisualResourceNearFog(VCBody *body, float32 nearFog); +int VCBody_SetVisualResourceFarFog(VCBody *body, float32 farFog); +int VCBody_SetAudioResourceResourceFile(VCBody *body, char *resourceFile); +int VCBody_SetAudioResourceVolume(VCBody *body, float32 volume); +int VCBody_SetAudioResourceSpreadingRollOff(VCBody *body, float32 spreadingRollOff); +int VCBody_SetAudioResourceAtmosphericAbsorption(VCBody *body, float32 atmosphericAbsorption); + + +void *VCBody_AttachAttributeCallback (VCBody *body, char *limbName, + ElementHandle element, VCBody_AttributeFunc func, + void *data); +int VC_UseBody(char *name); +void *VC_AttachBodyCreateCallback(VCBody_CreateFunc func , void *data); + + +void *VCBody_AttachInputCallback (VCBody *body, char *limbName, uint32 keyCode, uint32 maxKeyCode, + VCBody_InputFunc func, void *data); +void *VCBody_AttachCollisionCallback (VCBody *body, char *limbName, VCBody_CollisionFunc func, + void *data); +void *VCBody_AttachBodyPartCreateCallback(VCBody *body, VCBody_CreateBodyPartFunc func, + void *data); +int VCEntity_Pick (VCEntity *entity , VCAttribute *bodyPart, + VCEntity_DropFunc dropFunc, void *data); +int VCEntity_Drop(VCEntity *entity, VCAttribute *bodyPart); + + +VCBody *VC_GetFirstBody(VC_Traverse *traverseInfo); +VCBody *VC_GetNextBody(VC_Traverse *traverseInfo); +VCBody * VCAttribute_GetBody (VCAttribute *attribute); +VCAttribute *VCBody_GetFirstAttribute (VCBody *body, char *limbName, ElementHandle elem, + VC_Traverse *traverseInfo); +VCAttribute *VCBody_GetNextAttribute (VC_Traverse *traverseInfo); + + +/* + * Hierarchy function routines + */ + +int VC_SetObjectTableSize(int tabsize); +int VCEntity_GetDefaultNumAttributes(void); +int VCEntity_SetDefaultNumAttributes( int numAttributes); +void VCEntityAposInvalid(VCEntity *entity); +int VCAttribute_Get(VCAttribute *attribute, int doExtract); +VCAttribute *VCAttribute_Create(ElementHandle type, InstanceNo inst); +int32 VCAttribute_Delete(VCAttribute *attribute); +VCEntity *VCEntity_Create (VCPositionData *posp, uint32 count ); +int VCEntity_Delete ( VCEntity *entity , uint32 mode); +int VCEntity_SetRelocateMode (VCEntity *entity,int mode); +int VCEntity_GetRelocateMode (VCEntity *entity); +int VCEntity_AttachAttribute (VCEntity *entity, VCAttribute *attribute); +int VCEntity_DetachAttribute (VCEntity *entity, VCAttribute *attribute); +int VCEntity_Link (VCEntity *parent, VCEntity *child, uint32 mode); +int VCEntity_Unlink ( VCEntity *child, uint32 mode); +VCEntity *VCEntity_GetRoot ( VCEntity *entity); +VCEntity *VC_GetFirstEntity ( VCEntity *entity, uint32 incEntity, VC_Traverse *traverse); +VCEntity *VC_GetNextEntity ( VC_Traverse *traverseInfo ); +int VCEntity_GetAbsolutePosition ( VCEntity *entity, dmMatrix mat) ; +void VCEntity_TraverseInOrder(VCEntity *entity, VCEntity_TraverseFunc func, void *data); +void VCEntity_TraversePostOrder(VCEntity *entity, VCEntity_TraverseFunc func, void *data); + +void *VCAttribute_AttachCreateCallback(VCAttribute *attribute, ElementHandle element, + VCAttribute_Func func, void *data); +void *VCAttribute_AttachDeleteCallback(VCAttribute *attribute, ElementHandle element, + VCAttribute_Func func, void *data); +void *VCAttribute_AttachUpdateCallback(VCAttribute *attribute, ElementHandle element, + VCAttribute_Func func, void *data); +int VCAttribute_DetachCreateCallback(VCAttribute *attribute, ElementHandle element, + void *callbackHandle); +int VCAttribute_DetachUpdateCallback(VCAttribute *attribute, ElementHandle element, + void *callbackHandle); +int VCAttribute_DetachDeleteCallback(VCAttribute *attribute, ElementHandle element, + void *callbackHandle); +int VCEntity_DetachAttributeRelocateCallback(ElementHandle element, VCAttribute *attribute, + void *callbackHandle); +void *VCEntity_AttachAttributeRelocateCallback (ElementHandle element, VCAttribute *attribute, + uint32 mode, VCAttribute_RelocateFunc func, + VCAttribute_InvalidFunc inValidFunc, void *data); +int VCEntity_DetachAttributeCreateCallback(VCEntity *entity, void *callbackHandle); +int VCEntity_DetachAttributeUpdateCallback(VCEntity *entity, void *callbackHandle); + +void *VCEntity_AttachAttributeCreateCallback(VCEntity *entity, VCEntity_AttributeFunc func, + void *data); +void *VCEntity_AttachAttributeUpdateCallback(VCEntity *entity, VCEntity_AttributeFunc func, + void *data); + +int VCEntity_DetachRelocateCallback(VCEntity *entity,void *callbackHandle); +void *VCEntity_AttachRelocateCallback(VCEntity *entity, uint32 mode, VCEntity_RelocateFunc func, + VCEntity_InvalidFunc invalidFunc, void *data); + +VCEntity *VCAttribute_GetFirstEntity(VCAttribute *attribute, VC_Traverse *traverse); +VCEntity *VCAttribute_GetNextEntity(VC_Traverse *traverse); + +int _VCList_AttachUserData(VCUserDataList **list, uint32 vcId, void *data); +void *_VCList_GetUserData(VCUserDataList *list, uint32 vcId); +void *_VCList_DetachUserData(VCUserDataList **list, uint32 vcId); + +int VCEntity_SetAbsolutePosition(VCEntity *entity, VCPositionData *pos); +int VCEntity_SetPosition(VCEntity *entity, VCPositionData *pos); +int VCEntity_SetPositionMatrix(VCEntity *entity, dmMatrix mat); +int VCEntity_SetPositionPoint(VCEntity *entity, dmPoint p); +int VCEntity_SetPositionEuler(VCEntity *entity, dmEuler e); +int VCEntity_SetPositionScale(VCEntity *entity, dmScale s); +int VCEntity_SetPositionEulerScale(VCEntity *entity, dmEuler e, dmScale s); +int VCEntity_SetPositionPointEulerScale(VCEntity *entity, dmPoint p, dmEuler e, dmScale s); +int VCEntity_GetPosition(VCEntity *entity, VCPosition **position); +VCPositionData *VCEntity_GetPositionData(VCEntity *); +int VCEntity_GetPositionPointEulerScale(VCEntity *entity, dmPoint p, + dmEuler e, dmScale s); +int VCEntity_SetPositionLinearVelocity(VCEntity *entity, const dmVector velocity); +int VCEntity_SetPositionLinearAcceleration(VCEntity *entity, const dmVector acceleration); +int VCEntity_SetPositionAngularVelocity(VCEntity *entity, const dmVector velocity); +int VCEntity_SetPositionAngularAcceleration(VCEntity *entity, const dmVector acceleration); +VCAttribute *VCEntity_GetFirstAttribute (VCEntity *entity, ElementHandle elem, + VC_Traverse *traverseInfo); +VCAttribute *VCEntity_GetNextAttribute (VC_Traverse *traverseInfo); +int VCEntity_UpdatePosition(VCEntity *entity); + +void *VCCollision_AttachCreateCallback(VCCollision *collision, VCCollision_Func func, void *data); +void *VCCollision_AttachUpdateCallback(VCCollision *collision, VCCollision_Func func, void *data); +void *VCCollision_AttachDeleteCallback(VCCollision *collision, VCCollision_Func func, void *data); +int VCCollision_DetachCreateCallback(VCCollision *collision, void *callbackHandle); +int VCCollision_DetachUpdateCallback(VCCollision *collision, void *callbackHandle); +int VCCollision_DetachDeleteCallback(VCCollision *collision, void *callbackHandle); +void VCCollision_SetCacheMode(VCCollision *collision, uint32 cacheMode); +uint32 VCCollision_GetCacheMode(VCCollision *collision); + +VCCollision *VCCollision_Create(VCAttribute *attribute, VCCollisionReportData *collReportData, + int numCollisionsReported, int numCollisions); +int VCCollision_Get(VCCollision *collision, VCAttribute **attribute, VCCollisionReportData **collReportData, + int *numCollisionsReported, int *numCollisions); +VCCollision *VCCollision_Set(VCAttribute *attribute, VCCollisionReportData *collReportData, + int numCollisionsReported, int *numCollisions); +VCCollisionReportData *VCCollision_GetFirstCollisionReport(VCCollision *collision, VC_Traverse *traverseInfo); +VCCollisionReportData *VCCollision_GetNextCollisionReport(VC_Traverse *traverseInfo); +int VCCollision_Delete(VCCollision *item); + +void VCIntersection_SetCacheMode(VCIntersection *intersection, uint32 cacheMode); +uint32 VCIntersection_GetCacheMode(VCIntersection *intersection); +void *VCIntersection_AttachCreateCallback(VCIntersection *intersection, VCIntersection_Func func, + void *data); +void *VCIntersection_AttachUpdateCallback(VCIntersection *intersection, VCIntersection_Func func, + void *data); +void *VCIntersection_AttachDeleteCallback(VCIntersection *intersection, VCIntersection_Func func, + void *data); +int VCIntersection_DetachCreateCallback(VCIntersection *intersection, void *callbackHandle); +int VCIntersection_DetachUpdateCallback(VCIntersection *intersection, void *callbackHandle); +int VCIntersection_DetachDeleteCallback(VCIntersection *intersection, void *callbackHandle); +VCIntersection *VCIntersection_Create(VCAttribute *attribute, VCIntersectionReportData *intersectReportData, + int numIntersectionsReported, int numIntersections); +int VCIntersection_Get(VCIntersection *intersection, VCAttribute **attribute, + VCIntersectionReportData **intersectReportData, + int *numIntersectionsReported, int *numIntersections); +VCIntersectionReportData *VCIntersection_GetFirstIntersectionReport(VCIntersection *intersection, + VC_Traverse *traverse); +VCIntersectionReportData *VCIntersection_GetNextIntersectionReport(VC_Traverse *traverse); +int VCIntersection_Delete(VCIntersection *item); + + + + +void VCMaterial_SetCacheMode (VCMaterial *item, uint32 newCacheMode); +uint32 VCMaterial_GetCacheMode (VCMaterial *item); +void *VCMaterial_AttachCreateCallback(VCMaterial *item, VCMaterial_Func func, void *data); +void *VCMaterial_AttachUpdateCallback(VCMaterial *item, VCMaterial_Func func, void *data); +void *VCMaterial_AttachDeleteCallback(VCMaterial *item, VCMaterial_Func func, void *data); +int VCMaterial_DetachCreateCallback(VCMaterial *item, void *callbackHandle); +int VCMaterial_DetachUpdateCallback(VCMaterial *item, void *callbackHandle); +int VCMaterial_DetachDeleteCallback(VCMaterial *item, void *callbackHandle); +VCMaterial *VCMaterial_Create (char *name, uint32 mode, VCColor ambient, VCColor diffuse, + VCSpecular specular, VCColor emissive, + VCColor opacity, char *textureName, char *ramp); +VCMaterial *VCMaterial_CreateData (VCMaterialData *materialData); +int VCMaterial_Get (VCMaterial *item, char **name, uint32 *mode, + VCColor ambient, VCColor diffuse, + VCSpecular specular, VCColor emissive, + VCColor opacity, char **textureName, + char **ramp); +int VCMaterial_GetData (VCMaterial *item, VCMaterialData *materialData); +int VCMaterial_SetData (VCMaterial *item,VCMaterialData *materialData); +int VCMaterial_Set (VCMaterial *item, char *name, uint32 setMode, + uint32 clearMode, VCColor ambient, VCColor diffuse, + VCSpecular specular, VCColor emissive, VCColor opacity, + char *textureName, char *ramp); +int VCMaterial_ModifyMode (VCMaterial *item, uint32 setMode, uint32 clearMode); +int VCMaterial_SetName (VCMaterial *item, char *name); +int VCMaterial_SetMode (VCMaterial *item, uint32 mode); +int VCMaterial_SetAmbient (VCMaterial *item, VCColour ambient); +int VCMaterial_SetDiffuse (VCMaterial *item, VCColour diffuse); +int VCMaterial_SetSpecular (VCMaterial *item, VCSpecular specular); +int VCMaterial_SetEmissive (VCMaterial *item, VCColour emissive); +int VCMaterial_SetOpacity (VCMaterial *item, VCColour opacity); +int VCMaterial_SetTexture (VCMaterial *item, char *texture); +int VCMaterial_SetRamp (VCMaterial *item, char *ramp); + +int VCMaterial_GetName (VCMaterial *item, char **name); +int VCMaterial_GetMode (VCMaterial *item, uint32 *mode); +int VCMaterial_GetAmbient (VCMaterial *item, VCColour ambient); +int VCMaterial_GetDiffuse (VCMaterial *item, VCColour diffuse); +int VCMaterial_GetSpecular (VCMaterial *item, VCSpecular specular); +int VCMaterial_GetEmissive (VCMaterial *item, VCColour emissive); +int VCMaterial_GetOpacity (VCMaterial *item, VCColour opacity); +int VCMaterial_GetTexture (VCMaterial *item, char **texture); +int VCMaterial_GetRamp (VCMaterial *item, char **ramp); +int VCMaterial_Delete (VCMaterial *item); + + +void VCTexture_SetCacheMode (VCTexture *item, uint32 newCacheMode); +uint32 VCTexture_GetCacheMode (VCTexture *item); +void *VCTexture_AttachCreateCallback (VCTexture *item, VCTexture_Func func, void *data); +void *VCTexture_AttachUpdateCallback (VCTexture *item, VCTexture_Func func, void *data); +void *VCTexture_AttachDeleteCallback (VCTexture *item, VCTexture_Func func, void *data); +int VCTexture_DetachCreateCallback (VCTexture *item, void *callbackHandle); +int VCTexture_DetachUpdateCallback (VCTexture *item, void *callbackHandle); +int VCTexture_DetachDeleteCallback (VCTexture *item, void *callbackHandle); +VCTexture *VCTexture_Create (char *name, uint32 mode, uint8 minify, uint8 magnify, + uint8 alpha, uint8 wrapU, uint8 wrapV, + uint8 detailType, char *textureMap, char *detailMap); +VCTexture *VCTexture_CreateData (VCTextureData *textureData); +int VCTexture_Get (VCTexture *item, char **name, uint32 *mode, uint8 *minify, + uint8 *magnify, uint8 *alpha, + uint8 *wrapU, uint8 *wrapV, uint8 *detailType, + char **textureMap, char **detailMap); +int VCTexture_GetData (VCTexture *item, VCTextureData *textureData); +int VCTexture_SetData (VCTexture *item,VCTextureData *textureData); +int VCTexture_Set (VCTexture *item, char *name, uint32 setMode, + uint32 clearMode, uint8 *minify, uint8 *magnify, + uint8 *alpha, uint8 *wrapU, uint8 *wrapV, uint8 *detailType, + char *textureMap, char *detailMap); +int VCTexture_ModifyMode (VCTexture *item, uint32 setMode, uint32 clearMode); +int VCTexture_SetName (VCTexture *item, char *name); +int VCTexture_SetMode (VCTexture *item, uint32 mode); +int VCTexture_SetMinify (VCTexture *item, uint8 minify); +int VCTexture_SetMagnify (VCTexture *item, uint8 magnify); +int VCTexture_SetAlpha (VCTexture *item, uint8 alpha); +int VCTexture_SetWrapU (VCTexture *item, uint8 wrapU); +int VCTexture_SetWrapV (VCTexture *item, uint8 wrapV); +int VCTexture_SetDetailType (VCTexture *item, uint8 detailType); +int VCTexture_SetTextureMap (VCTexture *item, char *textureMap); +int VCTexture_SetDetailMap (VCTexture *item, char *detailMap); +int VCTexture_GetName (VCTexture *item, char **name); +int VCTexture_GetMode (VCTexture *item, uint32 *mode); +int VCTexture_GetMinify (VCTexture *item, uint8 *minify); +int VCTexture_GetMagnify (VCTexture *item, uint8 *magnify); +int VCTexture_GetAlpha (VCTexture *item, uint8 *alpha); +int VCTexture_GetWrapU (VCTexture *item, uint8 *wrapU); +int VCTexture_GetWrapV (VCTexture *item, uint8 *wrapV); +int VCTexture_GetDetailType (VCTexture *item, uint8 *detailType); +int VCTexture_GetTextureMap (VCTexture *item, char **textureMap); +int VCTexture_GetDetailMap (VCTexture *item, char **detailMap); +int VCTexture_Delete (VCTexture *item); + +void VCInput_SetCacheMode (VCInput *item, uint32 newCacheMode); +uint32 VCInput_GetCacheMode (VCInput *item); +VCInput *_VC_GetInput (InstanceNo inst); +void *VCInput_AttachCreateCallback (VCInput *item, VCInput_Func func, void *data); +void *VCInput_AttachUpdateCallback (VCInput *item, uint32 minKeyCode, uint32 maxKeyCode, + VCInput_UpdateFunc func, void *data); +void *VCInput_AttachDeleteCallback (VCInput *item, VCInput_Func func, void *data); +int VCInput_DetachCreateCallback (VCInput *item, void *callbackHandle); + +int VCInput_DetachUpdateCallback (VCInput *item, void *callbackHandle); +int VCInput_DetachDeleteCallback (VCInput *item, void *callbackHandle); +VCInput *VCInput_Create (uint32 size); +int VCInput_Append(VCInput *item, uint32 keyCode, int doUpdate); +int VCInput_Update(VCInput *item); +int VCInput_Delete(VCInput *item); + + + + + + +void VCTracker_SetCacheMode(VCTracker *item, uint32 newCacheMode); +uint32 VCTracker_GetCacheMode(VCTracker *item); +void *VCTracker_AttachCreateCallback(VCTracker *item, VCTracker_Func func, void *data); +void *VCTracker_AttachUpdateCallback(VCTracker *item, VCTracker_Func func, void *data); +void *VCTracker_AttachDeleteCallback(VCTracker *item, VCTracker_Func func, void *data); +int VCTracker_DetachCreateCallback(VCTracker *item, void *callbackHandle); +int VCTracker_DetachUpdateCallback(VCTracker *item, void *callbackHandle); +int VCTracker_DetachDeleteCallback(VCTracker *item, void *callbackHandle); +VCTracker *VCTracker_Create(char *name, uint32 updateRate, uint32 transmissionDelay, dmPoint sourcePosition, + dmEuler sourceEuler, uint32 baudRate, char *deviceType); +VCTracker *VCTracker_CreateData(VCTrackerData *trackerData); +int VCTracker_Get(VCTracker *item, char **name, uint32 *updateRate, uint32 *transmissionDelay, dmPoint sourcePosition, + dmEuler sourceEuler, uint32 *baudRate, char **deviceType); +int VCTracker_GetData(VCTracker *item, VCTrackerData *trackerData); +int VCTracker_SetData (VCTracker *item,VCTrackerData *trackerData); +int VCTracker_Set(VCTracker *item, char *name, uint32 *updateRate, uint32 *transmissionDelay, dmPoint sourcePosition, + dmEuler sourceEuler, uint32 *baudRate, char *deviceType); +int VCTracker_SetName(VCTracker *item, char *name); +int VCTracker_SetUpdateRate(VCTracker *item, uint32 updateRate); +int VCTracker_SetTransmissionDelay(VCTracker *item, uint32 transmissionDelay); +int VCTracker_SetSourcePosition(VCTracker *item, dmPoint sourcePosition); +int VCTracker_SetSourceEuler(VCTracker *item, dmPoint sourceEuler); +int VCTracker_SetBaudRate(VCTracker *item, uint32 baudRate); +int VCTracker_SetDeviceType(VCTracker *item, char *deviceType); +int VCTracker_GetName(VCTracker *item, char **name); +int VCTracker_GetUpdateRate(VCTracker *item, uint32 *updateRate); +int VCTracker_GetTransmissionDelay(VCTracker *item, uint32 *transmissionDelay); +int VCTracker_GetSourcePosition(VCTracker *item, dmPoint sourcePosition); +int VCTracker_GetSourceEuler(VCTracker *item, dmPoint sourceEuler); +int VCTracker_GetBaudRate(VCTracker *item, uint32 *baudRate); +int VCTracker_GetDeviceType(VCTracker *item, char **deviceType); +int VCTracker_Delete(VCTracker *item); + + +void VCPosition_SetCacheMode (VCPosition *item, uint32 newCacheMode); +uint32 VCPosition_GetCacheMode(VCPosition *item); +void *VCPosition_AttachCreateCallback(VCPosition *item, VCPosition_Func func, void *data); +void *VCPosition_AttachUpdateCallback(VCPosition *item, VCPosition_Func func, void *data); +void *VCPosition_AttachDeleteCallback(VCPosition *item, VCPosition_Func func, void *data); +int VCPosition_DetachCreateCallback(VCPosition *item, void *callbackHandle); +int VCPosition_DetachUpdateCallback(VCPosition *item, void *callbackHandle); +int VCPosition_DetachDeleteCallback(VCPosition *item, void *callbackHandle); +VCPosition *VCPosition_Create(dmPosition *pos, uint32 mode); +VCPosition *VCPosition_CreateData(VCPositionData *positionData); +int VCPosition_Get(VCPosition *item, dmPosition *pos, uint32 *mode); +int VCPosition_GetData(VCPosition *item, VCPositionData *positionData); +int VCPosition_SetData (VCPosition *item,VCPositionData *positionData); +int VCPosition_Set(VCPosition *item, dmPosition *pos, uint32 setMode, uint32 clearMode); +int VCPosition_Delete(VCPosition *item); + + +void VCXWindowId_SetCacheMode(VCXWindowId *item, uint32 newCacheMode); +uint32 VCXWindowId_GetCacheMode(VCXWindowId *item); +void * VCXWindowId_AttachCreateCallback(VCXWindowId *item, VCXWindowId_Func func, void *data); +void * VCXWindowId_AttachUpdateCallback(VCXWindowId *item, VCXWindowId_Func func, void *data); +void * VCXWindowId_AttachDeleteCallback(VCXWindowId *item, VCXWindowId_Func func, void *data); +int VCXWindowId_DetachCreateCallback(VCXWindowId *item, void *callbackHandle); +int VCXWindowId_DetachUpdateCallback(VCXWindowId *item, void *callbackHandle); +int VCXWindowId_DetachDeleteCallback(VCXWindowId *item, void *callbackHandle); +VCXWindowId * VCXWindowId_Create(char *name, uint32 windowId, char *serverName); +VCXWindowId * VCXWindowId_CreateData(VCXWindowIdData *xwindowidData); +int VCXWindowId_Get(VCXWindowId *item, char **name, uint32 *windowId, char **serverName); +int VCXWindowId_GetData(VCXWindowId *item, VCXWindowIdData *xwindowidData); +int VCXWindowId_SetData (VCXWindowId *item,VCXWindowIdData *xwindowidData); +int VCXWindowId_Set(VCXWindowId *item, char *name, uint32 *windowId, char *serverName); +int VCXWindowId_SetName(VCXWindowId *item, char *name); +int VCXWindowId_SetWindowId(VCXWindowId *item, uint32 windowId); +int VCXWindowId_SetServerName(VCXWindowId *item, char *serverName); +int VCXWindowId_GetName(VCXWindowId *item, char **name); +int VCXWindowId_GetWindowId(VCXWindowId *item, uint32 *windowId); +int VCXWindowId_GetServerName(VCXWindowId *item, char **serverName); +int VCXWindowId_Delete(VCXWindowId *item); + + +void VCPseudoGravity_SetCacheMode(VCPseudoGravity *item, uint32 newCacheMode); + +uint32 VCPseudoGravity_GetCacheMode(VCPseudoGravity *item); + +void * VCPseudoGravity_AttachCreateCallback(VCPseudoGravity *item, VCPseudoGravity_Func func, void *data); + +void * VCPseudoGravity_AttachUpdateCallback(VCPseudoGravity *item, VCPseudoGravity_Func func, void *data); + +void * VCPseudoGravity_AttachDeleteCallback(VCPseudoGravity *item, VCPseudoGravity_Func func, void *data); + +int VCPseudoGravity_DetachCreateCallback(VCPseudoGravity *item, void *callbackHandle); + +int VCPseudoGravity_DetachUpdateCallback(VCPseudoGravity *item, void *callbackHandle); + +int VCPseudoGravity_DetachDeleteCallback(VCPseudoGravity *item, void *callbackHandle); + +VCPseudoGravity * VCPseudoGravity_Create(uint32 mode, dmVector direction, float32 gravity); + +VCPseudoGravity * VCPseudoGravity_CreateData(VCPseudoGravityData *pseudoGravityData); + +int VCPseudoGravity_Get(VCPseudoGravity *item, uint32 *mode, dmVector direction, float32 *gravity); + +int VCPseudoGravity_GetData(VCPseudoGravity *item, VCPseudoGravityData *pseudoGravityData); + +int VCPseudoGravity_SetData (VCPseudoGravity *item,VCPseudoGravityData *pseudoGravityData); + +int VCPseudoGravity_Set(VCPseudoGravity *item, uint32 setMode, uint32 clearMode, dmVector direction, + float32 *gravity); + +int VCPseudoGravity_ModifyMode(VCPseudoGravity *item, uint32 setMode, uint32 clearMode); +int VCPseudoGravity_SetMode(VCPseudoGravity *item, uint32 mode); + +int VCPseudoGravity_SetDirection(VCPseudoGravity *item, dmVector direction); + +int VCPseudoGravity_SetGravity(VCPseudoGravity *item, float32 gravity); + +int VCPseudoGravity_GetMode(VCPseudoGravity *item, uint32 *mode); + +int VCPseudoGravity_GetDirection(VCPseudoGravity *item, dmVector direction); + +int VCPseudoGravity_GetGravity(VCPseudoGravity *item, float32 *gravity); + +int VCPseudoGravity_Delete(VCPseudoGravity *item); + + + +void VCVisualViewResource_SetCacheMode(VCVisualViewResource *item, uint32 newCacheMode); +uint32 VCVisualViewResource_GetCacheMode(VCVisualViewResource *item); +VCVisualViewResource *_VCVisualViewResource_GetViewFromAttribute(VCAttribute *attribute); +VCAttribute *_VCVisualViewResource_GetAttribute(VCVisualViewResource *view); +void *VCVisualViewResource_AttachCreateCallback(VCVisualViewResource *item, VCVisualViewResource_Func func, void *data); +void *VCVisualViewResource_AttachUpdateCallback(VCVisualViewResource *item, VCVisualViewResource_Func func, void *data); +void *VCVisualViewResource_AttachDeleteCallback(VCVisualViewResource *item, VCVisualViewResource_Func func, void *data); +int VCVisualViewResource_DetachCreateCallback(VCVisualViewResource *item, void *callbackHandle); +int VCVisualViewResource_DetachUpdateCallback(VCVisualViewResource *item, void *callbackHandle); +int VCVisualViewResource_DetachDeleteCallback(VCVisualViewResource *item, void *callbackHandle); +VCVisualViewResource *VCVisualViewResource_Create(char *name, VCAttribute *visualResource, uint32 mode, + dmPoint offset, dmEuler orientation, float32 size[2]); +VCVisualViewResource *VCVisualViewResource_CreateData(VCVisualViewResourceData *viewData); +int VCVisualViewResource_Get(VCVisualViewResource *item, char **name, VCAttribute **visualResource, + uint32 *mode, dmPoint offset, dmEuler orientation, float32 size[2]); +int VCVisualViewResource_GetData(VCVisualViewResource *item, VCVisualViewResourceData *viewData); +int VCVisualViewResource_SetData (VCVisualViewResource *item,VCVisualViewResourceData *viewData); +int VCVisualViewResource_Set(VCVisualViewResource *item, VCAttribute *visualResource, + uint32 setMode, uint32 clearMode, dmPoint offset, + dmEuler orientation, float32 size[2]); + +int VCVisualViewResource_Delete(VCVisualViewResource *item); +int VCVisualViewResource_SetVisualResource(VCVisualViewResource *item, VCAttribute *visualResource); +int VCVisualViewResource_SetMode(VCVisualViewResource *item, uint32 mode); +int VCVisualViewResource_ModifyMode(VCVisualViewResource *item, uint32 setMode, uint32 clearMode); +int VCVisualViewResource_SetOffset(VCVisualViewResource *item, dmPoint offset); +int VCVisualViewResource_SetOrientation(VCVisualViewResource *item, dmEuler orientation); +int VCVisualViewResource_SetSize(VCVisualViewResource *item, float32 size[2]); +int VCVisualViewResource_GetName(VCVisualViewResource *item, char **name); +int VCVisualViewResource_GetVisualResource(VCVisualViewResource *item, VCAttribute **visualResource); +int VCVisualViewResource_GetMode(VCVisualViewResource *item, uint32 *mode); +int VCVisualViewResource_GetOffset(VCVisualViewResource *item, dmPoint offset); +int VCVisualViewResource_GetOrientation(VCVisualViewResource *item, dmEuler orientation); +int VCVisualViewResource_GetSize(VCVisualViewResource *item, float32 size[2]); + +VCVisualViewResource *VCVisualViewResource_GetFirst(VCAttribute *visualResource, VC_Traverse *traverseInfo); +VCVisualViewResource *VCVisualViewResource_GetNext(VC_Traverse *traverseInfo); + + + + + +VCEntity *VC_ConstructAudioVoice(char *voice, VCAttribute **audioAttribute); +VCEntity *VC_ConstructAudioData(VCAudioData *audioData, VCAttribute **audioAttribute); +VCEntity *VC_ConstructLightAmbient(VCColour colour, VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightDirectional(VCColour colour, VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightPoint(VCColour colour, VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightSpot(VCColour colour, float32 exponent, float32 theta, + VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightData(VCLightData *lightData, VCAttribute **lightAttribute); +VCEntity *VC_ConstructVisualGeometry(char *geometry, int collidable, VCAttribute **visualAttribute, + VCAttribute **boundaryAttribute); +VCEntity *VC_ConstructVisualData(VCVisualData *visualData, int collidable, VCAttribute **visualAttribute, + VCAttribute **boundaryAttribute); + + +void VCSync_SetCacheMode(VCSync *item, uint32 newCacheMode); +uint32 VCSync_GetCacheMode(VCSync *item); +void *VC_AttachSyncCallbacks(char *actorName, char *actorType, VCSync_Func updateFunc, + VCSync_Func deleteFunc, void *data); +int VC_DetachSyncCallbacks( void *callbackHandle); +VCSync *VCSync_Create(char *name, char *actorType, VCTime *time); +int VCSync_Get(VCSync *item, char **name, char **actorType, VCTime *time); +int VCSync_Set(VCSync *item, VCTime *time); +int VCSync_SetTime(VCSync *item, VCTime *time); +int VCSync_GetName(VCSync *item, char **name); +int VCSync_GetActorType(VCSync *item, char **type); +int VCSync_GetTime(VCSync *item, VCTime *time); +int VCSync_Delete(VCSync *item); + + +void VCCollideMonitor_SetCacheMode (VCCollideMonitor *item, uint32 newCacheMode); +uint32 VCCollideMonitor_GetCacheMode (VCCollideMonitor *item); +void *VCCollideMonitor_AttachCreateCallback (VCCollideMonitor *item, VCCollideMonitor_Func func, void *data); +void *VCCollideMonitor_AttachUpdateCallback (VCCollideMonitor *item, VCCollideMonitor_Func func, void *data); +void *VCCollideMonitor_AttachDeleteCallback (VCCollideMonitor *item, VCCollideMonitor_Func func, void *data); +int VCCollideMonitor_DetachCreateCallback (VCCollideMonitor *item, void *callbackHandle); +int VCCollideMonitor_DetachUpdateCallback (VCCollideMonitor *item, void *callbackHandle); +int VCCollideMonitor_DetachDeleteCallback (VCCollideMonitor *item, void *callbackHandle); +VCCollideMonitor *VCCollideMonitor_CreateData (VCCollideMonitorData *collideMonitorData); +int VCCollideMonitor_GetData (VCCollideMonitor *item, VCCollideMonitorData *collideMonitorData); +int VCCollideMonitor_SetData (VCCollideMonitor *item,VCCollideMonitorData *collideMonitorData); +int VCCollideMonitor_Delete (VCCollideMonitor *item); + +void VCTrackerMonitor_SetCacheMode (VCTrackerMonitor *item, uint32 newCacheMode); +uint32 VCTrackerMonitor_GetCacheMode (VCTrackerMonitor *item); +void *VCTrackerMonitor_AttachCreateCallback (VCTrackerMonitor *item, VCTrackerMonitor_Func func, void *data); +void *VCTrackerMonitor_AttachUpdateCallback (VCTrackerMonitor *item, VCTrackerMonitor_Func func, void *data); +void *VCTrackerMonitor_AttachDeleteCallback (VCTrackerMonitor *item, VCTrackerMonitor_Func func, void *data); +int VCTrackerMonitor_DetachCreateCallback (VCTrackerMonitor *item, void *callbackHandle); +int VCTrackerMonitor_DetachUpdateCallback (VCTrackerMonitor *item, void *callbackHandle); +int VCTrackerMonitor_DetachDeleteCallback (VCTrackerMonitor *item, void *callbackHandle); +VCTrackerMonitor *VCTrackerMonitor_CreateData (VCTrackerMonitorData *trackerMonitorData); +int VCTrackerMonitor_GetData (VCTrackerMonitor *item, VCTrackerMonitorData *trackerMonitorData); +int VCTrackerMonitor_SetData (VCTrackerMonitor *item,VCTrackerMonitorData *trackerMonitorData); +int VCTrackerMonitor_Delete (VCTrackerMonitor *item); + +void VCVisualMonitor_SetCacheMode (VCVisualMonitor *item, uint32 newCacheMode); +uint32 VCVisualMonitor_GetCacheMode (VCVisualMonitor *item); +void *VCVisualMonitor_AttachCreateCallback (VCVisualMonitor *item, VCVisualMonitor_Func func, void *data); +void *VCVisualMonitor_AttachUpdateCallback (VCVisualMonitor *item, VCVisualMonitor_Func func, void *data); +void *VCVisualMonitor_AttachDeleteCallback (VCVisualMonitor *item, VCVisualMonitor_Func func, void *data); +int VCVisualMonitor_DetachCreateCallback (VCVisualMonitor *item, void *callbackHandle); +int VCVisualMonitor_DetachUpdateCallback (VCVisualMonitor *item, void *callbackHandle); +int VCVisualMonitor_DetachDeleteCallback (VCVisualMonitor *item, void *callbackHandle); +VCVisualMonitor *VCVisualMonitor_CreateData (VCVisualMonitorData *visualMonitorData); +int VCVisualMonitor_GetData (VCVisualMonitor *item, VCVisualMonitorData *visualMonitorData); +int VCVisualMonitor_SetData (VCVisualMonitor *item,VCVisualMonitorData *visualMonitorData); +int VCVisualMonitor_Delete (VCVisualMonitor *item); + +void VCRadiator_SetCacheMode(VCRadiator *item, uint32 newCacheMode); +uint32 VCRadiator_GetCacheMode(VCRadiator *item); +void *VCRadiator_AttachCreateCallback(VCRadiator *item, VCRadiator_Func func, void *data); +void *VCRadiator_AttachUpdateCallback(VCRadiator *item, VCRadiator_Func func, void *data); +void *VCRadiator_AttachDeleteCallback(VCRadiator *item, VCRadiator_Func func, void *data); +int VCRadiator_DetachCreateCallback(VCRadiator *item, void *callbackHandle); +int VCRadiator_DetachUpdateCallback(VCRadiator *item, void *callbackHandle); +int VCRadiator_DetachDeleteCallback(VCRadiator *item, void *callbackHandle); +VCRadiator *VCRadiator_Create (char *name, int32 numPoints, float32 points[VC_RADIATOR_MAX_POINTS]); +VCRadiator *VCRadiator_CreateData(VCRadiatorData *radiatorData); +int VCRadiator_Get (VCRadiator *item, char **name, int32 *numPoints, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_GetData(VCRadiator *item, VCRadiatorData *radiatorData); +int VCRadiator_SetData (VCRadiator *item,VCRadiatorData *radiatorData); +int VCRadiator_Set (VCRadiator *radiator, char *name, int32 *numPoints, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_SetName(VCRadiator *radiator, char *name); +int VCRadiator_SetNumPoints(VCRadiator *radiator, int32 numPoints); +int VCRadiator_SetPoints(VCRadiator *radiator, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_GetName(VCRadiator *radiator, char **name); +int VCRadiator_GetNumPoints(VCRadiator *radiator, int32 *numPoints); +int VCRadiator_GetPoints(VCRadiator *radiator, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_Delete(VCRadiator *item); + +void VCRamp_SetCacheMode(VCRamp *item, uint32 newCacheMode); +uint32 VCRamp_GetCacheMode(VCRamp *item); +void *VCRamp_AttachCreateCallback(VCRamp *item, VCRamp_Func func, void *data); +void *VCRamp_AttachUpdateCallback(VCRamp *item, VCRamp_Func func, void *data); +void *VCRamp_AttachDeleteCallback(VCRamp *item, VCRamp_Func func, void *data); +int VCRamp_DetachCreateCallback(VCRamp *item, void *callbackHandle); +int VCRamp_DetachUpdateCallback(VCRamp *item, void *callbackHandle); +int VCRamp_DetachDeleteCallback(VCRamp *item, void *callbackHandle); +VCRamp *VCRamp_Create(char *name, uint32 mode, VCColour minRgb, VCColour maxRgb); +VCRamp *VCRamp_CreateData(VCRampData *rampData); +int VCRamp_Get(VCRamp *item, char **name, uint32 *mode, VCColour minRgb, VCColour maxRgb); +int VCRamp_GetData(VCRamp *item, VCRampData *rampData); +int VCRamp_SetData (VCRamp *item,VCRampData *rampData); +int VCRamp_Set(VCRamp *item, char *name, uint32 setMode, uint32 clearMode, VCColour minRgb, VCColour maxRgb); +int VCRamp_ModifyMode(VCRamp *item, uint32 setMode, uint32 clearMode); +int VCRamp_SetName(VCRamp *item, char *name); +int VCRamp_SetMode(VCRamp *item, uint32 mode); +int VCRamp_SetMinRgb (VCRamp *item, VCColour minRgb); +int VCRamp_SetMaxRgb (VCRamp *item, VCColour maxRgb); +int VCRamp_GetName(VCRamp *item, char **name); +int VCRamp_GetMode(VCRamp *item, uint32 *mode); +int VCRamp_GetMinRgb (VCRamp *item, VCColour minRgb); +int VCRamp_GetMaxRgb (VCRamp *item, VCColour maxRgb); +int VCRamp_Delete(VCRamp *item); + + + + + +int VC_StartGroup(void); +int VC_StopGroup(void); +int32 VC_GetGroup(void); + +int VC_DetachGroupCallback(void *callbackHandle); +void *VC_AttachGroupCallback(VC_GroupFunc function, void *data); + +char *VC_ErrorString(int errno, int errType); +void VC_Perror(char *message); +void VCPrintBadMatrixSplit(dmMatrix mat, char *func, char *file, int line); + +extern VCAttribute *VCFindAttribute (const InstanceNo attrIno); +extern VCEntity * VCFindObject( const InstanceNo obj_ino); + +extern char *VCApplicationName; +extern char *VCDomainName; +extern char *VCDomainExtName; +extern FILE *VCLogFilePtr; +extern int vcerrno; +extern int vcErrType; +# ifdef __cplusplus +} +# endif +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCBODAPP.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCBODAPP.H new file mode 100644 index 0000000..97aa8e7 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCBODAPP.H @@ -0,0 +1,47 @@ + +typedef struct +{ + int state; + void *collideEntity; + void *pickEntity; + void *pickRelocateHandle; + void *relocateData; +}VCBodyPartAppInfo; + +typedef struct +{ + VCEntity *entity; + VCAttribute *bodyPart; + VCBody *body; +}VCBodyAppCallbackData; + +typedef struct +{ + VCAttribute *bodyPart; + VCBody *body; +}VCBodyAppRelocateData; + + +#define VC_BODYAPP_COLLIDED 0x00000001 +#define VC_BODYAPP_PICK_PRESSED 0x00000002 + +typedef void (*VCBodyTouchFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyUnTouchFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyPickFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyDropFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyMoveFunc)(VCBodyAppCallbackData *callbackData, void *data); + +typedef struct +{ + void *touchFunc; + void *unTouchFunc; + void *pickFunc; + void *dropFunc; + void *moveFunc; +} VCBodyFuncInfo; + +void *VCBody_AttachInteractionCallbacks(VCBody *body, VCBodyTouchFunc touchFunc, + VCBodyUnTouchFunc unTouchFunc, VCBodyPickFunc pickFunc, + VCBodyDropFunc dropFunc, VCBodyMoveFunc moveFunc, void *data); + +void VCBody_DetachInteractionCallbacks(VCBody *body, void *callbackHandle); diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCDATA.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDATA.H new file mode 100644 index 0000000..19d07a6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDATA.H @@ -0,0 +1,60 @@ + +#define VCEntity_AttachUserData(e,i,d) _VCList_AttachUserData(&((e)->systemData->userData),i,d) +#define VCEntity_GetUserData(e,i) _VCList_GetUserData((e)->systemData->userData,i) +#define VCEntity_DetachUserData(e,i) _VCList_DetachUserData(&((e)->systemData->userData),i) + +#define VCEntityAttribute_AttachUserData(e,o,i,d) _VCList_AttachUserData(&((e)->attributes[o].userDataList),i,d) +#define VCEntityAttribute_GetUserData(e,o,i) _VCList_GetUserData ((e)->attributes[o].userDataList,i) +#define VCEntityAttribute_DetachUserData(e,o,i) _VCList_DetachUserData (&((e)->attributes[o].userDataList),i) +#define VCAttribute_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCAttribute_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCAttribute_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCMaterial_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCMaterial_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCMaterial_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCCollision_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCCollision_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCCollision_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCTexture_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCTexture_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCTexture_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCInput_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCInput_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCInput_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCIntersection_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCIntersection_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCIntersection_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCTracker_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCTracker_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCTracker_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCPosition_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCPosition_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCPosition_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCXWindowId_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCXWindowId_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCXWindowId_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCPseudoGravity_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCPseudoGravity_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCPseudoGravity_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCVisualViewResource_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->attribute->userDataList),i,d) +#define VCVisualViewResource_GetUserData(a,i) _VCList_GetUserData((a)->attribute->userDataList,i) +#define VCVisualViewResource_DetachUserData(a,i) _VCList_DetachUserData(&((a)->attribute->userDataList),i) +#define VCSync_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCSync_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCSync_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCCollideMonitor_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCCollideMonitor_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCCollideMonitor_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCTrackerMonitor_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCTrackerMonitor_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCTrackerMonitor_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCVisualMonitor_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCVisualMonitor_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCVisualMonitor_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCRadiator_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCRadiator_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCRadiator_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCRamp_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCRamp_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCRamp_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) + diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCDEFS.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDEFS.H new file mode 100644 index 0000000..487b2e2 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDEFS.H @@ -0,0 +1,597 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vcdefs.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:10 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcdefs.h,v 1.3 1995/03/22 12:23:51 jeff Exp $ + * + * FUCTION: + * + * + * + * + * Copyright (c) 1992 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +/*--- Local sizing constants */ + +#define VC_RED 0 +#define VC_GREEN 1 +#define VC_BLUE 2 +#define VC_MAX_OBJECT_ATTRIBUTES 6 + +#define VC_ERRTYPE_NONE 0 +#define VC_ERRTYPE_VL 1 +#define VC_ERRTYPE_DM 2 +#define VC_ERRTYPE_VC 3 +#define VC_ERRTYPE_SYSTEM 4 + +#define VC_MAX_SIGNALS 32 + +#define VC_MAX_SENSORS 4 + +#define VC_RADIATOR_MAX_POINTS 36 +#define VC_RADIATOR_NAME_LENGTH 16 + +#define VC_LIGHT_ENABLE 0x00000004 + +#define VC_LIGHT_MODE_MASK 0x00000003 +#define VC_LIGHT_MODE_DIRECTIONAL 0x00000000 +#define VC_LIGHT_MODE_POINT 0x00000001 +#define VC_LIGHT_MODE_AMBIENT 0x00000002 +#define VC_LIGHT_MODE_SPOT 0x00000003 + +#define VC_LOD_NAME_LENGTH 8 + +#define VC_NO_INSTANCES -1 +#define VC_ALL_INSTANCES 0 +#define VC_FIRST_ATTRIBUTE -1 +#define VC_ALL_ATTRIBUTES -1 + +#define VC_ALL_ELEMENTS 0 +/* + * Values for Visible field in Visual object + */ + +#define VC_ALL_MODES 0xffffffff +#define VC_VISIBLE 0x01 +#define VC_VISUAL_ENABLE 0x01 +#define VC_RMODE_POLYGONAL 0x00 +#define VC_RMODE_WIREFRAME 0x02 +#define VC_RMODE_SPARE1 0x04 +#define VC_RMODE_SPARE2 0x06 +#define VC_VISUAL_BILLBOARD 0x08 +#define VC_VISUAL_NOVECTINTERSECT 0x10 + +#define VC_RMODE_MASK 0x06 + + + +#define VC_VISUALVIEW_MODE_MASK 0x03 +#define VC_VISUALVIEW_RELATIVE_MODE_MASK 0x04 + +#define VC_VISUALVIEW_MODE_MONO 0x00 +#define VC_VISUALVIEW_MODE_LEFT 0x01 +#define VC_VISUALVIEW_MODE_RIGHT 0x02 +#define VC_VISUALVIEW_RELATIVE_MODE_HEAD 0x00 +#define VC_VISUALVIEW_RELATIVE_MODE_EYE 0x04 +#define VC_VISUALVIEW_ENABLE 0x08 + + +#define VC_VISUALRESOURCE_FOG_MASK 0x00070000 +#define VC_VISUALRESOURCE_FOG_MODE_MASK 0x00000010 +#define VC_VISUALRESOURCE_PHASE_MODE_MASK 0x00003000 +#define VC_VISUALRESOURCE_RENDERMODE_MASK 0x00000001 + +#define VC_VISUALRESOURCE_MODE_POLYGONAL 0x00000000 +#define VC_VISUALRESOURCE_MODE_WIREFRAME 0x00000001 +#define VC_VISUALRESOURCE_MODE_STATISTICS 0x00000002 +#define VC_VISUALRESOURCE_MODE_TEXTURE 0x00000004 +#define VC_VISUALRESOURCE_MODE_SINGLE_BUF 0x00000008 +#define VC_VISUALRESOURCE_FOG_MODE_PIXEL 0x00000000 +#define VC_VISUALRESOURCE_FOG_MODE_VERTEX 0x00000010 +#define VC_VISUALRESOURCE_PHASE_MODE_LOCK 0x00000000 +#define VC_VISUALRESOURCE_PHASE_MODE_FLOAT 0x00001000 +#define VC_VISUALRESOURCE_PHASE_MODE_FREE 0x00002000 +#define VC_VISUALRESOURCE_PHASE_MODE_LIMIT 0x00003000 +#define VC_VISUALRESOURCE_ENABLE 0x00008000 +#define VC_VISUALRESOURCE_FOG_DISABLED 0x00000000 +#define VC_VISUALRESOURCE_FOG_LINEAR 0x00010000 +#define VC_VISUALRESOURCE_FOG_EXP 0x00020000 +#define VC_VISUALRESOURCE_FOG_EXP_SQUARED 0x00030000 +#define VC_VISUALRESOURCE_Z_CLEAR_ONLY 0x00080000 + + + +#define VC_NOT_PICKED 3 +#define VC_NOT_DROPPED VC_NOT_PICKED +#define VC_FOUND_DEFAULT 2 +#define VC_FOUND_EXPLICIT 1 +#define VC_OK 0 +#define VC_ERR -1 +#define VC_NOT_FOUND -1 +#define VC_EXISTS -2 +#define VC_BAD_ARGS -3 +#define VC_BAD_ACTOR VL_BAD_ACTOR +/* + * flags to VCAddInstance + */ +#define VC_ADD 0 +#define VC_OVERRIDE 1 +#define VC_FAIL 2 + +#define VC_X 0 +#define VC_Y 1 +#define VC_Z 2 +#define VC_W 3 + +#define VC_MIN_X 0 +#define VC_MIN_Y 1 +#define VC_MIN_Z 2 +#define VC_MAX_X 3 +#define VC_MAX_Y 4 +#define VC_MAX_Z 5 + +#define VC_BOUND_ROT_X 6 +#define VC_BOUND_ROT_Y 7 +#define VC_BOUND_ROT_Z 8 + +#define VC_BOUND_SIZE 9 + + +#define VC_MIN_PITCH 0 +#define VC_MIN_YAW 1 +#define VC_MIN_ROLL 2 +#define VC_MAX_PITCH 3 +#define VC_MAX_YAW 4 +#define VC_MAX_ROLL 5 + +#define VC_RADIUS 3 + +#define VC_CONSTRAIN_ENABLE 0x80000000 +#define VC_CONSTRAIN_MODE_MASK 0x7fffffff + +#define VC_CONSTRAIN_NORMAL 0 +#define VC_CONSTRAIN_HINGE_X 1 +#define VC_CONSTRAIN_HINGE_Y 2 +#define VC_CONSTRAIN_HINGE_Z 3 + + + +#define VC_PICK_CONSTRAINED 0x00000000 +#define VC_PICK_NON_CONSTRAINED 0x00000001 +#define VC_PICK_DROP 0x00000002 +#define VC_PICK_IDLE 0x00000003 + +#define VC_PICK_COMMAND_MASK 0x0000000f + + +/* + * Mice input port types + */ +#define VC_SERIAL 1 +#define VC_PARALLEL 2 +#define VC_PIO 3 + +#define VC_PV100_MOUSE 1 +#define VC_PV200_MOUSE 2 +#define VC_LOGITECH_MOUSE 3 +#define VC_SPACEBALL_MOUSE 4 + + +#define VC_HOOK_ATTACH_MASK 0x0000000f +#define VC_HOOK_DETACH_MASK 0x000000f0 + +#define VC_ATTACH_ABSOLUTE 0x00000001 +#define VC_ATTACH_RELATIVE 0x00000002 +#define VC_DETACH_ABSOLUTE 0x00000010 +#define VC_DETACH_RELATIVE 0x00000020 + +#define VC_LINK_LEAVE_POSITION 0x00000000 +#define VC_LINK_ADJUST_POSITION 0x00000001 +#define VC_LINK_QUIET 0x00000002 +#define VC_UNLINK_LEAVE_POSITION 0x00000000 +#define VC_UNLINK_ADJUST_POSITION 0x00000001 +#define VC_UNLINK_QUIET 0x00000002 +#define VC_UNLINK_DONT_FIX_PARENT_INTEREST 0x00000010 + +#define VC_LOCK_X_VAL 0x00000001 +#define VC_LOCK_Y_VAL 0x00000002 +#define VC_LOCK_Z_VAL 0x00000004 +#define VC_LOCK_X 0x00000010 +#define VC_LOCK_Y 0x00000020 +#define VC_LOCK_Z 0x00000040 +#define VC_LOCK_ROLL_VAL 0x00000100 +#define VC_LOCK_PITCH_VAL 0x00000200 +#define VC_LOCK_YAW_VAL 0x00000400 +#define VC_LOCK_ROLL 0x00001000 +#define VC_LOCK_PITCH 0x00002000 +#define VC_LOCK_YAW 0x00004000 +#define VC_LOCK_FIXED 0x00010000 + +/* + * Body Values + */ + +#define VC_BODY_USE_ENTITY_TRANSLATION 0x00000001 +#define VC_ALL_BODIES -1 + +#define VC_BODY_FLY_ENABLED 0x00000001 +#define VC_BODY_FLY_VERTICAL 0x00000002 +#define VC_BODY_FLY_VERTICAL_ALWAYS 0x00000004 +#define VC_BODY_FLY_FORWARD_SLOW 0x00000008 +#define VC_BODY_FLY_FORWARD_FAST 0x00000010 +#define VC_BODY_FLY_FORWARD_ACCELERATE 0x00000020 +#define VC_BODY_FLY_BACKWARD_SLOW 0x00000040 +#define VC_BODY_FLY_BACKWARD_FAST 0x00000080 +#define VC_BODY_FLY_BACKWARD_ACCELERATE 0x00000100 + +#define VC_BODY_ROT_LEFT_SLOW 0x00000200 +#define VC_BODY_ROT_LEFT_FAST 0x00000400 +#define VC_BODY_ROT_LEFT_ACCELERATE 0x00000800 +#define VC_BODY_ROT_RIGHT_SLOW 0x00001000 +#define VC_BODY_ROT_RIGHT_FAST 0x00002000 +#define VC_BODY_ROT_RIGHT_ACCELERATE 0x00004000 + +#define VC_BODY_FLY_LEFT_SLOW 0x00008000 +#define VC_BODY_FLY_LEFT_FAST 0x00010000 +#define VC_BODY_FLY_LEFT_ACCELERATE 0x00020000 +#define VC_BODY_FLY_RIGHT_SLOW 0x00040000 +#define VC_BODY_FLY_RIGHT_FAST 0x00080000 +#define VC_BODY_FLY_RIGHT_ACCELERATE 0x00100000 + +#define VC_BODY_FLY_UP_SLOW 0x00200000 +#define VC_BODY_FLY_UP_FAST 0x00400000 +#define VC_BODY_FLY_UP_ACCELERATE 0x00800000 +#define VC_BODY_FLY_DOWN_SLOW 0x01000000 +#define VC_BODY_FLY_DOWN_FAST 0x02000000 +#define VC_BODY_FLY_DOWN_ACCELERATE 0x04000000 + + + + +/* + * Flags for new VCActorInit call - MG, March 23, '94 + * + */ + +#define VC_INIT_NOUSER 0x001 /* Don't get user information */ +#define VC_INIT_NOCONFIG 0x002 /* Don't do actor configuration */ + +/* + * Sensor Resource update Mode values + */ + +#define VC_MODE_IMMEDIATE 1 +#define VC_MODE_INDIRECT 2 + +/* + * VCObject Update Modes + */ + +#define VC_REPORT_LOCAL_UPDATES 0x00000001 +#define VC_REPORT_REMOTE_UPDATES 0x00000002 + +/* + * flags for VCPosition mode bit + */ + +#define VC_DEAD_RECKON 0x00000001 + +/* + * Flags passed into VCRelocateHandler & relocate functions + */ + +#define VC_REPORT_ABSOLUTE_POSITION 0x00000000 +#define VC_REPORT_RELATIVE_POSITION 0x00000001 +#define VC_REPORT_DONT_DEAD_RECKON 0x00000002 +#define VC_REPORT_DELAY_RELOCATE 0x00000004 +#define VC_REPORT_POSITION_IN_ENTITY 0x00000010 +#define VC_REPORT_ALL_ENTITIES 0x00000020 + +/* + * Flags to VCDestruct + */ + +#define VC_DESTRUCT_FORCE 0x00000001 +#define VC_DESTRUCT_ATTRIBUTES 0x00000002 +#define VC_DESTRUCT_CHILDREN 0x00000004 + +#define VC_RELOCATE_FIRST_REPORT 0x00000001 +#define VC_RELOCATE_ABSOLUTE 0x00000002 +#define VC_RELOCATE_RELATIVE 0x00000004 +#define VC_RELOCATE_LINKAGE_CHANGE 0x00000008 + +#define VC_HANDLED 0 +#define VC_NOT_HANDLED 1 + +#define VC_COLLISION_ENABLE 0x01 +/* +* Don't know what to do with this +#define VC_COLLISION_SOLID 0x02 +*/ +#define VC_COLLISION_HIERACHY_DISABLE 0x04 +#define VC_COLLISION_PICKABLE 0x08 +#define VC_COLLISION_PICKING 0x10 +#define VC_COLLISION_QUIET 0x20 +#define VC_COLLISION_INV_QUIET 0x40 + +#define VC_COLLISION_SIMPLE 0x000 +#define VC_COLLISION_RADIUS 0x100 +#define VC_COLLISION_GEOMETRY 0x200 +#define VC_COLLISION_BBOX 0x300 + +#define VC_COLLISION_MODE_MASK 0x300 + +#define VC_COLLISION_BOUNDS_VALID 0x400 +#define VC_COLLISION_ZONE 0x800 +#define VC_COLLISION_NO_POSITION 0x1000 +#define VC_COLLISION_NO_VECTOR 0x2000 +#define VC_COLLISION_NO_TIME 0x4000 + +#define VC_COLLISION_RETURN_MASK 0xf0000 +#define VC_COLLISION_RETURN_NONE 0x00000 +#define VC_COLLISION_RETURN_BBOX 0x10000 +#define VC_COLLISION_RETURN_RADIUS 0x20000 +#define VC_COLLISION_RETURN_VALID 0x100000 +#define VC_ATTRIBUTE_MODE_DONT_CACHE 0x000 +#define VC_ATTRIBUTE_MODE_CACHE 0x001 + +#define VC_AUDIORESOURCE_SPREADINGROLLOFF_VALID 0x00000010 +#define VC_AUDIORESOURCE_ATMOSPHERICABSORPTION_VALID 0x00000020 + +#define VC_AUDIO_ENABLE 0x01 +#define VC_AUDIO_ZONED 0x02 +#define VC_AUDIO_SPATIAL_OFF 0x04 + +#define VC_AUDIO_PRIORITY_LOCKED -1 +#define VC_AUDIO_MAX_PRIORITY 127 + + +#define VC_SENSOR_ENABLE 0x00000001 +#define VC_SENSOR_MODE_RELATIVE 0x00000002 +#define VC_SENSOR_FILTER_ENABLE 0x00000004 +#define VC_SENSOR_POSITION_SHARED 0x00000008 +#define VC_SENSOR_REPORT_MASK 0x000000f0 +#define VC_SENSOR_REPORT_NORMAL 0x00000010 +#define VC_SENSOR_REPORT_INTERPOLATE 0x00000020 +#define VC_SENSOR_REPORT_DEADRECKON_1 0x00000030 +#define VC_SENSOR_REPORT_DEADRECKON_2 0x00000040 +#define VC_SENSOR_REPORT_ENABLE 0x00000100 + +#define VC_MATERIAL_ENABLE 0x00000001 + +/* + * Value for texture mode + */ + +#define VC_TEXTURE_ENABLE 0x00000001 + +/* + * Values fot texture minify field + */ + +#define VC_TEXTURE_MIN_POINT_SAMPLED 0x01 +#define VC_TEXTURE_MIN_BILINEAR 0x02 +#define VC_TEXTURE_MIN_TRILINEAR 0x03 +#define VC_TEXTURE_MIN_MIP_MAP_POINT_SAMPLED 0x04 +#define VC_TEXTURE_MIN_MIP_MAP_LINEAR 0x05 +#define VC_TEXTURE_MIN_MIP_MAP_BILINEAR 0x06 +#define VC_TEXTURE_MIN_MIP_MAP_TRILINEAR 0x07 +#define VC_TEXTURE_MIN_MIP_MAP_QUADLINEAR 0x08 + +/* + * Values fot texture magnify field + */ + +#define VC_TEXTURE_MAG_POINT_SAMPLED 0x01 +#define VC_TEXTURE_MAG_BILINEAR 0x02 +#define VC_TEXTURE_MAG_TRILINEAR 0x03 +#define VC_TEXTURE_MAG_BICUBIC 0x04 +#define VC_TEXTURE_MAG_SHARPEN 0x05 + +/* + * Values fot texture alpha field + */ + +#define VC_TEXTURE_ALPHA_BLEND 0x01 +#define VC_TEXTURE_ALPHA_CUT 0x02 +#define VC_TEXTURE_ALPHA_BLEND_CUT 0x03 + +/* + * Values fot texture wrapu/wrapv fields + */ + +#define VC_TEXTURE_WRAP_REPEAT 0x00 +#define VC_TEXTURE_WRAP_CLAMP 0x01 +#define VC_TEXTURE_WRAP_SELECT 0x02 + +/* + * Values fot texture detailType field + */ +#define VC_TEXTURE_DETAIL_ADD 0x01 +#define VC_TEXTURE_DETAIL_MODULATE 0x02 + + + +/* + * Viz query status values + */ + +#define VC_VISUALQUERY_OK 0x00000001 +#define VC_VISUALQUERY_FAIL 0x00000002 + +#define VC_VISUALQUERY_MASK 0xffffff00 + +#define VC_VISUALQUERY_NO_SUBJECT 0x00000100 +#define VC_VISUALQUERY_NOT_FOUND 0x00000200 + +/* + * Viz query modes + */ + +#define VC_VISUALQUERY_OFF 0x00000000 +#define VC_VISUALQUERY_MATERIAL_NAMES 0x00000001 +#define VC_VISUALQUERY_TEXTURE_NAMES 0x00000002 +#define VC_VISUALQUERY_RAMP_NAMES 0x00000003 +#define VC_VISUALQUERY_LOD_NAMES 0x00000004 +#define VC_VISUALQUERY_PATCH_NAMES 0x00000005 +#define VC_VISUALQUERY_MATERIAL 0x00000006 +#define VC_VISUALQUERY_TEXTURE 0x00000007 +#define VC_VISUALQUERY_LOD 0x00000008 + +#define VC_VECTORINTERSECT_ENABLE 0x00000001 +#define VC_VECTORINTERSECT_REPORT_CONTINUOUS 0x00000002 +#define VC_VECTORINTERSECT_REPORT_RELATIVE 0x00000004 + +#define VC_VISUALEFFECT_ENABLE 0x0001 +#define VC_VISUALEFFECT_MODE_MASK 0x0ff0 +#define VC_VISUALEFFECT_MODE_EXPLOSION 0x0010 + + +#define VC_VERBOSE 0x00010000 +#define VC_VERBOSE_MATSPLIT 0x00020000 +#define VC_ZONE_ALL_ACTORS -1 +#define VC_ZONE_VISUAL 0x00000001 +#define VC_ZONE_COLLIDE 0x00000002 +#define VC_ZONE_PHYSICS 0x00000004 +#define VC_ZONE_AUDIO 0x00000008 +#define VC_ZONE_BODY 0x00000010 + +#define VC_ZONE_ENABLE_MASK 0x0000000F +#define VC_ZONE_ENABLED 0x00000000 +#define VC_ZONE_DISABLED 0x00000001 + +/* + * turn on things in a VCDynamics + */ +#define VC_DYNAMICS_ENABLE 0x00000001 +#define VC_DYNAMICS_INERTIA_MASK 0x6 +#define VC_DYNAMICS_INERTIA_POINT_MASS 0x2 +#define VC_DYNAMICS_INERTIA_DISTRIBUTED_MASS 0x4 + +#define VC_DYNAMICS_BOUNCE_MASK 0x00000018 +#define VC_DYNAMICS_BOUNCE_DISBALED 0 +#define VC_DYNAMICS_BOUNCE_SIMPLE 0x00000008 +#define VC_DYNAMICS_BOUNCE_COMPLEX 0x00000010 + +#define VC_DYNAMICS_GRAVITATIONAL_MASS 0x00000020 + + +/* + * indecies into arrays of + * values from an inertial tensor + */ +#define VC_I_XX 0 +#define VC_I_YY 1 +#define VC_I_ZZ 2 +#define VC_I_XY 3 +#define VC_I_YZ 4 +#define VC_I_XZ 5 + +/* + * turn on a VCForce as a force or pure torque (mutually exclusive). + * define whether it acts in local coordinante space (default) + * or world coordinate space. + */ +#define VC_FORCE_MODE_MASK 0x00000003 + +#define VC_FORCE_FORCE 0x00000001 +#define VC_FORCE_TORQUE 0x00000002 +#define VC_FORCE_WCS 0x00000004 +/* + * enable a pseudo-gravitational field + */ +#define VC_PSEUDO_GRAVITY_ENABLE 0x00000001 + +#define VC_LOD_ENABLE 0x000000001 +#define VC_LOD_DYNAMIC 0x000000002 + +#define VC_GEOGROUP_ENABLE 0x00000001 +#define VC_GEOGROUP_DYNAMIC 0x00000002 + +#define VC_GEOGROUP_VERTEX_ONLY 0x00000000 +#define VC_GEOGROUP_VERTEX_NORMALS 0x00000001 +#define VC_GEOGROUP_VERTEX_RGBA 0x00000002 +#define VC_GEOGROUP_VERTEX_LUMINANCE 0x00000004 +#define VC_GEOGROUP_VERTEX_2D_TEXTURE 0x00000008 +#define VC_GEOGROUP_VERTEX_3D_TEXTURE 0x00000010 +#define VC_GEOGROUP_VERTEX_RADIUS 0x00000020 + +#define VC_GEOGROUP_DRAWMODE_SOLID 0x00000000 +#define VC_GEOGROUP_DRAWMODE_WIREFRAME 0x00000001 +#define VC_GEOGROUP_DRAWMODE_DOTTED 0x00000002 + +#define VC_GEOGROUP_LOCK_OFF 0x00000000 +#define VC_GEOGROUP_LOCK_ON 0x00000001 + +#define VC_GEOMETRY_ENABLE 0x00000040 +#define VC_GEOMETRY_TYPE_MASK 0x0000003f + +#define VC_GEOMETRY_TYPE_TRISTRIP 0x00000000 +#define VC_GEOMETRY_TYPE_POLYSTRIP 0x00000001 +#define VC_GEOMETRY_TYPE_POLYGON 0x00000002 +#define VC_GEOMETRY_TYPE_LINE 0x00000003 +#define VC_GEOMETRY_TYPE_SPHERELIST 0x00000004 +#define VC_GEOMETRY_TYPE_PMESH 0x00000005 +#define VC_GEOMETRY_TYPE_TEXT 0x00000006 + +#define VC_GEOMETRY_SPHERELIST_DICE_U 0xfff00000 +#define VC_GEOMETRY_SPHERELIST_DICE_U_SHIFT 20 +#define VC_GEOMETRY_SPHERELIST_DICE_V 0x000fff00 +#define VC_GEOMETRY_SPHERELIST_DICE_V_SHIFT 8 + +#define VC_GEOMETRY_LINE_THICKNESS 0x0000ff00 +#define VC_GEOMETRY_LINE_THICKNESS_SHIFT 8 + +#define VC_CONNECTION_PCOUNT_SHIFT 8 +#define VC_CONNECTION_PCOUNT_MASK 0x0000ff00 + +#define VC_GROUP_START 0 +#define VC_GROUP_END 1 + +#define VC_RAMP_ENABLE 0x00000001 + + +#define VC_INPUTRESOURCE_ENABLE 0x00000001 + + + +#define VC_CACHEMODE_DEFAULT 0 +#define VC_CACHEMODE_DO_CACHE 1 +#define VC_CACHEMODE_DONT_CACHE 2 + + +#define VC_DEBUG_HARCHY 0x00020000 +#define VC_DEBUG_HARCHY_EXTRA 0x00040000 +#define VC_DEBUG_RESOURCE 0x00080000 +#define VC_DEBUG_ENTITY 0x00100000 +#define VC_DEBUG_PICK 0x00200000 +#define VC_DEBUG_BODY_TRAVERSE 0x00400000 +#define VC_DEBUG_ATTRIBUTE 0x00800000 +#define VC_DEBUG_INPUT 0x01000000 +#define VC_DEBUG_TIMER 0x02000000 +#define VC_DEBUG_BODY_RESOURCE 0x04000000 + +#if defined (_TRANSPUTER) || defined (_IRIX) +#define VCWARNING(x) VC_Warn ( #x" at line %d of %s\n",__LINE__, __FILE__) + +#else +#define VCWARNING(x) {int WARNING = #x; \ + VC_Warn ( #x" at line %d of %s\n",__LINE__, __FILE__);} +#endif + +#define VCAwaitEvent(a,m) {_VCDoneWaitEvent = 1;VLAwaitEvent(a,m); } + + diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCDTYPES.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDTYPES.H new file mode 100644 index 0000000..d616acc --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDTYPES.H @@ -0,0 +1,394 @@ +/*************************************************************************** + * + * PROJECT: dVS + * SUBSYSTEM: VC Toolkit. + * MODULE: VC Type definitions. + * + *************************************************************************** + * + * File: $RCSfile: vctypes.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:11 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctypes.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * + * FUNCTION: + * + * + * + ************************************************************************** + * * + * Copyright (c) 1995 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +#ifndef _VCDTYPES_H +#define _VCDTYPES_H +typedef float32 VCColour[3]; + +#define VCColor VCColour /* For our American Friends !! */ +typedef struct +{ + uint32 secs; + uint32 uSecs; +}VCTime; + +typedef struct +{ + dmPosition dmPos; + uint32 mode; +}VCPositionData; + +typedef struct +{ + uint32 mode; + float32 frameRate; + float32 iod; + float32 convergence; + VCColour background; + float32 nearClip; + float32 farClip; + VCColour fogColour; + float32 nearFog; + float32 farFog; + float32 lodScale; + uint32 actorId; + char *name; +}VCVisualResourceData; + +typedef struct +{ + VCAttribute *visualResource; + uint32 mode; + dmPoint offset; + dmEuler orientation; + float32 size[2]; + char *name; +} VCVisualViewResourceData; + + +typedef struct +{ + uint32 mode; + uint32 flags; + float32 translation[6]; + float32 rotation[6]; +} VCConstraintsData; + +typedef struct +{ + uint32 mode; + VCInput *input; + char *name; +}VCInputResourceData; + +typedef struct { + uint32 mode; + VCTracker *tracker; + uint32 sensorId; + float32 translationScale[3]; + float32 rotationScale[3]; + float32 rotationCurveOrder[3]; + float32 translationCurveOrder[3]; + dmPoint prePosition; + dmPoint postPosition; + dmEuler preEuler; + dmEuler postEuler; + float32 relativeSphere[6]; + VCPosition *position; + VCConstraintsData constraints; + char *name; +} VCSensorResourceData; + +typedef struct +{ + uint32 updateRate; + uint32 transmissionDelay; + dmPoint sourcePosition; + dmEuler sourceEuler; + uint32 baudRate; + char *deviceType; + char *name; +}VCTrackerData; + + +typedef struct +{ + uint32 mode; + VCColour colour; + float32 exponent; + float32 theta; +}VCLightData; + +typedef struct +{ + uint32 mode; + uint32 intersectMask; + VCDynamicVisual *dynamicVisual; + char *geometryName; + char *frontMaterial; + char *backMaterial; + char *lod; +} VCVisualData; + +typedef struct +{ + VCAttribute *boundaryAttr; + uint16 flags; + dmPoint point; + dmVector direction; + VCTime time; +} VCCollisionReportData; + +typedef struct +{ + VCAttribute *boundary; + uint32 numberCollisions; + uint32 numberReportedCollisions; + VCCollisionReportData *collReportData; +}VCCollisionData; + +typedef struct +{ + float32 bound[VC_BOUND_SIZE]; + uint32 mode; + int32 numberCollisions; + VCCollision *collision; + VCDynamicVisual *dynamicVisual; + char *geometry; + char *lod; +}VCBoundaryData; + +typedef struct +{ + VCEntity *entity; + VCAttribute *visual; + InstanceNo patch; + dmPoint point; +}VCIntersectionReportData; + +typedef struct +{ + VCAttribute *vectorIntersect; + uint32 numberIntersections; + uint32 numberReportedIntersections; + VCIntersectionReportData *collReportData; +}VCIntersectionData; + +typedef struct +{ + uint32 mode; + float32 length; + uint32 intersectMask; + int32 numberIntersections; + VCIntersection *intersection; +}VCVectorIntersectData; + + + + +typedef struct +{ + uint32 mode; + int32 loopCount; + float32 gain; + uint16 play; + uint8 velocity; + int8 priority; + char *voice; + char *radiatorName; + char *radiatorFileName; +} VCAudioData; + +typedef struct +{ + uint32 mode; + float32 iad; + float32 volume; + float32 spreadingRollOff; + float32 atmosphericAbsorption; + float32 worldScale; + char *name; + char *hrtf; + char *resourceFile; +} VCAudioResourceData; + +typedef struct +{ + VCEntity *pickEntity; + uint32 mode; + uint32 pickActorId; +}VCPickObjectData; + +typedef struct +{ + uint32 mode; + VCColour ambient; + VCColour diffuse; + VCSpecular specular; + VCColour emissive; + VCColour opacity; + char *name; + char *textureName; + char *ramp; +} VCMaterialData; + +typedef struct +{ + uint32 mode; + uint8 minify; + uint8 magnify; + uint8 alpha; + uint8 wrapU; + uint8 wrapV; + uint8 detailType; + char *name; + char *textureMap; + char *detailMap; +} VCTextureData; + +typedef struct +{ + uint32 actorId; + char *name; + uint32 numAliases; + char **aliases; +} VCBodyPartData; + +typedef struct +{ + char8 *name; + int32 numPoints; + float32 points[VC_RADIATOR_MAX_POINTS]; +} VCRadiatorData; + +typedef struct +{ + uint32 mode; + uint32 type; + dmPoint offset; + float32 info[72]; + char *texture; +}VCVisualEffectData; + +typedef struct +{ + uint32 mode; + uint32 actorMask; +}VCZoneData; + +typedef struct +{ + uint32 mode; + float32 iMass; + float32 gMass; + dmPoint centre; + float32 iTensor[6]; + float32 spring; + float32 damper; + float32 staticFriction; + float32 dynamicFriction; +}VCDynamicsData; + +typedef struct +{ + uint32 mode; + dmVector force; + dmPoint point; +} VCForceData; + +typedef struct +{ + uint32 windowId; + char *serverName; + char *actorName; +} VCXWindowIdData; + +typedef struct +{ + uint32 mode; + dmVector direction; + float32 gravity; +}VCPseudoGravityData; + + +typedef struct +{ + float32 slow_speed; + float32 fast_speed; + float32 acceleration; + float32 max_speed; + uint32 slow_key; + uint32 fast_key; + uint32 accelerate_key; +}VCBodyFlyInfoData; + +typedef struct +{ + uint32 actorId; + VCEntity *bodyRoot; + VCEntity *bodyPosEntity; + VCBodyFlyInfoData fly_forward; + VCBodyFlyInfoData fly_backward; + VCBodyFlyInfoData fly_up; + VCBodyFlyInfoData fly_down; + VCBodyFlyInfoData fly_left; + VCBodyFlyInfoData fly_right; + VCBodyFlyInfoData rot_left; + VCBodyFlyInfoData rot_right; + VCBodyFlyInfoData rot_up; + VCBodyFlyInfoData rot_down; + uint32 verticalFly_key; + uint32 altFly_key; + VCEntity *flyDirectionLimb; + VCEntity *altFlyDirectionLimb; + VCEntity *altFlyLimb; + uint32 flyMode; + char *name; + char *user; + char *role; +} VCBodyData; + +typedef struct +{ + float32 objectInRate; + float32 objectInActive; + float32 objectTests; + char *name; +}VCCollideMonitorData; + +typedef struct +{ + float32 sensorRate[VC_MAX_SENSORS]; + int sensorBaseNumber; + char *name; +}VCTrackerMonitorData; + +typedef struct +{ + float32 headUpdateRate; /* No updates / second */ + float32 geometryUpdates; /* No updates / second */ + float32 frameRate; /* No frames drawn/second */ + float32 drawRate; /* Tri's per second */ + char8 *name; /* Name of the actor. */ +}VCVisualMonitorData; + +typedef struct +{ + uint32 mode; + VCColour minRgb; + VCColour maxRgb; + char* name; +} VCRampData; + +#endif + + + diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCDYNAM.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDYNAM.H new file mode 100644 index 0000000..24e4ba6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCDYNAM.H @@ -0,0 +1,538 @@ +/*************************************************************************** + * + * PROJECT: dVS + * SUBSYSTEM: VC Toolkit. + * MODULE: VC Type definitions (dynamic geometry). + * + *************************************************************************** + * + * File: $RCSfile: vcdynam.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:12 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcdynam.h,v 1.1 1995/03/10 14:52:46 steve Exp $ + * + * FUNCTION: + * + * + * + ************************************************************************** + * * + * Copyright (c) 1992 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +#ifndef _VCDYNTYPES_H +#define _VCDYNTYPES_H + +/* defines */ + + +/* typedefs */ + +typedef struct VCDynamicVisual_CallbackData VCDynamicVisual_CallbackData; +typedef void (*VCDynamicVisual_Func) (VCDynamicVisual_CallbackData *attributeData, void *data); +typedef struct VCLod_CallbackData VCLod_CallbackData; +typedef void (*VCLod_Func) (VCLod_CallbackData *attributeData, void *data); +typedef struct VCGeogroup_CallbackData VCGeogroup_CallbackData; +typedef void (*VCGeogroup_Func) (VCGeogroup_CallbackData *attributeData, void *data); +typedef struct VCGeometry_CallbackData VCGeometry_CallbackData; +typedef void (*VCGeometry_Func) (VCGeometry_CallbackData *attributeData, void *data); +typedef struct VCText_CallbackData VCText_CallbackData; +typedef void (*VCText_Func) (VCText_CallbackData *attributeData, void *data); +typedef struct VCConnectionList_CallbackData VCConnectionList_CallbackData; +typedef void (*VCConnectionList_Func) (VCConnectionList_CallbackData *attributeData, void *data); + + +typedef struct VCDynamicVisual_Traverse VCDynamicVisual_Traverse; +typedef struct VCLod_Traverse VCLod_Traverse; +typedef struct VCGeogroup_Traverse VCGeogroup_Traverse; +typedef struct VCGeometry_Traverse VCGeometry_Traverse; + +typedef enum { + VC_GEOMETRY_ALL=0x10, + VC_SPHERELIST=VC_GEOMETRY_TYPE_SPHERELIST, + VC_TRISTRIP=VC_GEOMETRY_TYPE_TRISTRIP, + VC_POLYSTRIP=VC_GEOMETRY_TYPE_POLYSTRIP, + VC_POLYGON=VC_GEOMETRY_TYPE_POLYGON, + VC_STRING=VC_GEOMETRY_TYPE_TEXT, + VC_VECTOR=VC_GEOMETRY_TYPE_LINE, + VC_PMESH=VC_GEOMETRY_TYPE_PMESH +} VCGeometry_Type; + +typedef enum { + VC_VERTEX_ALL = 0xff, + VC_VERTEX_XYZ = VC_GEOGROUP_VERTEX_ONLY, + VC_VERTEX_N =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_NORMALS), + VC_VERTEX_RGBA =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_RGBA), + VC_VERTEX_LA =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_LUMINANCE), + VC_VERTEX_UV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_UVW =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_3D_TEXTURE), + VC_VERTEX_NUV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_NORMALS | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_RGBAUV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_RGBA | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_LAUV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_LUMINANCE | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_SPHERE =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_RADIUS) +} VCVertex_Type; + +typedef float VCVertexXYZ[3]; +typedef float VCVertexN[6]; +typedef float VCVertexRGBA[7]; +typedef float VCVertexLA[5]; +typedef float VCVertexUV[5]; +typedef float VCVertexUVW[6]; +typedef float VCVertexNUV[8]; +typedef float VCVertexRGBAUV[9]; +typedef float VCVertexLAUV[7]; +typedef float VCVertexSphere[4]; + +typedef float *VCVertex; +typedef uint32 *VCConnection; + +typedef void (*VCDynamicVisual_TraverseFunc) (VCDynamicVisual *item, void *data); +typedef void (*VCLod_TraverseFunc) (VCLod *item, void *data); +typedef void (*VCGeogroup_TraverseFunc) (VCGeogroup *item, void *data); +typedef void (*VCGeometry_TraverseFunc) (VCGeometry *item, void *data); + +/* structures */ + +typedef struct { + uint32 faceCount; + uint32 noConnections; + VCConnection data; +} VCConnectionData; + +typedef struct { + VCConnectionList *connection; + int currentIndex, size, total, currentConnection; + VCConnectionData *connectData; + VCConnection data; +} VCConnection_Reference; + +typedef struct { + VCGeometry *geometry; + int currentIndex, size; + float distance; + VCVertex data; +} VCVertex_Reference; + +typedef struct { + float min[3]; + float max[3]; + float center[3]; +} VCGeometry_BoundBox; + +struct VCDynamicVisual +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCLod *lod; /* pointer to child LOD */ + void *octreeData; /* for future expansion */ + VCAttribute *attribute; /* pointer to parent */ + +}; + +struct VCLod +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCLod *next; /* LODs implemented as linked list */ + VCGeogroup *geogroup; /* pointer to child geogroup */ + void *octreeData; /* for future expansion */ + struct VCDynamicVisual *dvisual; /* pointer to parent */ + +}; + +struct VCGeogroup +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCGeogroup *next; /* GEOGROUPs implemented as linked list */ + VCGeometry *geometry; /* pointer to child geometry */ + void *octreeData; /* for future expansion */ + VCGeometry_BoundBox *boundingBox; /* define extents of attached geometry */ + VCLod *lod; /* pointer to parent */ + VCVertex_Type vertexFormat; /* copy of geogroup setting */ + +}; + +struct VCGeometry +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCGeometry *next; /* GEOMETRY implemented as linked list */ + void *octreeData; /* for future expansion */ + VCGeogroup *geogroup; /* pointer to parent */ + + VCGeometry_Type type; /* used to extract instanceData */ + VCVertex_Type vertexFormat; /* copy of geogroup setting */ + VCGeometry_BoundBox *boundingBox; /* define extents of attached geometry */ + VCConnectionList *connectionList; /* linked list for Pmeshes */ + +}; + +struct VCConnectionList +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCConnectionData *connectData; + VCGeometry *geometry; /* pointer to parent */ + +}; + +struct VCDynamicVisual_CallbackData { + VCDynamicVisual *dvisual; +}; + +struct VCLod_CallbackData { + VCLod *lod; +}; + +struct VCGeogroup_CallbackData { + VCGeogroup *geogroup; +}; + +struct VCGeometry_CallbackData { + VCGeometry *geometry; +}; + +struct VCText_CallbackData { + VCGeometry *geometry; +}; + +struct VCConnectionList_CallbackData { + VCConnectionList *connectionList; + VCGeometry *geometry; +}; + +struct VCDynamicVisual_Traverse { + VCDynamicVisual *dvisual; + VCLod *current; +}; + +struct VCLod_Traverse { + VCLod *lod; + VCGeogroup *current; + VCVertex_Type search; +}; + +struct VCGeogroup_Traverse { + VCGeogroup *geogroup; + VCGeometry *current; + VCGeometry_Type search; +}; + +struct VCGeometry_Traverse { + VCGeometry *geometry; + VCConnectionList *current; +}; + + +/* macros */ + + +#define VCSphereList_Delete(g) VCGeometry_Delete(g) +#define VCSphereList_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCSphereList_Flush(g) VCGeometry_Flush(g) +#define VCSphereList_Create(n,v) VCGeometry_Create(VC_SPHERELIST, \ + VC_VERTEX_SPHERE,n,v,0,NULL) +#define VCGeogroup_AddSphereList(g, n,v) VCGeogroup_AddGeometry(g, \ + VC_SPHERELIST,\ + VC_VERTEX_SPHERE,n,v,0,NULL) + +#define VCPolystrip_Delete(g) VCGeometry_Delete(g) +#define VCPolystrip_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCPolystrip_Flush(g) VCGeometry_Flush(g) +#define VCPolystrip_Create(t,n,v) VCGeometry_Create(VC_POLYSTRIP, \ + t,n,v,0,NULL) +#define VCGeogroup_AddPolystrip(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_POLYSTRIP,\ + t,n,v,0,NULL) + +#define VCTristrip_Delete(g) VCGeometry_Delete(g) +#define VCTristrip_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCTristrip_Flush(g) VCGeometry_Flush(g) +#define VCTristrip_Create(t,n,v) VCGeometry_Create(VC_TRISTRIP, \ + t,n,v,0,NULL) +#define VCGeogroup_AddTristrip(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_TRISTRIP,\ + t,n,v,0,NULL) + +#define VCPolygon_Delete(g) VCGeometry_Delete(g) +#define VCPolygon_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCPolygon_Flush(g) VCGeometry_Flush(g) +#define VCPolygon_Create(t,n,v) VCGeometry_Create(VC_POLYGON, \ + t,n,v,0,NULL) +#define VCGeogroup_AddPolygon(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_POLYGON,\ + t,n,v,0,NULL) + +#define VCVector_Delete(g) VCGeometry_Delete(g) +#define VCVector_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCVector_Flush(g) VCGeometry_Flush(g) +#define VCVector_Create(t,n,v) VCGeometry_Create(VC_VECTOR, \ + t,n,v,0,NULL) +#define VCGeogroup_AddVector(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_VECTOR,\ + t,n,v,0,NULL) + +#define VCPmesh_Delete(g) VCGeometry_Delete(g) +#define VCPmesh_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCPmesh_FlushVertexList(g) VCGeometry_Flush(g) +#define VCPmesh_Create(t,n,v,c,l) VCGeometry_Create(VC_PMESH, \ + t,n,v,c,l) +#define VCGeogroup_AddPmesh(g,t,n,v,c,l) VCGeogroup_AddGeometry(g, \ + VC_PMESH,\ + t,n,v,c,l) + +#define VCString_Delete(g) VCText_Delete(g) +#define VCString_Create(s,f,p,o,c) VCText_Create(s,-1,f,p,o,c) +#define VCString_CreateSized(s,z,f,p,o,c) VCText_Create(s,z,f,p,o,c) +#define VCGeogroup_AddString(g,s,z,f,p,o,c) VCGeogroup_AddText(g,s,z,f,p,o,c) +#define VCString_SetMode(g,m) VCText_ModifyMode(g,m,0) +#define VCString_ModifyMode(g,m,c) VCText_ModifyMode(g,m,c) +#define VCString_GetMode(g,m) VCText_GetMode(g,m) +#define VCString_GetFont(g,m) VCText_GetFont(g,m) +#define VCString_GetText(g,m) VCText_GetText(g,m) +#define VCString_GetPositionOrientationScale(g,p,o,s) VCText_GetPositionOrientationScale(g,p,o,s) +#define VCString_SetFont(g,m) VCText_SetFont(g,m) +#define VCString_SetText(g,m) VCText_SetText(g,m) +#define VCString_SetPositionOrientationScale(g,p,o,s) VCText_SetPositionOrientationScale(g,p,o,s) + +#define VCGeogroup_AttachPmesh(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachTristrip(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachPolystrip(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachPolygon(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachVector(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachString(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachSphereList(g,p) VCGeogroup_AttachGeometry(g,p) + +#define VCGeogroup_DetachPmesh(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachTristrip(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachPolystrip(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachPolygon(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachVector(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachString(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachSphereList(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCEntity_AddDynamicVisual(e,v,f,b) VCEntity_AddVisual(e, NULL, v, \ + VC_VISIBLE | VC_RMODE_POLYGONAL, NULL, f, b, 0xffffffff) + +/* prototypes */ +VCDynamicVisual *VCDynamicVisual_Create(char *, uint32); +VCLod *VCDynamicVisual_AddLod(VCDynamicVisual *, char *, float, float, dmPoint); +int VCDynamicVisual_AttachLod(VCDynamicVisual *, VCLod *); +int VCDynamicVisual_DetachLod(VCDynamicVisual *, VCLod *); +VCLod *VCDynamicVisual_GetFirstLod(VCDynamicVisual *item, VCDynamicVisual_Traverse *trv); +VCLod *VCDynamicVisual_GetNextLod(VCDynamicVisual_Traverse *trv); +VCLod *VCDynamicVisual_GetIndexedLod(VCDynamicVisual *item, int index, + VCDynamicVisual_Traverse *trv); +VCLod *VCDynamicVisual_GetNamedLod(VCDynamicVisual *item, char *name, + VCDynamicVisual_Traverse *trv); +int VCDynamicVisual_ApplyPerLod(VCDynamicVisual *item, VCLod_TraverseFunc func, + void *data); +int VCDynamicVisual_ApplyPerGeogroup(VCDynamicVisual *item, VCGeogroup_TraverseFunc func, + void *data); +int VCDynamicVisual_ApplyPerGeometry(VCDynamicVisual *item, VCGeometry_TraverseFunc func, + void *data); +int VCDynamicVisual_GetNearestVertex(VCDynamicVisual *, dmPoint, float, + VCVertex_Reference *); + +VCLod *VCLod_Create(char *, float, float, dmPoint); +int VCLod_Get(VCLod *, char **, float *in, float *out, dmPoint reference); +int VCLod_Set(VCLod *lod, char *, float *in, float *out, dmPoint reference); +int VCLod_SetInOutDistance(VCLod *lod, float in, float out); +int VCLod_SetReference(VCLod *lod, dmPoint reference); +int VCLod_SetName(VCLod *lod, char *); +int VCLod_GetName(VCLod *lod, char **); +int VCLod_GetInOutDistance(VCLod *lod, float *in, float *out); +int VCLod_GetReference(VCLod *lod, dmPoint reference); +int VCLod_GetMode(VCLod *, uint32 *mode); +int VCLod_ModifyMode(VCLod *, uint32 setMode, uint32 clearMode); +int VCLod_AttachLod(VCLod *lod, VCLod *child); +int VCLod_DetachLod(VCLod *lod, VCLod *child); +int VCLod_AttachGeogroup(VCLod *lod, VCGeogroup *geogroup); +int VCLod_DetachGeogroup(VCLod *lod, VCGeogroup *geogroup); +VCGeogroup *VCLod_AddGeogroup(VCLod *lod, + VCVertex_Type, uint32, uint8, uint8, uint8, uint8, + char *, char *); +VCGeogroup *VCLod_GetFirstGeogroup(VCLod *lod, VCVertex_Type search, + VCLod_Traverse *traverse); +VCGeogroup *VCLod_GetNextGeogroup(VCLod_Traverse *traverse); +int VCLod_GetNearestVertex(VCLod *lod, dmPoint point, float dist, + VCVertex_Reference *ref); +int VCLod_ApplyPerGeogroup(VCLod *lod, VCGeogroup_TraverseFunc func, + void *data); +int VCLod_ApplyPerGeometry(VCLod *lod, VCGeometry_TraverseFunc func, + void *data); + + +VCGeogroup *VCGeogroup_Create(VCVertex_Type, uint32, uint8, uint8, uint8, uint8, + char *, char *); +int VCGeogroup_Get(VCGeogroup *group, VCVertex_Type *format, + uint32 *decal, uint8 *faceted, uint8 *lock, + uint8 *drawMode, uint8 *drawWidth, + char **fmat, char **bmat); +int VCGeogroup_Set(VCGeogroup *group, + uint32 *decal, uint8 *faceted, uint8 *lock, + uint8 *drawMode, uint8 *drawWidth, + VCVertex_Type *format, char *fmat, char *bmat); +int VCGeogroup_SetFrontMaterial(VCGeogroup *group, char *fmat); +int VCGeogroup_SetBackMaterial(VCGeogroup *group, char *bmat); +int VCGeogroup_SetMaterialAll(VCGeogroup *group, char *fmat, char *bmat); +int VCGeogroup_SetVertexFormat(VCGeogroup *group, VCVertex_Type format); +int VCGeogroup_SetMode(VCGeogroup *group, uint32 mode); +int VCGeogroup_ModifyMode(VCGeogroup *group, uint32 setMode, uint32 clearMode); +int VCGeogroup_GetMode(VCGeogroup *group, uint32 *mode); +int VCGeogroup_GetFrontMaterial(VCGeogroup *group, char **fmat); +int VCGeogroup_GetBackMaterial(VCGeogroup *group, char **bmat); +int VCGeogroup_GetMaterialAll(VCGeogroup *group, char **fmat, char **bmat); +int VCGeogroup_GetVertexFormat(VCGeogroup *group, VCVertex_Type *format); +int VCGeogroup_AttachGeometry(VCGeogroup *geogroup, VCGeometry *geometry); +int VCGeogroup_DetachGeometry(VCGeogroup *geogroup, VCGeometry *geometry); +VCGeometry *VCGeogroup_GetFirstGeometry(VCGeogroup *geogroup, VCGeometry_Type search, + VCGeogroup_Traverse *traverse); +VCGeometry *VCGeogroup_GetNextGeometry(VCGeogroup_Traverse *traverse); +int VCGeogroup_SetBoundBox(VCGeogroup *geogroup, VCGeometry_BoundBox *bbox); +int VCGeogroup_GetNearestVertex(VCGeogroup *geogroup, dmPoint point, float dist, + VCVertex_Reference *ref); +int VCGeogroup_ApplyPerGeometry(VCGeogroup *group, VCGeometry_TraverseFunc func, + void *data); + +VCGeometry *VCGeometry_Create(VCGeometry_Type, VCVertex_Type, uint32, VCVertex, + uint32, VCConnectionData *); +int VCGeometry_Get(VCGeometry *geometry, uint32 *mode, uint32 *noVertices); +int VCGeometry_Set(VCGeometry *geometry, uint32 setMode, uint32 clearMode, + uint32 noVertices, VCVertex data); +int VCPmesh_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCPmesh_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCTristrip_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCTristrip_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCPolystrip_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCPolystrip_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCPolygon_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCPolygon_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCVector_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCVector_SetThickness(VCGeometry *geometry, uint32 thickness); +int VCVector_GetThickness(VCGeometry *geometry, uint32 *thick); +int VCVector_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCSphereList_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCSphereList_SetDicingHints(VCGeometry *geometry, uint32 dice_u, uint32 dice_v); +int VCSphereList_GetDicingHints(VCGeometry *geometry, uint32 *dice_u, uint32 *dice_v); +int VCSphereList_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCGeometry_Modify(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCGeometry_Flush(VCGeometry *geometry); +int VCGeometry_AttachConnectionList(VCGeometry *geom, VCConnectionList *connect); +int VCGeometry_GetFirstVertex(VCGeometry *geometry, VCVertex_Reference *ref); +int VCGeometry_GetNextVertex(VCVertex_Reference *ref); +int VCGeometry_GetIndexedVertex(VCGeometry *geometry, uint32 index, + VCVertex_Reference *ref); +VCConnectionList *VCGeometry_GetFirstConnectionList(VCGeometry *geometry, + VCGeometry_Traverse *traverse); +VCConnectionList *VCGeometry_GetNextConnectionList(VCGeometry_Traverse *traverse); +int VCGeometry_SetBoundBox(VCGeometry *geometry, VCGeometry_BoundBox *box); +int VCGeometry_GetNearestVertex(VCGeometry *geometry, dmPoint point, float dist, + VCVertex_Reference *ref); + +VCGeometry *VCText_Create(char *, uint32, uint8, dmPoint, dmEuler, dmScale); +int VCText_ModifyMode(VCGeometry *geometry, uint32 setMode, uint32 clearMode); +int VCText_Set(VCGeometry *geometry, uint8 *font, dmPoint pos, + dmEuler orient, dmScale scale, char *text); +int VCText_Get(VCGeometry *geometry, uint8 *font, dmPoint pos, dmEuler orient, + dmScale scale, char **text); +int VCText_GetMode(VCGeometry *geometry, uint32 *mode); +int VCText_SetFont(VCGeometry *geometry, uint8 font); +int VCText_SetPositionOrientationScale(VCGeometry *geometry, dmPoint pos, + dmEuler orient, dmScale scale); +int VCText_SetText(VCGeometry *geometry, char *text); +int VCText_GetFont(VCGeometry *geometry, uint8 *font); +int VCText_GetPositionOrientationScale(VCGeometry *geometry, dmPoint pos, + dmEuler orient, dmScale scale); +int VCText_GetText(VCGeometry *geometry, char **text); + +VCConnectionList *VCConnectionList_Create(uint32, VCConnectionData *); +int VCConnectionList_Get(VCConnectionList *connect, uint32 *noConnections, VCConnectionData **); +VCConnectionList *VCPmesh_AddConnectionList(VCGeometry *, uint32, VCConnectionData *); +int VCConnectionList_GetFirstConnection(VCConnectionList *connect, + VCConnection_Reference *ref); +int VCConnectionList_GetNextConnection(VCConnection_Reference *ref); +int VCPmesh_GetConnectionData(VCGeometry *, uint32 *, VCConnectionData **); +int VCPmesh_GetFirstConnection(VCGeometry *, VCConnection_Reference *); +int VCPmesh_GetNextConnection(VCConnection_Reference *); + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCELEMEN.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCELEMEN.H new file mode 100644 index 0000000..f809685 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCELEMEN.H @@ -0,0 +1,840 @@ +/* + * WARNING: machine generated code. + * + * do NOT edit this file, edit the + * original '.epp' file and regenerate this + * one. + */ + +#ifndef ____VCELEMEN_H +#define ____VCELEMEN_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Instance number access macros. + */ +#define VL_VCObjectPosition_vcPos_ino(x) ((x)+1) +#define VL_VCObjectPosition_parent_ino(x) ((x)+2) +#define VL_VCObject_pos_ino(x) ((x)+1) +#define VL_VCObject_pos_vcPos_ino(x) ((x)+2) +#define VL_VCObject_pos_parent_ino(x) ((x)+3) +#define VL_VCObject_attributes_ino(x) ((x)+4) +#define VL_VCGeometry_header_ino(x) ((x)+1) +#define VL_VCGeometry_vertices_ino(x) ((x)+2) +#define VL_VCText_header_ino(x) ((x)+1) +#define VL_VCText_text_ino(x) ((x)+2) +#define VL_VCConnectionList_header_ino(x) ((x)+1) +#define VL_VCConnectionList_connections_ino(x) ((x)+2) + + + +/* + * Generated function declarations. + */ +extern int32 ModuleVCInit ( void ); + +extern InstanceNo (VLCreateVCTime)(VCTime *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDeleteVCTime)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdateVCTime)(InstanceNo ino, VCTime *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtractVCTime)(InstanceNo ino , VCTime *data, VLTime *utime); + +extern InstanceNo (VLCreateVCColour)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDeleteVCColour)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdateVCColour)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtractVCColour)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCPosition)(_VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCPosition)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCPosition)(InstanceNo ino, _VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCPosition)(InstanceNo ino , _VCPosition *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCObjectPosition)(_VCObjectPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCObjectPosition)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCObjectPosition)(InstanceNo ino, _VCObjectPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObjectPosition)(InstanceNo ino , _VCObjectPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObjectPosition_vcPos)(InstanceNo ino, _VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObjectPosition_vcPos)(InstanceNo ino , _VCPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObjectPosition_parent)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObjectPosition_parent)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCObject)(_VCObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCObject)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCObject)(InstanceNo ino, _VCObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject)(InstanceNo ino , _VCObject *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_pos)(InstanceNo ino, _VCObjectPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_pos)(InstanceNo ino , _VCObjectPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_pos_vcPos)(InstanceNo ino, _VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_pos_vcPos)(InstanceNo ino , _VCPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_pos_parent)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_pos_parent)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_attributes)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_attributes)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConstraints)(_VCConstraints *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCConstraints)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConstraints)(InstanceNo ino, _VCConstraints *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCConstraints)(InstanceNo ino , _VCConstraints *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCZone)(_VCZone *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCZone)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCZone)(InstanceNo ino, _VCZone *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCZone)(InstanceNo ino , _VCZone *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualMonitor)(_VCVisualMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualMonitor)(InstanceNo ino, _VCVisualMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualMonitor)(InstanceNo ino , _VCVisualMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConfigRequest)(_VCConfigRequest *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCConfigRequest)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConfigRequest)(InstanceNo ino, _VCConfigRequest *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConfigRequest)(InstanceNo ino , _VCConfigRequest *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConfigReply)(_VCConfigReply *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCConfigReply)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConfigReply)(InstanceNo ino, _VCConfigReply *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConfigReply)(InstanceNo ino , _VCConfigReply *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCUser)(_VCUser *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCUser)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCUser)(InstanceNo ino, _VCUser *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCUser)(InstanceNo ino , _VCUser *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCResource)(_VCResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCResource)(InstanceNo ino, _VCResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCResource)(InstanceNo ino , _VCResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCResourceRequest)(_VCResourceRequest *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCResourceRequest)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCResourceRequest)(InstanceNo ino, _VCResourceRequest *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCResourceRequest)(InstanceNo ino , _VCResourceRequest *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCAudio)(_VCAudio *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCAudio)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCAudio)(InstanceNo ino, _VCAudio *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCAudio)(InstanceNo ino , _VCAudio *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCRadiator)(_VCRadiator *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCRadiator)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCRadiator)(InstanceNo ino, _VCRadiator *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCRadiator)(InstanceNo ino , _VCRadiator *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCAudioResource)(_VCAudioResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCAudioResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCAudioResource)(InstanceNo ino, _VCAudioResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCAudioResource)(InstanceNo ino , _VCAudioResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisual)(_VCVisual *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisual)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisual)(InstanceNo ino, _VCVisual *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisual)(InstanceNo ino , _VCVisual *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCMaterial)(_VCMaterial *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCMaterial)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCMaterial)(InstanceNo ino, _VCMaterial *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCMaterial)(InstanceNo ino , _VCMaterial *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCRamp)(_VCRamp *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCRamp)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCRamp)(InstanceNo ino, _VCRamp *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCRamp)(InstanceNo ino , _VCRamp *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTexture)(_VCTexture *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTexture)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTexture)(InstanceNo ino, _VCTexture *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTexture)(InstanceNo ino , _VCTexture *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCLight)(_VCLight *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCLight)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCLight)(InstanceNo ino, _VCLight *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCLight)(InstanceNo ino , _VCLight *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualResource)(_VCVisualResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualResource)(InstanceNo ino, _VCVisualResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualResource)(InstanceNo ino , _VCVisualResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualViewResource)(_VCVisualViewResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualViewResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualViewResource)(InstanceNo ino, _VCVisualViewResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualViewResource)(InstanceNo ino , _VCVisualViewResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCIntersectionReport)(_VCIntersectionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCIntersectionReport)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCIntersectionReport)(InstanceNo ino, _VCIntersectionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCIntersectionReport)(InstanceNo ino , _VCIntersectionReport *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCIntersectionState)(_VCIntersectionState *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCIntersectionState)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCIntersectionState)(InstanceNo ino, _VCIntersectionState *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCIntersectionState)(InstanceNo ino , _VCIntersectionState *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVectorIntersect)(_VCVectorIntersect *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCVectorIntersect)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVectorIntersect)(InstanceNo ino, _VCVectorIntersect *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCVectorIntersect)(InstanceNo ino , _VCVectorIntersect *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualEffect)(_VCVisualEffect *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualEffect)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualEffect)(InstanceNo ino, _VCVisualEffect *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualEffect)(InstanceNo ino , _VCVisualEffect *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCDynamicVisual)(_VCDynamicVisual *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCDynamicVisual)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCDynamicVisual)(InstanceNo ino, _VCDynamicVisual *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCDynamicVisual)(InstanceNo ino , _VCDynamicVisual *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCLod)(_VCLod *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCLod)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCLod)(InstanceNo ino, _VCLod *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCLod)(InstanceNo ino , _VCLod *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCGeogroup)(_VCGeogroup *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCGeogroup)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCGeogroup)(InstanceNo ino, _VCGeogroup *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCGeogroup)(InstanceNo ino , _VCGeogroup *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCGeometryHeader)(_VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCGeometryHeader)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCGeometryHeader)(InstanceNo ino, _VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCGeometryHeader)(InstanceNo ino , _VCGeometryHeader *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCGeometry)(_VCGeometry *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCGeometry)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCGeometry)(InstanceNo ino, _VCGeometry *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCGeometry)(InstanceNo ino , _VCGeometry *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCGeometry_header)(InstanceNo ino, _VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCGeometry_header)(InstanceNo ino , _VCGeometryHeader *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCGeometry_vertices)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCGeometry_vertices)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTextData)(_VCTextData *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTextData)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTextData)(InstanceNo ino, _VCTextData *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTextData)(InstanceNo ino , _VCTextData *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCText)(_VCText *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCText)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCText)(InstanceNo ino, _VCText *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCText)(InstanceNo ino , _VCText *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCText_header)(InstanceNo ino, _VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCText_header)(InstanceNo ino , _VCGeometryHeader *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCText_text)(InstanceNo ino, _VCTextData *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCText_text)(InstanceNo ino , _VCTextData *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConnectionListHeader)(_VCConnectionListHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCConnectionListHeader)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConnectionListHeader)(InstanceNo ino, _VCConnectionListHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCConnectionListHeader)(InstanceNo ino , _VCConnectionListHeader *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConnectionList)(_VCConnectionList *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCConnectionList)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConnectionList)(InstanceNo ino, _VCConnectionList *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConnectionList)(InstanceNo ino , _VCConnectionList *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCConnectionList_header)(InstanceNo ino, _VCConnectionListHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCConnectionList_header)(InstanceNo ino , _VCConnectionListHeader *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCConnectionList_connections)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConnectionList_connections)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCCollisionReport)(_VCCollisionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCCollisionReport)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCCollisionReport)(InstanceNo ino, _VCCollisionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCCollisionReport)(InstanceNo ino , _VCCollisionReport *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCCollisionState)(_VCCollisionState *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCCollisionState)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCCollisionState)(InstanceNo ino, _VCCollisionState *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCCollisionState)(InstanceNo ino , _VCCollisionState *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBoundary)(_VCBoundary *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBoundary)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBoundary)(InstanceNo ino, _VCBoundary *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBoundary)(InstanceNo ino , _VCBoundary *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBodyPart)(_VCBodyPart *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBodyPart)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBodyPart)(InstanceNo ino, _VCBodyPart *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBodyPart)(InstanceNo ino , _VCBodyPart *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBodyMonitor)(_VCBodyMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBodyMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBodyMonitor)(InstanceNo ino, _VCBodyMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBodyMonitor)(InstanceNo ino , _VCBodyMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBodyFlyInfo)(_VCBodyFlyInfo *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCBodyFlyInfo)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBodyFlyInfo)(InstanceNo ino, _VCBodyFlyInfo *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCBodyFlyInfo)(InstanceNo ino , _VCBodyFlyInfo *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBody)(_VCBody *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBody)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBody)(InstanceNo ino, _VCBody *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBody)(InstanceNo ino , _VCBody *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCPickObject)(_VCPickObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCPickObject)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCPickObject)(InstanceNo ino, _VCPickObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCPickObject)(InstanceNo ino , _VCPickObject *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTrackerMonitor)(_VCTrackerMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTrackerMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTrackerMonitor)(InstanceNo ino, _VCTrackerMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTrackerMonitor)(InstanceNo ino , _VCTrackerMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCCollideMonitor)(_VCCollideMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCCollideMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCCollideMonitor)(InstanceNo ino, _VCCollideMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCCollideMonitor)(InstanceNo ino , _VCCollideMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCSensorResource)(_VCSensorResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCSensorResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCSensorResource)(InstanceNo ino, _VCSensorResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCSensorResource)(InstanceNo ino , _VCSensorResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTracker)(_VCTracker *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTracker)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTracker)(InstanceNo ino, _VCTracker *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTracker)(InstanceNo ino , _VCTracker *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCInputResource)(_VCInputResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCInputResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCInputResource)(InstanceNo ino, _VCInputResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCInputResource)(InstanceNo ino , _VCInputResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCInput)(_VCInput *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCInput)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCInput)(InstanceNo ino, _VCInput *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCInput)(InstanceNo ino , _VCInput *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCXWindowId)(_VCXWindowId *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCXWindowId)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCXWindowId)(InstanceNo ino, _VCXWindowId *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCXWindowId)(InstanceNo ino , _VCXWindowId *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCQuery)(_VCQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCQuery)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCQuery)(InstanceNo ino, _VCQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCQuery)(InstanceNo ino , _VCQuery *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCResponse)(_VCResponse *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCResponse)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCResponse)(InstanceNo ino, _VCResponse *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCResponse)(InstanceNo ino , _VCResponse *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualQuery)(_VCVisualQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCVisualQuery)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualQuery)(InstanceNo ino, _VCVisualQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCVisualQuery)(InstanceNo ino , _VCVisualQuery *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCDynamics)(_VCDynamics *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCDynamics)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCDynamics)(InstanceNo ino, _VCDynamics *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCDynamics)(InstanceNo ino , _VCDynamics *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCForce)(_VCForce *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCForce)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCForce)(InstanceNo ino, _VCForce *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCForce)(InstanceNo ino , _VCForce *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCPseudoGravity)(_VCPseudoGravity *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCPseudoGravity)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCPseudoGravity)(InstanceNo ino, _VCPseudoGravity *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCPseudoGravity)(InstanceNo ino , _VCPseudoGravity *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCSync)(_VCSync *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCSync)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCSync)(InstanceNo ino, _VCSync *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCSync)(InstanceNo ino , _VCSync *data, VLTime *utime); + +#ifdef __VL_INLINE_ACCESS__ +#define VLCreateVCTime( d, t, m) vlCreateInstance(el_VCTime, 0, (d),(t),(m)) +#define VLDeleteVCTime(i,m) vlDeleteInstance((i),(m)) +#define VLUpdateVCTime( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtractVCTime(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreateVCColour( d, t, m) vlCreateInstance(el_VCColour, 0, (d),(t),(m)) +#define VLDeleteVCColour(i,m) vlDeleteInstance((i),(m)) +#define VLUpdateVCColour( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtractVCColour(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCPosition( d, t, m) vlCreateInstance(el__VCPosition, 0, (d),(t),(m)) +#define VLDelete_VCPosition(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCPosition( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCPosition(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCObjectPosition( d, t, m) vlCreateInstance(el__VCObjectPosition, 0, (d),(t),(m)) +#define VLDelete_VCObjectPosition(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCObjectPosition( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCObjectPosition(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCObjectPosition_vcPos( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCObjectPosition_vcPos(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCObjectPosition_parent( i, d, t, m) vlUpdateInstance((i) + 2,(d),(t),(m)) +#define VLExtract_VCObjectPosition_parent(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCObject( d, t, m) vlCreateInstance(el__VCObject, 0, (d),(t),(m)) +#define VLDelete_VCObject(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCObject( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCObject(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCObject_pos( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCObject_pos(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCObject_pos_vcPos( i, d, t, m) vlUpdateInstance((i) + 2,(d),(t),(m)) +#define VLExtract_VCObject_pos_vcPos(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLUpdate_VCObject_pos_parent( i, d, t, m) vlUpdateInstance((i) + 3,(d),(t),(m)) +#define VLExtract_VCObject_pos_parent(i, d, t) vlExtractInstance((i) + 3,(d),(t)) + + +#define VLUpdate_VCObject_attributes( i, d, t, m) vlUpdateInstance((i) + 4,(d),(t),(m)) +#define VLExtract_VCObject_attributes(i, d, t) vlExtractInstance((i) + 4,(d),(t)) + + +#define VLCreate_VCConstraints( d, t, m) vlCreateInstance(el__VCConstraints, 0, (d),(t),(m)) +#define VLDelete_VCConstraints(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConstraints( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCConstraints(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCZone( d, t, m) vlCreateInstance(el__VCZone, 0, (d),(t),(m)) +#define VLDelete_VCZone(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCZone( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCZone(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCVisualMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCConfigRequest(d, t, m, c) vlCreateDynamicInstance(el__VCConfigRequest,0,(d),(t),(m),(c)) +#define VLDelete_VCConfigRequest(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConfigRequest( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCConfigRequest(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCConfigReply(d, t, m, c) vlCreateDynamicInstance(el__VCConfigReply,0,(d),(t),(m),(c)) +#define VLDelete_VCConfigReply(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConfigReply( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCConfigReply(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCUser(d, t, m, c) vlCreateDynamicInstance(el__VCUser,0,(d),(t),(m),(c)) +#define VLDelete_VCUser(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCUser( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCUser(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCResource(d, t, m, c) vlCreateDynamicInstance(el__VCResource,0,(d),(t),(m),(c)) +#define VLDelete_VCResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCResourceRequest( d, t, m) vlCreateInstance(el__VCResourceRequest, 0, (d),(t),(m)) +#define VLDelete_VCResourceRequest(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCResourceRequest( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCResourceRequest(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCAudio(d, t, m, c) vlCreateDynamicInstance(el__VCAudio,0,(d),(t),(m),(c)) +#define VLDelete_VCAudio(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCAudio( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCAudio(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCRadiator( d, t, m) vlCreateInstance(el__VCRadiator, 0, (d),(t),(m)) +#define VLDelete_VCRadiator(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCRadiator( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCRadiator(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCAudioResource(d, t, m, c) vlCreateDynamicInstance(el__VCAudioResource,0,(d),(t),(m),(c)) +#define VLDelete_VCAudioResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCAudioResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCAudioResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisual(d, t, m, c) vlCreateDynamicInstance(el__VCVisual,0,(d),(t),(m),(c)) +#define VLDelete_VCVisual(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisual( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisual(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCMaterial(d, t, m, c) vlCreateDynamicInstance(el__VCMaterial,0,(d),(t),(m),(c)) +#define VLDelete_VCMaterial(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCMaterial( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCMaterial(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCRamp(d, t, m, c) vlCreateDynamicInstance(el__VCRamp,0,(d),(t),(m),(c)) +#define VLDelete_VCRamp(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCRamp( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCRamp(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCTexture(d, t, m, c) vlCreateDynamicInstance(el__VCTexture,0,(d),(t),(m),(c)) +#define VLDelete_VCTexture(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTexture( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTexture(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCLight( d, t, m) vlCreateInstance(el__VCLight, 0, (d),(t),(m)) +#define VLDelete_VCLight(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCLight( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCLight(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualResource(d, t, m, c) vlCreateDynamicInstance(el__VCVisualResource,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualViewResource(d, t, m, c) vlCreateDynamicInstance(el__VCVisualViewResource,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualViewResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualViewResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualViewResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCIntersectionReport( d, t, m) vlCreateInstance(el__VCIntersectionReport, 0, (d),(t),(m)) +#define VLDelete_VCIntersectionReport(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCIntersectionReport( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCIntersectionReport(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCIntersectionState(d, t, m, c) vlCreateDynamicInstance(el__VCIntersectionState,0,(d),(t),(m),(c)) +#define VLDelete_VCIntersectionState(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCIntersectionState( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCIntersectionState(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVectorIntersect( d, t, m) vlCreateInstance(el__VCVectorIntersect, 0, (d),(t),(m)) +#define VLDelete_VCVectorIntersect(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVectorIntersect( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCVectorIntersect(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualEffect(d, t, m, c) vlCreateDynamicInstance(el__VCVisualEffect,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualEffect(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualEffect( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualEffect(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCDynamicVisual(d, t, m, c) vlCreateDynamicInstance(el__VCDynamicVisual,0,(d),(t),(m),(c)) +#define VLDelete_VCDynamicVisual(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCDynamicVisual( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCDynamicVisual(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCLod(d, t, m, c) vlCreateDynamicInstance(el__VCLod,0,(d),(t),(m),(c)) +#define VLDelete_VCLod(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCLod( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCLod(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCGeogroup(d, t, m, c) vlCreateDynamicInstance(el__VCGeogroup,0,(d),(t),(m),(c)) +#define VLDelete_VCGeogroup(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCGeogroup( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCGeogroup(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCGeometryHeader( d, t, m) vlCreateInstance(el__VCGeometryHeader, 0, (d),(t),(m)) +#define VLDelete_VCGeometryHeader(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCGeometryHeader( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCGeometryHeader(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCGeometry(d, t, m, c) vlCreateDynamicInstance(el__VCGeometry,0,(d),(t),(m),(c)) +#define VLDelete_VCGeometry(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCGeometry( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCGeometry(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCGeometry_header( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCGeometry_header(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCGeometry_vertices( i, d, t, m,c) vlUpdateDynamicInstance((i) + 2,(d),(t),(m),(c)) +#define VLExtract_VCGeometry_vertices(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCTextData(d, t, m, c) vlCreateDynamicInstance(el__VCTextData,0,(d),(t),(m),(c)) +#define VLDelete_VCTextData(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTextData( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTextData(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCText(d, t, m, c) vlCreateDynamicInstance(el__VCText,0,(d),(t),(m),(c)) +#define VLDelete_VCText(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCText( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCText(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCText_header( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCText_header(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCText_text( i, d, t, m,c) vlUpdateDynamicInstance((i) + 2,(d),(t),(m),(c)) +#define VLExtract_VCText_text(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCConnectionListHeader( d, t, m) vlCreateInstance(el__VCConnectionListHeader, 0, (d),(t),(m)) +#define VLDelete_VCConnectionListHeader(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConnectionListHeader( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCConnectionListHeader(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCConnectionList(d, t, m, c) vlCreateDynamicInstance(el__VCConnectionList,0,(d),(t),(m),(c)) +#define VLDelete_VCConnectionList(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConnectionList( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCConnectionList(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCConnectionList_header( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCConnectionList_header(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCConnectionList_connections( i, d, t, m,c) vlUpdateDynamicInstance((i) + 2,(d),(t),(m),(c)) +#define VLExtract_VCConnectionList_connections(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCCollisionReport( d, t, m) vlCreateInstance(el__VCCollisionReport, 0, (d),(t),(m)) +#define VLDelete_VCCollisionReport(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCCollisionReport( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCCollisionReport(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCCollisionState(d, t, m, c) vlCreateDynamicInstance(el__VCCollisionState,0,(d),(t),(m),(c)) +#define VLDelete_VCCollisionState(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCCollisionState( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCCollisionState(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBoundary(d, t, m, c) vlCreateDynamicInstance(el__VCBoundary,0,(d),(t),(m),(c)) +#define VLDelete_VCBoundary(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBoundary( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBoundary(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBodyPart(d, t, m, c) vlCreateDynamicInstance(el__VCBodyPart,0,(d),(t),(m),(c)) +#define VLDelete_VCBodyPart(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBodyPart( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBodyPart(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBodyMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCBodyMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCBodyMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBodyMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBodyMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBodyFlyInfo( d, t, m) vlCreateInstance(el__VCBodyFlyInfo, 0, (d),(t),(m)) +#define VLDelete_VCBodyFlyInfo(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBodyFlyInfo( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCBodyFlyInfo(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBody(d, t, m, c) vlCreateDynamicInstance(el__VCBody,0,(d),(t),(m),(c)) +#define VLDelete_VCBody(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBody( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBody(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCPickObject( d, t, m) vlCreateInstance(el__VCPickObject, 0, (d),(t),(m)) +#define VLDelete_VCPickObject(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCPickObject( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCPickObject(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCTrackerMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCTrackerMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCTrackerMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTrackerMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTrackerMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCCollideMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCCollideMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCCollideMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCCollideMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCCollideMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCSensorResource(d, t, m, c) vlCreateDynamicInstance(el__VCSensorResource,0,(d),(t),(m),(c)) +#define VLDelete_VCSensorResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCSensorResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCSensorResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCTracker(d, t, m, c) vlCreateDynamicInstance(el__VCTracker,0,(d),(t),(m),(c)) +#define VLDelete_VCTracker(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTracker( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTracker(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCInputResource(d, t, m, c) vlCreateDynamicInstance(el__VCInputResource,0,(d),(t),(m),(c)) +#define VLDelete_VCInputResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCInputResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCInputResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCInput(d, t, m, c) vlCreateDynamicInstance(el__VCInput,0,(d),(t),(m),(c)) +#define VLDelete_VCInput(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCInput( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCInput(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCXWindowId(d, t, m, c) vlCreateDynamicInstance(el__VCXWindowId,0,(d),(t),(m),(c)) +#define VLDelete_VCXWindowId(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCXWindowId( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCXWindowId(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCQuery( d, t, m) vlCreateInstance(el__VCQuery, 0, (d),(t),(m)) +#define VLDelete_VCQuery(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCQuery( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCQuery(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCResponse( d, t, m) vlCreateInstance(el__VCResponse, 0, (d),(t),(m)) +#define VLDelete_VCResponse(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCResponse( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCResponse(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualQuery( d, t, m) vlCreateInstance(el__VCVisualQuery, 0, (d),(t),(m)) +#define VLDelete_VCVisualQuery(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualQuery( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCVisualQuery(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCDynamics( d, t, m) vlCreateInstance(el__VCDynamics, 0, (d),(t),(m)) +#define VLDelete_VCDynamics(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCDynamics( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCDynamics(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCForce( d, t, m) vlCreateInstance(el__VCForce, 0, (d),(t),(m)) +#define VLDelete_VCForce(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCForce( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCForce(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCPseudoGravity( d, t, m) vlCreateInstance(el__VCPseudoGravity, 0, (d),(t),(m)) +#define VLDelete_VCPseudoGravity(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCPseudoGravity( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCPseudoGravity(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCSync(d, t, m, c) vlCreateDynamicInstance(el__VCSync,0,(d),(t),(m),(c)) +#define VLDelete_VCSync(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCSync( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCSync(i, d, t) vlExtractInstance((i),(d),(t)) + +#endif +/* + * Symbolic element names. + */ +extern const ElementHandle el_VCTime; +extern const ElementHandle el_VCColour; +extern const ElementHandle el__VCPosition; +extern const ElementHandle el__VCObjectPosition; +extern const ElementHandle el__VCObject; +extern const ElementHandle el__VCConstraints; +extern const ElementHandle el__VCZone; +extern const ElementHandle el__VCVisualMonitor; +extern const ElementHandle el__VCConfigRequest; +extern const ElementHandle el__VCConfigReply; +extern const ElementHandle el__VCUser; +extern const ElementHandle el__VCResource; +extern const ElementHandle el__VCResourceRequest; +extern const ElementHandle el__VCAudio; +extern const ElementHandle el__VCRadiator; +extern const ElementHandle el__VCAudioResource; +extern const ElementHandle el__VCVisual; +extern const ElementHandle el__VCMaterial; +extern const ElementHandle el__VCRamp; +extern const ElementHandle el__VCTexture; +extern const ElementHandle el__VCLight; +extern const ElementHandle el__VCVisualResource; +extern const ElementHandle el__VCVisualViewResource; +extern const ElementHandle el__VCIntersectionReport; +extern const ElementHandle el__VCIntersectionState; +extern const ElementHandle el__VCVectorIntersect; +extern const ElementHandle el__VCVisualEffect; +extern const ElementHandle el__VCDynamicVisual; +extern const ElementHandle el__VCLod; +extern const ElementHandle el__VCGeogroup; +extern const ElementHandle el__VCGeometryHeader; +extern const ElementHandle el__VCGeometry; +extern const ElementHandle el__VCTextData; +extern const ElementHandle el__VCText; +extern const ElementHandle el__VCConnectionListHeader; +extern const ElementHandle el__VCConnectionList; +extern const ElementHandle el__VCCollisionReport; +extern const ElementHandle el__VCCollisionState; +extern const ElementHandle el__VCBoundary; +extern const ElementHandle el__VCBodyPart; +extern const ElementHandle el__VCBodyMonitor; +extern const ElementHandle el__VCBodyFlyInfo; +extern const ElementHandle el__VCBody; +extern const ElementHandle el__VCPickObject; +extern const ElementHandle el__VCTrackerMonitor; +extern const ElementHandle el__VCCollideMonitor; +extern const ElementHandle el__VCSensorResource; +extern const ElementHandle el__VCTracker; +extern const ElementHandle el__VCInputResource; +extern const ElementHandle el__VCInput; +extern const ElementHandle el__VCXWindowId; +extern const ElementHandle el__VCQuery; +extern const ElementHandle el__VCResponse; +extern const ElementHandle el__VCVisualQuery; +extern const ElementHandle el__VCDynamics; +extern const ElementHandle el__VCForce; +extern const ElementHandle el__VCPseudoGravity; +extern const ElementHandle el__VCSync; + +static const int ElCountVC = 58; + +/* + * Epp declaraions. NOT 'C' - hence the ifdef guard! + */ +#ifdef __EPP__ +%% +extern atomic element VCTime; +extern atomic element VCColour; +extern atomic element _VCPosition; +extern element _VCObjectPosition; +extern element _VCObject; +extern atomic element _VCConstraints; +extern atomic element _VCZone; +extern atomic element _VCVisualMonitor; +extern atomic element _VCConfigRequest; +extern atomic element _VCConfigReply; +extern atomic element _VCUser; +extern atomic element _VCResource; +extern atomic element _VCResourceRequest; +extern atomic element _VCAudio; +extern atomic element _VCRadiator; +extern atomic element _VCAudioResource; +extern atomic element _VCVisual; +extern atomic element _VCMaterial; +extern atomic element _VCRamp; +extern atomic element _VCTexture; +extern atomic element _VCLight; +extern atomic element _VCVisualResource; +extern atomic element _VCVisualViewResource; +extern atomic element _VCIntersectionReport; +extern atomic element _VCIntersectionState; +extern atomic element _VCVectorIntersect; +extern atomic element _VCVisualEffect; +extern atomic element _VCDynamicVisual; +extern atomic element _VCLod; +extern atomic element _VCGeogroup; +extern atomic element _VCGeometryHeader; +extern element _VCGeometry; +extern atomic element _VCTextData; +extern element _VCText; +extern atomic element _VCConnectionListHeader; +extern element _VCConnectionList; +extern atomic element _VCCollisionReport; +extern atomic element _VCCollisionState; +extern atomic element _VCBoundary; +extern atomic element _VCBodyPart; +extern atomic element _VCBodyMonitor; +extern atomic element _VCBodyFlyInfo; +extern atomic element _VCBody; +extern atomic element _VCPickObject; +extern atomic element _VCTrackerMonitor; +extern atomic element _VCCollideMonitor; +extern atomic element _VCSensorResource; +extern atomic element _VCTracker; +extern atomic element _VCInputResource; +extern atomic element _VCInput; +extern atomic element _VCXWindowId; +extern atomic element _VCQuery; +extern atomic element _VCResponse; +extern atomic element _VCVisualQuery; +extern atomic element _VCDynamics; +extern atomic element _VCForce; +extern atomic element _VCPseudoGravity; +extern atomic element _VCSync; +%% +#endif/* __EPP__ */ +#ifdef __cplusplus +} +#endif +#endif /* ____VCELEMEN_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCELTYPE.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCELTYPE.H new file mode 100644 index 0000000..776192b --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCELTYPE.H @@ -0,0 +1,629 @@ +/* + PROJET: + SUBSYSTEM: + MODULE: + + FILE: $RCSfile: vceltype.h,v $ + REVISION: $Revision: 1.1 $ + Date: $Date: 95/05/18 10:24:13 $ + Author: $Author: john $ + RCS Ident: $Id: vceltype.h,v 1.1 1995/03/10 14:52:46 john Exp $ + + FUNCTION: + + + + + Copyright (c) 1992 Division Ltd. + + All Rights Reserved. + + This Document may not, in whole or in part, be copied, + photocopied, reproduced, translated, or reduced to and + electronic medium or machine readable form without prior + written consent from Division Ltd. +*/ +#ifndef VCELTYPE_H +#define VCELTYPE_H +#ifdef _LIB_VC +#include + +#else +#include +#endif + + +#define InstanceNo uint32 /* Define InstanceNo as a basic type !! */ + +#ifndef VCColor +typedef float32 VCColour[3]; +#endif +#ifndef _VCDTYPES_H +typedef struct +{ + uint32 secs; + uint32 uSecs; +}VCTime; +#endif +/* +typedef VCPositionData _VCPosition; +*/ + +/* +typedef struct +{ + uint32 secs; + uint32 uSecs; +}VCTime; +*/ + +typedef struct +{ + dmPosition dmPos; + uint32 mode; +}_VCPosition; + +typedef struct +{ + _VCPosition vcPos; + uint32 parent; +}_VCObjectPosition; + + +typedef struct +{ + uint32 mode; + int32 loopCnt; + float32 gain; + uint16 play; + uint8 velocity; + int8 priority; + char8 voice[1]; +}_VCAudio; + + +typedef struct +{ + char8 name[VC_RADIATOR_NAME_LENGTH]; + int32 numPoints; + float32 points[VC_RADIATOR_MAX_POINTS]; +} _VCRadiator; + + +typedef struct +{ + uint32 mode; + uint32 flags; + float32 point[6]; + float32 rotation[6]; +} _VCConstraints; + +typedef struct +{ + uint32 mode; + uint32 intersectMask; + InstanceNo dynamicIno; + char8 geometry[1]; +} _VCVisual; + + +typedef struct +{ + uint32 mode; + float32 ambient[3]; + float32 diffuse[3]; + float32 specular[4]; + float32 emissive[3]; + float32 opacity[3]; + char8 name[1]; +} _VCMaterial; + +typedef struct +{ + uint32 mode; + uint8 minify; + uint8 magnify; + uint8 alpha; + uint8 wrapU; + uint8 wrapV; + uint8 detailType; + char8 name[1]; +} _VCTexture; + +typedef struct +{ + InstanceNo boundaryIno; + uint16 flags; + dmPoint point; + dmVector direction; + VCTime time; +} _VCCollisionReport; + +typedef struct +{ + InstanceNo myBoundaryIno; + uint32 numberCollisions; + _VCCollisionReport collisions[1]; +} _VCCollisionState; + + +typedef struct +{ + float32 bound[VC_BOUND_SIZE]; + uint32 mode; + int32 numberCollisions; + InstanceNo collisionStateIno; + InstanceNo dynamicVisual; + char8 geometry[1]; +} _VCBoundary; + +/* +typedef struct VCLightData _VCLight; +*/ + +typedef struct +{ + uint32 mode; + VCColour colour; + float32 exponent; + float32 theta; +}_VCLight; + + + +typedef struct +{ + _VCObjectPosition pos; + InstanceNo attributes[VC_MAX_OBJECT_ATTRIBUTES]; +}_VCObject; + +typedef struct +{ + uint32 actorId; + char8 name[1]; +} _VCBodyPart; + +typedef struct +{ + float32 headUpdateRate; /* No updates / second */ + float32 geometryUpdates; /* No updates / second */ + float32 frameRate; /* No frames drawn/second */ + float32 drawRate; /* Tri's per second */ + char8 name[1]; /* Name of the actor. */ +}_VCVisualMonitor; + + +typedef struct +{ + float32 sensorRate[VC_MAX_SENSORS]; /* Sensor updates per second */ + uint32 sensorBaseNumber; + char8 name[1]; /* Name of the actor. */ +}_VCTrackerMonitor; + +typedef struct { + uint32 updateRate; + uint32 transmissionDelay; + dmPoint sourcePosition; + dmEuler sourceEuler; + uint32 baudRate; + char8 name[1]; +} _VCTracker; + +typedef struct { + uint32 mode; + InstanceNo trackerIno; + uint32 sensorId; + float32 scaleTranslate[3]; + float32 scaleRotate[3]; + float32 rotationCurveOrder[3]; + float32 translationCurveOrder[3]; + dmPoint prePosition; + dmPoint postPosition; + dmEuler preEuler; + dmEuler postEuler; + float32 relativeSphere[6]; + InstanceNo positionIno; + _VCConstraints constraints; + char8 name[1]; /* Name of the actor. */ +} _VCSensorResource; + +typedef struct +{ + uint32 mode; + InstanceNo inputIno; + char8 name[1]; /* Name of the actor. */ +} _VCInputResource; + +typedef struct +{ + float32 objectInRate; /* Object updates per second */ + float32 objectInActive; /* Objects that are collidable per second */ + float32 objectTests; /* Number of collision tests per second */ + char8 name[1]; /* Name of the actor. */ +} _VCCollideMonitor; + + +typedef struct +{ + char8 name[1]; /* Name of the actor. */ +} _VCBodyMonitor; + +typedef struct +{ + uint32 mode; + float32 frameRate; + float32 iod; + float32 convergence; + float32 background[3]; + float32 nearClip; + float32 farClip; + float32 fogColour[3]; + float32 nearFog; + float32 farFog; + float32 lodScale; + uint32 actorId; + char8 name[1]; +} _VCVisualResource; + + +typedef struct +{ + InstanceNo visualResourceIno; + uint32 mode; + dmPoint offset; + dmEuler orientation; + float32 size[2]; + char8 name[1]; +} _VCVisualViewResource; + + +typedef struct +{ + float32 slow_speed; + float32 fast_speed; + float32 acceleration; + float32 max_speed; + uint32 slow_key; + uint32 fast_key; + uint32 accelerate_key; +}_VCBodyFlyInfo; + +typedef struct +{ + uint32 actorId; + InstanceNo bodyRoot; + InstanceNo bodyPosObject; + _VCBodyFlyInfo fly_forward; + _VCBodyFlyInfo fly_backward; + _VCBodyFlyInfo fly_up; + _VCBodyFlyInfo fly_down; + _VCBodyFlyInfo fly_left; + _VCBodyFlyInfo fly_right; + _VCBodyFlyInfo rot_left; + _VCBodyFlyInfo rot_right; + _VCBodyFlyInfo rot_up; + _VCBodyFlyInfo rot_down; + uint32 verticalFly_key; + uint32 altFly_key; + InstanceNo flyDirectionLimb; + InstanceNo altFlyDirectionLimb; + InstanceNo altFlyLimb; + uint32 flyMode; + char8 name[1]; +} _VCBody; + +typedef struct +{ + InstanceNo ino; + char8 name[1]; +} _VCConfigRequest; + +typedef struct +{ + InstanceNo user; + int32 verbose; + int32 enable; + char8 log[4]; + char8 config[1]; +} _VCConfigReply; + +typedef struct +{ + char8 name[1]; +} _VCUser; + +typedef struct +{ + InstanceNo resourceIno; + uint8 allocated; + char8 name[1]; +}_VCResource; + +typedef struct +{ + InstanceNo resource; + int32 updated; + InstanceNo serverResource; + uint32 resourceType; +} _VCResourceRequest; + +typedef struct +{ + uint32 mode; + float32 iad; + float32 volume; + float32 spreadingRollOff; + float32 atmosphericAbsorption; + float32 worldScale; + char8 name[1]; +} _VCAudioResource; + +typedef struct +{ + uint32 numWraps; + int32 head; + uint32 input[1]; +}_VCInput; + +typedef struct +{ + InstanceNo pickInstance; + uint32 mode; + uint32 pickActorId; +}_VCPickObject; + +typedef struct { + uint32 windowId; /* Identity of the window */ + char8 name [1]; /* Name of the resource. */ +} _VCXWindowId; + +typedef struct { + + uint32 actorId; + uint32 mode; + InstanceNo subject; +} _VCQuery; + +typedef struct { + uint32 status; + InstanceNo result; +} _VCResponse; + +typedef struct { + _VCQuery query; + _VCResponse response; +} _VCVisualQuery; + +typedef struct +{ + InstanceNo object; + InstanceNo visual; + InstanceNo patch; + dmPoint point; +} _VCIntersectionReport; + +typedef struct +{ + InstanceNo myVectorIntersectIno; + uint32 numberIntersections; + _VCIntersectionReport intersections[1]; +} _VCIntersectionState; + +typedef struct +{ + uint32 mode; + float32 length; + uint32 intersectMask; + int32 numberIntersections; + InstanceNo intersectStateIno; +}_VCVectorIntersect; + +typedef struct +{ + uint32 mode; + uint32 type; + dmPoint offset; + float32 data[72]; + char8 texture[1]; +}_VCVisualEffect; + +typedef struct +{ + uint32 mode; + float32 iMass; + float32 gMass; + dmPoint centre; + float32 iTensor[6]; + float32 spring; + float32 damper; + float32 staticFriction; + float32 dynamicFriction; +}_VCDynamics; + + +typedef struct +{ + uint32 mode; + dmVector force; + dmPoint point; +} _VCForce; + +typedef struct +{ + uint32 mode; + dmVector direction; + float32 gravity; +}_VCPseudoGravity; + +typedef struct +{ + uint32 mode; + uint32 actorMask; +}_VCZone; + +typedef struct +{ + uint32 mode; + InstanceNo lod; + char8 name[1]; +} _VCDynamicVisual; + +typedef struct +{ + uint32 mode; + float32 in; + float32 out; + dmPoint reference; + InstanceNo next; + char8 name[1]; +} _VCLod; + +typedef struct +{ + uint32 mode; + uint8 faceted; + uint8 vertexFormat; + uint8 lock; + uint8 drawMode; + uint8 drawWidth; + int32 decal; + InstanceNo lod; + char8 name[1]; +} _VCGeogroup; + +typedef struct +{ + uint32 mode; + uint32 numVertices; + InstanceNo geogroup; +} _VCGeometryHeader; + +typedef struct +{ + _VCGeometryHeader header; + float32 vertices[1]; +} _VCGeometry; + +typedef struct +{ + uint8 font; + dmPoint position; + dmEuler orientation; + dmScale scale; + char8 text[1]; +} _VCTextData; + +typedef struct +{ + _VCGeometryHeader header; + _VCTextData text; +} _VCText; + +typedef struct +{ + uint32 numConnections; + uint32 mode; + InstanceNo geometry; +} _VCConnectionListHeader; + +typedef struct +{ + _VCConnectionListHeader header; + uint32 connections[1]; +} _VCConnectionList; + +typedef struct +{ + VCTime time; + char8 name[1]; +} _VCSync; + +typedef struct +{ + uint32 mode; + VCColour minRgb; + VCColour maxRgb; + char8 name[1]; +} _VCRamp; + + + + +#undef InstanceNo /* Remove local Instance Number definition */ +#define el_VCPosition el__VCPosition +#define el_VCObjectPosition el__VCObjectPosition +#define el_VCObject el__VCObject +#define el_VCConstraints el__VCConstraints +#define el_VCZone el__VCZone + +#define el_VCVisualMonitor el__VCVisualMonitor +#define el_VCConfigRequest el__VCConfigRequest +#define el_VCConfigReply el__VCConfigReply +#define el_VCUser el__VCUser +#define el_VCResource el__VCResource +#define el_VCResourceRequest el__VCResourceRequest + +#define el_VCAudio el__VCAudio +#define el_VCRadiator el__VCRadiator +#define el_VCAudioResource el__VCAudioResource + + +#define el_VCVisual el__VCVisual +#define el_VCMaterial el__VCMaterial +#define el_VCTexture el__VCTexture +#define el_VCLight el__VCLight +#define el_VCVisualResource el__VCVisualResource +#define el_VCVisualViewResource el__VCVisualViewResource + +#define el_VCIntersect el__VCIntersect +#define el_VCVectorIntersect el__VCVectorIntersect + +#define el_VCIntersectionReport el__VCIntersectionReport +#define el_VCIntersectionState el__VCIntersectionState +#define el_VCNewVectorIntersect el__VCNewVectorIntersect + +#define el_VCVisualEffect el__VCVisualEffect + +#define el_VCCollisionReport el__VCCollisionReport +#define el_VCCollisionState el__VCCollisionState +#define el_VCBoundary el__VCBoundary + +#define el_VCBodyPart el__VCBodyPart +#define el_VCBodyMonitor el__VCBodyMonitor +#define el_VCBodyFlyInfo el__VCBodyFlyInfo +#define el_VCBody el__VCBody +#define el_VCPickObject el__VCPickObject + +#define el_VCTrackerMonitor el__VCTrackerMonitor +#define el_VCCollideMonitor el__VCCollideMonitor + + +#define el_VCSensorResource el__VCSensorResource +#define el_VCTracker el__VCTracker + +#define el_VCInputResource el__VCInputResource +#define el_VCInput el__VCInput + +#define el_VCXWindowId el__VCXWindowId + +#define el_VCQuery el__VCQuery +#define el_VCResponse el__VCResponse +#define el__VCResponse el__VCResponse +#define el_VCVisualQuery el__VCVisualQuery + +#define el_VCDynamics el__VCDynamics +#define el_VCForce el__VCForce +#define el_VCPseudoGravity el__VCPseudoGravity + +#define el_VCDynamicVisual el__VCDynamicVisual +#define el_VCLod el__VCLod +#define el_VCGeogroup el__VCGeogroup +#define el_VCGeometryHeader el__VCGeometryHeader +#define el_VCGeometry el__VCGeometry +#define el_VCTextData el__VCTextData +#define el_VCText el__VCText +#define el_VCConnectionListHeader el__VCConnectionListHeader +#define el_VCConnectionList el__VCConnectionList +#define el_VCSync el__VCSync +#define el_VCRamp el__VCRamp +#endif /* VCELTYPE_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCERROR.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCERROR.H new file mode 100644 index 0000000..0097c68 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCERROR.H @@ -0,0 +1,33 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1994 Division Limited. +-- All Rights Reserved +-- +-- +-- System : dVS 2.1 +-- Module : libvc +-- Object Name : $RCSfile: vcerror.h,v $ +-- Revision : $Revision: 1.1 $ +-- Date : $Date: 95/05/18 10:24:15 $ +-- Author : $Author: john $ +-- +-- Description +-- Vcerror routines. +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __VCERROR_H__ +#define __VCERROR_H__ + +void VC_Warn(char *format, ...); +void VC_Error(char *format, ...); +void VC_Fatal(char *format, ...); + +#endif /* __VCERROR_H__ */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCINPDEF.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCINPDEF.H new file mode 100644 index 0000000..8a8b0e4 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCINPDEF.H @@ -0,0 +1,71 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vcinpdef.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:16 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcinpdef.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + + +/* + * define the modifier values + */ +#define VC_INPUT_RELEASE 0x00010000 +#define VC_INPUT_PRESS 0x00020000 +#define VC_MODIFIER_0 0x00100000 +#define VC_MODIFIER_1 0x00200000 +#define VC_MODIFIER_2 0x00400000 +#define VC_MODIFIER_3 0x00800000 +#define VC_MODIFIER_4 0x01000000 +#define VC_MODIFIER_5 0x02000000 +#define VC_MODIFIER_6 0x04000000 +#define VC_MODIFIER_7 0x08000000 + +#define VC_MODIFIER_CTRL VC_MODIFIER_0 +#define VC_MODIFIER_ALT VC_MODIFIER_1 +#define VC_MODIFIER_ESC VC_MODIFIER_2 + +#define VC_INPUT_CODE_MASK 0x0000ffff +#define VC_INPUT_TYPE 0x000f0000 +#define VC_INPUT_MODIFIER_MASK 0x0ff00000 +#define VC_INPUT_ALL_KEYS 0x0000ffff +#define VC_INPUT_SINGLE_KEY 0x00000000 + +#define VC_BUTTON_0 0x0080 +#define VC_BUTTON_1 0x0081 +#define VC_BUTTON_2 0x0082 +#define VC_BUTTON_3 0x0083 +#define VC_BUTTON_4 0x0084 +#define VC_BUTTON_5 0x0085 +#define VC_BUTTON_6 0x0086 +#define VC_BUTTON_7 0x0087 +#define VC_BUTTON_8 0x0088 +#define VC_BUTTON_9 0x0089 +#define VC_BUTTON_10 0x008a +#define VC_BUTTON_11 0x008b +#define VC_BUTTON_12 0x008c +#define VC_BUTTON_13 0x008d +#define VC_BUTTON_14 0x008e +#define VC_BUTTON_15 0x008f + + + + + + + diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCMACROS.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCMACROS.H new file mode 100644 index 0000000..701838c --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCMACROS.H @@ -0,0 +1,33 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vctools.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:16 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctools.h,v 0.10 1994/10/05 12:51:14 john Exp jon $ + * + * FUNCTION: + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine reable form without prior + * written consent from Division Ltd. + */ + + + +#ifndef _VCMACROS_H_ +#define _VCMACROS_H_ + +#define VC_GetEntityRelocateMode() VCEntity_GetRelocateMode(NULL) +#define VC_SetEntityRelocateMode(m) VCEntity_SetRelocateMode(NULL,m) +#define VCBody_SetVisualResourceBackgroundColor(b,c) VCBody_SetVisualResourceBackgroundColour(b,c) +#define VCBody_SetVisualResourceFogColor(b,c,t,m) VCBody_SetVisualResourceFogColour(b,c,t,m) +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCOBJECT.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCOBJECT.H new file mode 100644 index 0000000..5d9db00 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCOBJECT.H @@ -0,0 +1,686 @@ +/*************************************************************************** + * <210493.1436> + * PROJECT: dVS + * SUBSYSTEM: VCTools. + * MODULE: VC Object definitions. + * + *************************************************************************** + * + * File: $RCSfile: vcobject.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:17 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcobject.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * Creator: Jon Green. + * + * + * + ************************************************************************** + * * + * Copyright (c) 1992,1993,1994,1995 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +/*--- Include Definitions */ + +#ifndef _VCOBJECT_H +#define _VCOBJECT_H 1 + +/* Spin functions */ +#define VCEntity_SpinX(e,a) VCEntity_Spin(e,VC_X,a) +#define VCEntity_SpinY(e,a) VCEntity_Spin(e,VC_Y,a) +#define VCEntity_SpinZ(e,a) VCEntity_Spin(e,VC_Z,a) + +int VCEntity_Rotate (VCEntity *e, dmPoint centre, int axis, float angle); +int VCEntity_RotateX (VCEntity *e, float angle); +int VCEntity_RotateY (VCEntity *e, float angle); +int VCEntity_RotateZ (VCEntity *e, float angle); + + +int VCEntity_Spin (VCEntity *e, int axis, float angle); +int VCEntity_Scale (VCEntity *e, float sx, float sy, float sz); +int VCEntity_Resize (VCEntity *entity, float sx, float sy, float sz); +int VCEntity_Translate (VCEntity *e, float dx, float dy, float dz); + + +VCAttribute *VCVisual_Create (char *visual_name, VCDynamicVisual *dynamicVIsual, uint32 mode, char *lod, + char *frontMaterial, char *backMaterial, + uint32 intersectMask); +int VCVisual_Set (VCAttribute *attribute, char *visual_name, VCDynamicVisual *dynamicVisual, + uint32 setMode, uint32 clearMode, char *lod, char *frontMaterial, + char *backMaterial, uint32 setIntersectMask, + uint32 clearIntersectMask); +int VCVisual_Get (VCAttribute *attribute, char **visual_name, + VCDynamicVisual **dynamicVisual, + uint32 *mode, char **lod, char **frontMaterial, char **backMaterial, + uint32 *intersectMask); +VCAttribute *VCVisual_CreateData (VCVisualData *visualData); +int VCVisual_SetData (VCAttribute *attribute,VCVisualData *visualData); +int VCVisual_GetData (VCAttribute *attribute, VCVisualData *visualData); + +VCAttribute *VCEntity_AddVisual (VCEntity *entity, char *visual_name, VCDynamicVisual *DynamicVisual, + uint32 mode, char *lod, + char *frontMaterial, char *backMaterial, uint32 intersectMask); +VCAttribute *VCEntity_AddVisualData(VCEntity *entity, VCVisualData *visualData); +int VCVisual_SetGeometry (VCAttribute *attribute, char *visual_name); +int VCVisual_SetDynamicVisual (VCAttribute *attribute, VCDynamicVisual *dynamicVisual); +int VCVisual_SetMode (VCAttribute *attribute, uint32 mode); +int VCVisual_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVisual_SetFrontMaterial (VCAttribute *attribute, char *frontMaterial); +int VCVisual_SetBackMaterial (VCAttribute *attribute, char *backMaterial); +int VCVisual_SetLod (VCAttribute *attribute, char *lod); +int VCVisual_SetIntersectMask (VCAttribute *attribute, uint32 intersectMask); +int VCVisual_ModifyIntersectMask (VCAttribute *attribute, uint32 setIntersectMask, + uint32 clearIntersectMask); + +int VCVisual_GetGeometry (VCAttribute *attribute, char **visual_name); +int VCVisual_GetDynamicVisual (VCAttribute *attribute, VCDynamicVisual **dynamicVisual); +int VCVisual_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVisual_GetFrontMaterial (VCAttribute *attribute, char **frontMaterial); +int VCVisual_GetBackMaterial (VCAttribute *attribute, char **backMaterial); +int VCVisual_GetLod (VCAttribute *attribute, char **lod); +int VCVisual_GetIntersectMask (VCAttribute *attribute, uint32 *intersectMask); + +#define VCEntity_AddVisualGeometry(e,g) VCEntity_AddVisual(e, g, NULL, VC_VISIBLE | VC_RMODE_POLYGONAL, NULL, NULL, NULL, 0xffffffff) +#define VCEntity_DetachVisual(e,a) VCEntity_DetachAttribute(e,a) +#define VCVisual_CreateGeometry(g) VCVisual_Create( g, NULL, VC_VISIBLE|VC_RMODE_POLYGONAL, NULL, NULL, NULL, NULL) +#define VCVisual_Delete(a) VCAttribute_Delete(a) + + +VCAttribute *VCBodyPart_Create (char *bodyPart_name, uint32 actorId); +VCAttribute *VCBodyPart_CreateData (VCBodyPartData *bodyPart); +VCAttribute *VCEntity_AddBodyPartData(VCEntity *entity, VCBodyPartData *data); +VCAttribute *VCEntity_AddBodyPart (VCEntity *entity, char *bodyPart_name, uint32 actorId); +int VCBodyPart_Set (VCAttribute *attribute, char *bodyPart_name, + uint32 *actorId); +int VCBodyPart_SetData (VCAttribute *attribute, VCBodyPartData *bodyPart); +int VCBodyPart_SetName (VCAttribute *attribute, char *name); +int VCBodyPart_Get (VCAttribute *attribute, char **bodyPart_name, + uint32 *actorId); +int VCBodyPart_GetData (VCAttribute *attribute, VCBodyPartData *bodyPart); +int VCBodyPart_GetName (VCAttribute *attribute, char **name); +int VCBodyPart_GetActorId (VCAttribute *attribute, uint32 *actorId); + +#define VCEntity_DetachBodyPart(e,a) VCEntity_DetachAttribute(e, a) +#define VCBodyPart_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCPickObject_Create (VCEntity *entity, uint32 mode, uint32 actorId); +VCAttribute *VCPickObject_CreateData (VCPickObjectData *pickData); +int VCPickObject_Set (VCAttribute *attribute, VCEntity *entity, + uint32 setMode, uint32 clearMode, uint32 *actorId); +int VCPickObject_SetData (VCAttribute *attribute, VCPickObjectData *pickData); +int VCPickObject_Get (VCAttribute *attribute, VCEntity **entity, + uint32 *mode, uint32 *actorId); +int VCPickObject_GetData (VCAttribute *attribute, VCPickObjectData *pickData); +VCAttribute *VCEntity_AddPickObjectData(VCEntity *entity, VCPickObjectData *data); +VCAttribute *VCEntity_AddPickObject (VCEntity *entity, VCEntity *pickingEntity, uint32 mode, + uint32 pickActorId); + +#define VCEntity_DetachPickObject(e,a) VCEntity_DetachAttribute(e,a) +#define VCPickObject_Delete(a) VCAttribute_Delete(a) + + + +int VCPickObject_SetMode (VCAttribute *attribute, uint32 mode); +int VCPickObject_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCPickObject_SetPickingEntity (VCAttribute *attribute, VCEntity *entity); +int VCPickObject_SetActorId (VCAttribute *attribute, uint32 actorId); +int VCPickObject_GetMode (VCAttribute *attribute, uint32 *mode); +int VCPickObject_GetPickingEntity (VCAttribute *attribute, VCEntity **entity); +int VCPickObject_GetActorId (VCAttribute *attribute, uint32 *actorId); + + +VCAttribute *VCBoundary_Create (char *geometry, VCDynamicVisual *dynamicVisual, float32 bounds[VC_BOUND_SIZE], + uint32 mode, char *lod , int numCollisions); +VCAttribute *VCBoundary_CreateData (VCBoundaryData *boundaryData); +int VCBoundary_Set (VCAttribute *attribute, char *geometry, VCDynamicVisual *dynamicVisual, + float32 bounds[VC_BOUND_SIZE], uint32 setMode, uint32 clearMode, char *lod , + int32 *numberCollisions); +int VCBoundary_SetData (VCAttribute *attribute, VCBoundaryData *boundaryData); +int VCBoundary_Get (VCAttribute *attribute, char **geometry, VCDynamicVisual **dynamicVisual, + float32 bounds[VC_BOUND_SIZE], uint32 *mode, char **lod, int32 *numberCollisions, + VCCollision **collision); +int VCBoundary_GetData (VCAttribute *attribute, VCBoundaryData *boundaryData); +VCAttribute *VCEntity_AddBoundaryData(VCEntity *entity, VCBoundaryData *data); +VCAttribute *VCEntity_AddBoundary (VCEntity *entity, char *geometry, VCDynamicVisual *dynamicVisual, + float32 bounds[VC_BOUND_SIZE], uint32 mode, char *lod, int numCollisions ); +int VCBoundary_Delete(VCAttribute *attribute); + +#define VCEntity_DetachBoundary(e,a) VCEntity_DetachAttribute(e, a) +#define VCBoundary_CreateBbox(g) VCBoundary_Create(g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_BBOX, NULL, 1) +#define VCBoundary_CreateRadius(g) VCBoundary_Create(g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_RADIUS, NULL, 1) +#define VCBoundary_CreateGeometry(g) VCBoundary_Create(g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_GEOMETRY, NULL, 1) +#define VCEntity_AddBoundaryBbox(e,g) VCEntity_AddBoundary(e,g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_BBOX, NULL, 1) +#define VCEntity_AddBoundaryRadius(e,g) VCEntity_AddBoundary(e, g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_RADIUS, NULL, 1) +#define VCEntity_AddBoundaryGeometry(e,g) VCEntity_AddBoundary(e, g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_GEOMETRY, NULL, 1) + + +int VCBoundary_ModifyMode(VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCBoundary_SetGeometry(VCAttribute *attribute, char *geometry); +int VCBoundary_SetDynamicVisual(VCAttribute *attribute, VCDynamicVisual *dynamicGeometry); +int VCBoundary_SetBounds(VCAttribute *attribute, float32 bounds[VC_BOUND_SIZE]); +int VCBoundary_SetMode(VCAttribute *attribute, uint32 mode); +int VCBoundary_SetLod(VCAttribute *attribute, char *lod); +int VCBoundary_SetNumberCollisions(VCAttribute *attribute, int32 numberCollisions); +int VCBoundary_GetGeometry(VCAttribute *attribute, char **geometry); +int VCBoundary_GetBounds(VCAttribute *attribute, float32 bounds[VC_BOUND_SIZE]); +int VCBoundary_GetMode(VCAttribute *attribute, uint32 *mode); +int VCBoundary_GetLod(VCAttribute *attribute, char **lod); +int VCBoundary_GetNumberCollisions(VCAttribute *attribute, int32 *numberCollisions); +int VCBoundary_GetCollision(VCAttribute *attribute, VCCollision **collision); +int VCBoundary_GetDynamicVisual(VCAttribute *attribute, VCDynamicVisual **dynamicGeometry); +void *VCBoundary_AttachCollisionCreateCallback(VCAttribute *boundary, VCCollision_Func func, void *data); +void *VCBoundary_AttachCollisionUpdateCallback(VCAttribute *boundary, VCCollision_Func func, void *data); +void *VCBoundary_AttachCollisionDeleteCallback(VCAttribute *boundary, VCCollision_Func func, void *data); +int VCBoundary_DetachCollisionCreateCallback(VCAttribute *boundary, void *callbackHandle); +int VCBoundary_DetachCollisionUpdateCallback(VCAttribute *boundary, void *callbackHandle); +int VCBoundary_DetachCollisionDeleteCallback(VCAttribute *boundary, void *callbackHandle); + +VCAttribute *VCLight_Create (uint32 mode, VCColour colour, float exponent, float theta); +VCAttribute *VCLight_CreateData (VCLightData *lightData); +int VCLight_Get (VCAttribute *attribute, uint32 *mode, VCColour colour, + float *exponent, float *theta); +int VCLight_GetData (VCAttribute *attribute, VCLightData *lightData); +VCAttribute *VCEntity_AddLightData(VCEntity *entity, VCLightData *data); +VCAttribute *VCEntity_AddLight (VCEntity *entity, uint32 mode, float32 *colour, + float exponent, float theta); +int VCLight_Set (VCAttribute *attribute, uint32 setMode, uint32 clearMode, + VCColour colour, float *exponent, float *theta); +int VCLight_SetData (VCAttribute *attribute, VCLightData *lightData); +int VCLight_SetMode (VCAttribute *attribute, uint32 mode); +int VCLight_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCLight_SetColour (VCAttribute *attribute, VCColour colour); +int VCLight_SetUmbra (VCAttribute *attribute, float32 exponent, float theta); + +int VCLight_GetMode (VCAttribute *attribute, uint32 *mode); +int VCLight_GetColour (VCAttribute *attribute, VCColour colour); +int VCLight_GetUmbra (VCAttribute *attribute, float32 *exponent, float32 *theta); + +#define VCEntity_DetachLight(e,a) VCEntity_DetachAttribute(e,a) +#define VCLight_Delete(a) VCAttribute_Delete(a) +#define VCLight_SetColor(a,c) VCLight_SetColour(a,c) +#define VCLight_GetColor(a,c) VCLight_GetColour(a,c) + +#define VCEntity_AddLightDirectional(e,c) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_DIRECTIONAL, c, 0.0f, 0.0f) +#define VCEntity_AddLightAmbient(e,c) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_AMBIENT, c, 0.0f, 0.0f) +#define VCEntity_AddLightPoint(e,c) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_POINT, c, 0.0f, 0.0f) +#define VCEntity_AddLightSpot(e,c,x,t) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_SPOT, c, x, t) + +#define VCLight_CreateDirectional(c) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_DIRECTIONAL, c, 0.0f, 0.0f) +#define VCLight_CreateAmbient(c) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_AMBIENT, c, 0.0f, 0.0f) +#define VCLight_CreatePoint(c) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_POINT, c, 0.0f, 0.0f) +#define VCLight_CreateSpot(c,x,t) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_SPOT, c, x, t) + +VCAttribute *VCAudio_Create (char *voice, float32 gain, uint8 velocity, + uint32 mode, int32 loopCnt, int8 priority, + char *radiatorName, char *radiatorFileName); +VCAttribute *VCEntity_AddAudioData(VCEntity *entity, VCAudioData *data); +VCAttribute *VCEntity_AddAudio (VCEntity *entity, char *voice, float32 gain, uint8 velocity, + uint32 mode, int32 loopCnt, int8 priority, + char * radiatorName, char *radiatorFileName); +int VCAudio_Set (VCAttribute *attribute, char *voice, + float32 *gain, uint8 *velocity, uint32 setMode, + uint32 clearMode, uint8 play, int32 *loopCnt, int8 *priority, + char *radiatorName, char *radiatorFileName); +int VCAudio_Get (VCAttribute *attribute, char **voice, + float32 *gain, uint8 *velocity, uint32 *mode, + int32 *loopCnt, int8 *priority, + char **radiatorName, char **radiatorFileName); +VCAttribute *VCAudio_CreateData (VCAudioData *audioData); +int VCAudio_GetData (VCAttribute *attribute, VCAudioData *audioData); +int VCAudio_SetData (VCAttribute *attribute, VCAudioData *audioData); + +int VCAudio_SetVoice (VCAttribute *attribute, char *voice); +int VCAudio_SetMode (VCAttribute *attribute, uint32 mode); +int VCAudio_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCAudio_SetGain (VCAttribute *attribute, float32 gain); +int VCAudio_SetVelocity (VCAttribute *attribute, uint8 velocity); +int VCAudio_SetLoopCount (VCAttribute *attribute, int32 loopCnt); +int VCAudio_SetPriority (VCAttribute *attribute, int8 priority); +int VCAudio_SetRadiatorName(VCAttribute *attribute, char *radiator); +int VCAudio_SetRadiatorFile(VCAttribute *attribute, char *radiator); +int VCAudio_Start (VCAttribute *attribute); +int VCAudio_Stop (VCAttribute *attribute); + +int VCAudio_GetVoice (VCAttribute *attribute, char **voice); +int VCAudio_GetMode (VCAttribute *attribute, uint32 *mode); +int VCAudio_GetGain (VCAttribute *attribute, float32 *gain); +int VCAudio_GetVelocity (VCAttribute *attribute, uint8 *velocity); +int VCAudio_GetLoopCount (VCAttribute *attribute, int32 *loopCount); +int VCAudio_GetPriority (VCAttribute *attribute, int8 *priority); +int VCAudio_GetRadiatorName(VCAttribute *attribute, char **radiator); +int VCAudio_GetRadiatorFile(VCAttribute *attribute, char **radiator); + + +#define VCEntity_AddAudioVoice(e,v) VCEntity_AddAudio(e, v, 0, 80, 0, 1, 0, NULL, NULL) +#define VCEntity_DetachAudio(e,a) VCEntity_DetachAttribute(e,a) +#define VCAudio_CreateVoice(v) VCAudio_Create( v, 0, 80, 0, 1, 0, NULL, NULL) +#define VCAudio_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCConstraints_Create (uint32 mode, uint32 flags, float32 points[6], + float32 rotation[6]); +VCAttribute *VCConstraints_CreateData (VCConstraintsData *constraintsData); +int VCConstraints_Get (VCAttribute *attribute, uint32 *mode, uint32 *flags, + float32 points[6], float32 rotation[6]); +int VCConstraints_GetData (VCAttribute *attribute, VCConstraintsData *constraintsData); + +VCAttribute *VCEntity_AddConstraintsData(VCEntity *entity, VCConstraintsData *data); +VCAttribute *VCEntity_AddConstraints(VCEntity *entity, uint32 mode, uint32 flags, + float32 points[6], float32 rotation[6]); +int VCConstraints_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, uint32 setFlags, uint32 clearFlags, + float32 points[6], float32 rotation[6]); +int VCConstraints_SetData (VCAttribute *attribute, VCConstraintsData *constraintsData); + +int VCConstraints_SetMode (VCAttribute *attribute, uint32 mode); +int VCConstraints_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCConstraints_ModifyFlags (VCAttribute *attribute, uint32 setFlags, uint32 clearFlags); +int VCConstraints_SetFlags (VCAttribute *attribute, uint32 flags); +int VCConstraints_SetPoint (VCAttribute *attribute, float32 point[6]); +int VCConstraints_SetRotation (VCAttribute *attribute, float32 rotation[6]); +int VCConstraints_GetMode (VCAttribute *attribute, uint32 *mode); +int VCConstraints_GetFlags (VCAttribute *attribute, uint32 *flags); +int VCConstraints_GetPoint (VCAttribute *attribute, float32 point[6]); +int VCConstraints_GetRotation (VCAttribute *attribute, float32 rotation[6]); + + + + + +VCAttribute *VCEntity_AddConstraintsHinge(VCEntity *entity, uint32 axis, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsHingeX(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsHingeY(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsHingeZ(VCEntity *entity, float32 min, float32 max); + +VCAttribute *VCEntity_AddConstraintsTranslate(VCEntity *entity, uint32 axis, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsTranslateX(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsTranslateY(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsTranslateZ(VCEntity *entity, float32 min, float32 max); + +VCAttribute *VCEntity_AddConstraintsRotate(VCEntity *entity, uint32 axis, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsRotateX(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsRotateY(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsRotateZ(VCEntity *entity, float32 min, float32 max); + +VCAttribute *VCConstraints_CreateHinge(uint32 axis, float32 min, float32 max); +VCAttribute *VCConstraints_CreateHingeX(float32 min, float32 max); +VCAttribute *VCConstraints_CreateHingeY(float32 min, float32 max); +VCAttribute *VCConstraints_CreateHingeZ(float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslate(uint32 axis, float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslateX(float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslateY(float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslateZ(float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotate(uint32 axis, float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotateX(float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotateY(float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotateZ(float32 min, float32 max); + +#define VCEntity_DetachConstraints(e,a) VCEntity_DetachAttribute(e,a) +#define VCConstraints_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCVisualResource_Create (char *name, uint32 mode, float32 frameRate, float32 iod, + float32 convergence, VCColour backGround, + float32 nearClip, float32 farClip, VCColour fogColour, + float32 nearFlog, float32 farFog, float32 lodScale, + uint32 actorId); +VCAttribute *VCVisualResource_CreateData (VCVisualResourceData *visualResource); +int VCVisualResource_Get (VCAttribute *attribute, char **name, uint32 *mode, + float32 *frameRate, float32 *iod, float32 *convergence, + VCColour backGround, float32 *nearClip, float32 *farClip, + VCColour fogColour, float32 *nearFog, float32 *farFog, + float32 *lodScale, uint32 *actorId); +int VCVisualResource_GetData (VCAttribute *attribute, VCVisualResourceData *visualResource); +int VCVisualResource_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *frameRate, float32 *iod, + float32 *convergence, VCColour backGround, + float32 *nearClip, float32 *farClip, VCColour fogColour, + float32 *nearFog, float32 *farFog, float32 *lodScale); +int VCVisualResource_SetData (VCAttribute *attribute, VCVisualResourceData *visualResource); +VCAttribute *VCEntity_AddVisualResourceData(VCEntity *entity, VCVisualResourceData *data); +VCAttribute *VCEntity_AddVisualResource (VCEntity *entity, char *name, uint32 mode, + float32 frameRate, float32 iod, float32 convergence, + VCColour backGround, float32 nearClip, float32 farClip, + VCColour fogColour, float32 nearFlog, float32 farFog, + float32 lodScale, uint32 actorId); + +#define VCEntity_DetachVisualResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCVisualResource_Delete(a) VCAttribute_Delete(a) + +int VCVisualResource_SetMode (VCAttribute *attribute, uint32 mode); +int VCVisualResource_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVisualResource_SetFrameRate (VCAttribute *attribute, float32 frameRate); +int VCVisualResource_SetIod (VCAttribute *attribute, float32 iod); +int VCVisualResource_SetConvergence (VCAttribute *attribute, float32 convergence); +int VCVisualResource_SetBackground (VCAttribute *attribute, VCColour backGround); +int VCVisualResource_SetNearClip (VCAttribute *attribute, float32 nearClip); +int VCVisualResource_SetFarClip (VCAttribute *attribute, float32 farClip); +int VCVisualResource_SetFogColour (VCAttribute *attribute, VCColour fogColour); +int VCVisualResource_SetNearFog (VCAttribute *attribute, float32 nearFog); +int VCVisualResource_SetFarFog (VCAttribute *attribute, float32 farFog); +int VCVisualResource_SetLodScale (VCAttribute *attribute, float32 lodScale); +int VCVisualResource_GetName (VCAttribute *attribute, char **name); +int VCVisualResource_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVisualResource_GetFrameRate (VCAttribute *attribute, float32 *frameRate); +int VCVisualResource_GetIod (VCAttribute *attribute, float32 *iod); +int VCVisualResource_GetConvergence (VCAttribute *attribute, float32 *convergence); +int VCVisualResource_GetBackground (VCAttribute *attribute, VCColour backGround); +int VCVisualResource_GetNearClip (VCAttribute *attribute, float32 *nearClip); +int VCVisualResource_GetFarClip (VCAttribute *attribute, float32 *farClip); +int VCVisualResource_GetFogColour (VCAttribute *attribute, VCColour fogColour); +int VCVisualResource_GetNearFog (VCAttribute *attribute, float32 *nearFog); +int VCVisualResource_GetFarFog (VCAttribute *attribute, float32 *farFog); +int VCVisualResource_GetLodScale(VCAttribute *attribute, float32 *lodScale); +int VCVisualResource_GetActorId(VCAttribute *attribute, uint32 *actorId); + +#define VCVisualResource_SetFogColor(a,c) VCVisualResource_SetFogColour(a,c) +#define VCVisualResource_GetFogColor(a,c) VCVisualResource_GetFogColour(a,c) + +VCAttribute *VCAudioResource_Create (char *name, uint32 mode, float32 iad, float32 volume, + float32 spreadingRollOff, float32 atmosAbsorb,char *hrtf, + char *resourceFileName); +VCAttribute *VCAudioResource_CreateData (VCAudioResourceData *audioData); +VCAttribute *VCEntity_AddAudioResourceData(VCEntity *entity, VCAudioResourceData *data); +VCAttribute *VCEntity_AddAudioResource (VCEntity *entity, char *name, uint32 mode, float32 iad, + float32 volume, float32 spreadingRollOff, float32 atmosAbsorb, + char *hrtf, char *resourceFileName); +int VCAudioResource_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *iad, float32 *volume, + float32 *spreadingRollOff, float32 *atmosphericAbsorption, + char *hrtf, char *resourceFileName); +int VCAudioResource_SetData (VCAttribute *attribute,VCAudioResourceData *audioData); +int VCAudioResource_Get (VCAttribute *attribute, char **name, uint32 *mode, + float32 *iad, float32 *volume, + float32 *spreadingRollOff, float32 *atmosphericAbsorption, + char **hrtf, char **resourceFileName); +int VCAudioResource_GetData (VCAttribute *attribute,VCAudioResourceData *audioData); +#define VCEntity_DetachAudioResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCAudioResource_Delete(a) VCAttribute_Delete(a) + +int VCAudioResource_SetIad (VCAttribute *attribute, float32 iad); +int VCAudioResource_SetMode (VCAttribute *attribute, uint32 mode); +int VCAudioResource_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCAudioResource_SetVolume (VCAttribute *attribute, float32 volume); +int VCAudioResource_SetHrtf (VCAttribute *attribute, char *hrtf); +int VCAudioResource_SetResourceFileName (VCAttribute *attribute, char *resourceName); +int VCAudioResource_SetSpreadingRollOff (VCAttribute *attribute, float32 spreadingRollOff); +int VCAudioResource_SetAtmosphericAbsorption (VCAttribute *attribute, + float32 atmosphericAbsorption); + +int VCAudioResource_GetName (VCAttribute *attribute, char **name); +int VCAudioResource_GetMode (VCAttribute *attribute, uint32 *mode); +int VCAudioResource_GetIad (VCAttribute *attribute, float32 *iad); +int VCAudioResource_GetVolume (VCAttribute *attribute, float32 *volume); +int VCAudioResource_GetHrtf (VCAttribute *attribute, char **hrtf); +int VCAudioResource_GetResourceFileName (VCAttribute *attribute, char **resourceName); +int VCAudioResource_GetSpreadingRollOff (VCAttribute *attribute, + float32 *spreadingRollOff); +int VCAudioResource_GetAtmosphericAbsorption (VCAttribute *attribute, + float32 *atomsphericAbsorption); + + + +VCAttribute *VCInputResource_Create (char *name, uint32 mode, VCInput *input); +VCAttribute *VCInputResource_CreateData (VCInputResourceData *inputData); +VCAttribute *VCEntity_AddInputResourceData(VCEntity *entity, VCInputResourceData *data); +VCAttribute *VCEntity_AddInputResource (VCEntity *entity, char *name, uint32 mode, VCInput *input); +int VCInputResource_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, VCInput *input); +int VCInputResource_SetData (VCAttribute *attribute, VCInputResourceData *inputData); +int VCInputResource_Get (VCAttribute *attribute, char **name, + uint32 *mode, VCInput **input); +int VCInputResource_GetData (VCAttribute *attribute, VCInputResourceData *inputData); +int VCInputResource_SetMode (VCAttribute *attribute, uint32 mode); +int VCInputResource_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCInputResource_GetName (VCAttribute *attribute, char **name); +int VCInputResource_GetMode (VCAttribute *attribute, uint32 *mode); +int VCInputResource_GetInput (VCAttribute *attribute, VCInput **input); + + +#define VCEntity_DetachInputResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCInputResource_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCSensorResource_Create (char *name, uint32 mode, VCTracker *tracker, uint32 sensorId, + float32 scaleTranslate[3], float32 scaleRotate[3], + float32 translationCurveOrder[3], float32 rotationCurveOrder[3], + dmPoint prePosition, dmPoint postPosition, dmEuler preEuler, + dmEuler postEuler, float32 relativeSphere[6], VCPosition *position, + VCConstraintsData *constraints); +VCAttribute *VCSensorResource_CreateData (VCSensorResourceData *sensorData); +VCAttribute *VCEntity_AddSensorResourceData(VCEntity *entity, VCSensorResourceData *data); +VCAttribute *VCEntity_AddSensorResource (VCEntity *entity, char *name, uint32 mode, VCTracker *tracker, + uint32 sensorId, float32 scaleTranslate[3], + float32 scaleRotate[3],float32 translationCurveOrder[3], + float32 rotationCurveOrder[3], dmPoint prePosition, + dmPoint postPosition, dmEuler preEuler, dmEuler postEuler, + float32 relativeSphere[6], + VCPosition *position, VCConstraintsData *constraints); + +int VCSensorResource_Set (VCAttribute *attribute, uint32 setMode, uint32 clearMode, + float32 scaleTranslate[3], + float32 scaleRotate[3], float32 translationCurveOrder[3], + float32 rotationCurveOrder[3], dmPoint prePosition, + dmPoint postPosition, dmEuler preEuler, dmEuler postEuler, + float32 relativeSphere[6], VCPosition *position, + VCConstraintsData *constraints); +int VCSensorResource_SetData (VCAttribute *attribute, VCSensorResourceData *sensorData); +int VCSensorResource_Get (VCAttribute *attribute, char **name, + uint32 *mode, VCTracker **tracker, uint32 *sensorId, + float32 scaleTranslate[3], float32 scaleRotate[3], + float32 translationCurveOrder[3], float32 rotationCurveOrder[3], + dmPoint prePosition, dmPoint postPosition, dmEuler preEuler, + dmEuler postEuler, float32 relativeSphere[6], + VCPosition **position, VCConstraintsData *constraints); +int VCSensorResource_GetData (VCAttribute *attribute, VCSensorResourceData *sensorData); + + +#define VCEntity_DetachSensorResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCSensorResource_Delete(a) VCAttribute_Delete(a) + +int VCSensorResource_ModifyMode(VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCSensorResource_SetMode(VCAttribute *attribute, uint32 mode); +int VCSensorResource_SetTranslationScale(VCAttribute *attribute, float32 scaleTranslate[3]); +int VCSensorResource_SetRotationScale(VCAttribute *attribute, float32 scaleRotate[3]); +int VCSensorResource_SetTranslationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_SetRotationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_SetPrePosition(VCAttribute *attribute, dmPoint prePosition); +int VCSensorResource_SetPostPosition(VCAttribute *attribute, dmPoint postPosition); +int VCSensorResource_SetPreEuler(VCAttribute *attribute, dmEuler preEuler); +int VCSensorResource_SetPostEuler(VCAttribute *attribute, dmEuler postEuler); +int VCSensorResource_SetRelativeSphere(VCAttribute *attribute, float32 relativeSphere[6]); +int VCSensorResource_SetPosition(VCAttribute *attribute, VCPosition *pos); +int VCSensorResource_SetConstraints(VCAttribute *attribute, VCConstraintsData *constraints); +int VCSensorResource_GetName(VCAttribute *attribute, char **name); +int VCSensorResource_GetMode(VCAttribute *attribute, uint32 *mode); +int VCSensorResource_GetTracker(VCAttribute *attribute, VCTracker **tracker); +int VCSensorResource_GetSensorId(VCAttribute *attribute, uint32 *sensorId); +int VCSensorResource_GetTranslationScale(VCAttribute *attribute, float32 scaleTranslate[3]); +int VCSensorResource_GetRotationScale(VCAttribute *attribute, float32 scaleRotate[3]); +int VCSensorResource_GetTranslationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_GetRotationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_GetPrePosition(VCAttribute *attribute, dmPoint prePosition); +int VCSensorResource_GetPostPosition(VCAttribute *attribute, dmPoint postPosition); +int VCSensorResource_GetPreEuler(VCAttribute *attribute, dmEuler preEuler); +int VCSensorResource_GetPostEuler(VCAttribute *attribute, dmEuler postEuler); +int VCSensorResource_GetRelativeSphere(VCAttribute *attribute, float32 relativeSphere[6]); +int VCSensorResource_GetPosition(VCAttribute *attribute, VCPosition **pos); +int VCSensorResource_GetConstraints(VCAttribute *attribute, VCConstraintsData *constraints); + + +VCAttribute *VCVectorIntersect_Create (uint32 mode, float32 length, uint32 mask, + int32 numIntersections); +VCAttribute *VCVectorIntersect_CreateData (VCVectorIntersectData *intersectData); + +VCAttribute *VCEntity_AddVectorIntersectData(VCEntity *entity, VCVectorIntersectData *data); +VCAttribute *VCEntity_AddVectorIntersect (VCEntity *entity, uint32 mode, float32 length, + uint32 mask, int32 numIntersections); +int VCVectorIntersect_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *length, uint32 setMask, + uint32 clearMaks, int32 *numIntersections); +int VCVectorIntersect_SetData (VCAttribute *attribute, VCVectorIntersectData *intersectData); +int VCVectorIntersect_Get (VCAttribute *attribute, uint32 *mode, + float32 *length, uint32 *mask, int32 *numIntersections, + VCIntersection **intersection); +int VCVectorIntersect_GetData (VCAttribute *attribute, VCVectorIntersectData *intersectData); +int VCVectorIntersect_Delete(VCAttribute *attribute); +#define VCEntity_DetachVectorIntersect(e,a) VCEntity_DetachAttribute(e,a) + + +int VCVectorIntersect_SetMode (VCAttribute *attribute, uint32 mode); +int VCVectorIntersect_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVectorIntersect_SetLength (VCAttribute *attribute, float32 kength); +int VCVectorIntersect_SetIntersectMask (VCAttribute *attribute, uint32 mask); +int VCVectorIntersect_ModifyIntersectMask (VCAttribute *attribute, uint32 setMask, + uint32 clearMask); +int VCVectorIntersect_SetNumberIntersections (VCAttribute *attribute, int32 numIntersections); +int VCVectorIntersect_SetIntersection (VCAttribute *attribute, VCIntersection *intersection); + +int VCVectorIntersect_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVectorIntersect_GetLength (VCAttribute *attribute, float32 *length); +int VCVectorIntersect_GetIntersectMask (VCAttribute *attribute, uint32 *mask); +int VCVectorIntersect_GetNumberIntersections (VCAttribute *attribute, int32 numIntersections); +int VCVectorIntersect_GetIntersection (VCAttribute *attribute, VCIntersection **intersection); +void *VCVectorIntersect_AttachIntersectionCreateCallback(VCAttribute *intersect, + VCIntersection_Func func, void *data); +void *VCVectorIntersect_AttachIntersectionUpdateCallback(VCAttribute *intersect, + VCIntersection_Func func, void *data); +void *VCVectorIntersect_AttachIntersectionDeleteCallback(VCAttribute *intersect, + VCIntersection_Func func, void *data); + +int VCVectorIntersect_DetachIntersectionCreateCallback(VCAttribute *intersect, void *callbackHandle); +int VCVectorIntersect_DetachIntersectionUpdateCallback(VCAttribute *intersect, void *callbackHandle); + +int VCVectorIntersect_DetachIntersectionDeleteCallback(VCAttribute *intersect, void *callbackHandle); + + + + + + +VCAttribute *VCVisualEffect_Create (uint32 mode, uint32 type, dmPoint offset, float32 *data, + char *texture); +VCAttribute *VCVisualEffect_CreateData (VCVisualEffectData *visEffectData); +VCAttribute *VCEntity_AddVisualEffectData(VCEntity *entity, VCVisualEffectData *data); +VCAttribute *VCEntity_AddVisualEffect (VCEntity *entity, uint32 mode, uint32 type, + dmPoint offset, float *data, char *texture); +int VCVisualEffect_Set (VCAttribute *attribute, uint32 setMode, uint32 clearMode, + uint32 *type, dmPoint offset, float data[72], char *texture); +int VCVisualEffect_SetData (VCAttribute *attribute,VCVisualEffectData *visEffectData); +int VCVisualEffect_Get (VCAttribute *attribute, uint32 *mode, uint32 *type, + dmPoint offset, float32 data[72], char **texture); +int VCVisualEffect_GetData (VCAttribute *attribute,VCVisualEffectData *visEffectData); +#define VCEntity_DetachVisualEffect(e,a) VCEntity_DetachAttribute(e,a) +#define VCVisualEffect_Delete(a) VCAttribute_Delete(a) +#define VCEntity_AddVisualEffectExplosion(e,t,o,te) VCEntity_AddVisualEffect(e,VC_VISUALEFFECT_MODE_EXPLOSION,t,o,NULL,te) +#define VCVisualEffect_CreateExplosion(t,o,te) VCVisualEffect_Create(VC_VISUALEFFECT_MODE_EXPLOSION,t,o,NULL,te) +#define VCVisualEffect_StartExplosion(a,o) VCVisualEffect_Set(a,VC_VISUALEFFECT_ENABLE,0,NULL,o,NULL,NULL) + +int VCVisualEffect_SetMode (VCAttribute *attribute, uint32 mode); +int VCVisualEffect_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVisualEffect_SetType (VCAttribute *attribute, uint32 type); +int VCVisualEffect_SetOffset (VCAttribute *attribute, dmPoint offset); +int VCVisualEffect_SetInfo (VCAttribute *attribute, float32 info[72]); +int VCVisualEffect_SetTexture (VCAttribute *attribute, char *texture); + +int VCVisualEffect_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVisualEffect_GetType (VCAttribute *attribute, uint32 *type); +int VCVisualEffect_GetOffset (VCAttribute *attribute, dmPoint offset); +int VCVisualEffect_GetInfo (VCAttribute *attribute, float32 info[72]); +int VCVisualEffect_GetTexture (VCAttribute *attribute, char **texture); + + +VCAttribute *VCDynamics_Create (uint32 mode, float32 imass, float32 gmass, dmPoint centre, + float32 *iTensor, float32 spring, float32 damper, + float32 sFriction, float32 dFriction); +VCAttribute *VCDynamics_CreateData (VCDynamicsData *dynamicData); +int VCDynamics_Get (VCAttribute *attribute, uint32 *mode, float32 *imass, + float32 *gmass, dmPoint centre, float32 itensor[6], + float32 *spring, float32 *damper, float32 *sFriction, + float32 *dFricition); +int VCDynamics_GetData (VCAttribute *attribute, VCDynamicsData *dynamicData); +VCAttribute *VCEntity_AddDynamicsData(VCEntity *entity, VCDynamicsData *data); +VCAttribute *VCEntity_AddDynamics (VCEntity *entity, uint32 mode, float32 imass, float32 gmass, + dmPoint centre, float32 *iTensor, float32 spring, + float32 damper, float32 sFriction, float32 dFriction); +int VCDynamics_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *imass, float32 *gmass, + dmPoint centre, float32 *iTensor, float32 *spring, + float32 *damper, float32 *sFriction, float32 *dFriction); +int VCDynamics_SetData (VCAttribute *attribute, VCDynamicsData *dynamicData); +#define VCEntity_DetachDynamics(e,a) VCEntity_DetachAttribute(e,a) +#define VCDynamics_Delete(a) VCAttribute_Delete(a) + +int VCDynamics_SetMode (VCAttribute *attribute, uint32 mode); +int VCDynamics_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCDynamics_SetImass (VCAttribute *attribute, float32 imass); +int VCDynamics_SetGmass (VCAttribute *attribute, float32 gmass); +int VCDynamics_SetCentre (VCAttribute *attribute, dmPoint centre); +int VCDynamics_SetItensor (VCAttribute *attribute, float32 *itensor); +int VCDynamics_SetSpring (VCAttribute *attribute, float32 spring); +int VCDynamics_SetDamper (VCAttribute *attribute, float32 damper); +int VCDynamics_SetStaticFriction (VCAttribute *attribute, float32 sFriction); +int VCDynamics_SetDynamicFriction (VCAttribute *attribute, float32 dFriction); +int VCDynamics_GetMode (VCAttribute *attribute, uint32 *mode); +int VCDynamics_GetImass (VCAttribute *attribute, float32 *imass); +int VCDynamics_GetGmass (VCAttribute *attribute, float32 *gmass); +int VCDynamics_GetCentre (VCAttribute *attribute, dmPoint centre); +int VCDynamics_GetItensor (VCAttribute *attribute, float32 itensor[6]); +int VCDynamics_GetSpring (VCAttribute *attribute, float32 *spring); +int VCDynamics_GetDamper (VCAttribute *attribute, float32 *damper); +int VCDynamics_GetStaticFriction (VCAttribute *attribute, float32 *sFriction); +int VCDynamics_GetDynamicFriction (VCAttribute *attribute, float32 *dFriction); + + +VCAttribute *VCForce_Create (uint32 mode, dmVector force, dmPoint point); +VCAttribute *VCForce_CreateData (VCForceData *forceData); +int VCForce_Get (VCAttribute *attribute, uint32 *mode, dmVector force, dmPoint point); +int VCForce_GetData (VCAttribute *attribute, VCForceData *forceData); +VCAttribute *VCEntity_AddForceData(VCEntity *entity, VCForceData *data); +VCAttribute *VCEntity_AddForce (VCEntity *entity, uint32 mode, dmVector force, dmPoint point); +int VCForce_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, dmVector force, dmPoint point); +int VCForce_SetData (VCAttribute *attribute, VCForceData *forceData); + + + +#define VCEntity_DetachForce(e,a) VCEntity_DetachAttribute(e,a) +#define VCForce_Delete(a) VCAttribute_Delete(a) + +int VCForce_SetMode (VCAttribute *attribute, uint32 mode); +int VCForce_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCForce_SetForce (VCAttribute *attribute, dmVector force); +int VCForce_SetPoint (VCAttribute *attribute, dmPoint point); +int VCForce_GetMode (VCAttribute *attribute, uint32 *mode); +int VCForce_GetForce (VCAttribute *attribute, dmVector force); +int VCForce_GetPoint (VCAttribute *attribute, dmPoint point); + + + +VCAttribute *VCZone_Create (uint32 mode, uint32 actorMask); +VCAttribute *VCZone_CreateData (VCZoneData *zoneData); +int VCZone_Get (VCAttribute *attribute, uint32 *mode, uint32 *actorMask); +int VCZone_GetData (VCAttribute *attribute, VCZoneData *zoneData); +VCAttribute *VCEntity_AddZoneData(VCEntity *entity, VCZoneData *data); +VCAttribute *VCEntity_AddZone (VCEntity *entity, uint32 mode, uint32 actorMask); +int32 VCZone_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, uint32 setActorMask, uint32 clearActorMask); +int VCZone_SetData (VCAttribute *attribute, VCZoneData *zoneData); +#define VCEntity_DetachZone(e,a) VCEntity_DetachAttribute(e,a) +#define VCZone_Delete(a) VCAttribute_Delete(a) + +int VCZone_SetMode (VCAttribute *attribute, uint32 mode); +int VCZone_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCZone_SetActorMask (VCAttribute *attribute, uint32 mask); +int VCZone_ModifyActorMask (VCAttribute *attribute, uint32 setMask, uint32 clearMask); +int VCZone_GetMode(VCAttribute *attribute, uint32 *mode); +int VCZone_GetActorMask(VCAttribute *attribute, uint32 *mask); + + + +#endif /* _VCOBJECT_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCSTRUCT.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCSTRUCT.H new file mode 100644 index 0000000..57097e9 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCSTRUCT.H @@ -0,0 +1,215 @@ + +struct VCActorConfig +{ + char *actorName; + char *domainName; + char *domainExtName; + char *userName; + char *userDir; + char *logName; + char *configData; + int32 verbose; + int32 enable; + int32 testMode; + FILE *fpLog; +}; + +struct VCBodyCreate_CallbackData +{ + VCBody *body; +}; + +struct VCBodyAttribute_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + VCAttribute *attribute; +}; + +struct VCBodyPartCreate_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; +}; + +struct VCTimer_CallbackData +{ + uint32 dummy; +}; + + +struct VCExit_CallbackData +{ + uint32 dummy; +}; + +struct VCGroup_CallbackData +{ + uint32 operation; +}; + + + +struct VCBodyInput_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + uint32 keyCode; +}; + +struct VCBodyCollision_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + VCCollision *collision; +}; + +struct VCInput_UpdateCallbackData +{ + VCInput *input; + VCAttribute *inputResource; + uint32 keyCode; +}; + +struct VCInput_CallbackData +{ + VCInput *input; + VCAttribute *inputResource; + uint32 keyCode; +}; + + +struct VCEntityRelocate_CallbackData +{ + VCEntity *entity; + VCPositionData *pos; + uint32 flags; +}; + +struct VCEntityInvalid_CallbackData +{ + VCEntity *entity; +}; + +struct VCAttributeRelocate_CallbackData +{ + VCEntity *entity; + int32 index; + VCAttribute *attribute; + VCPositionData *pos; + uint32 flags; +}; + +struct VCEntityAttribute_CallbackData +{ + VCEntity *entity; + int32 index; + VCAttribute *attribute; +}; + +struct VCAttribute_CallbackData +{ + VCAttribute *attribute; +}; + +struct VCCollision_CallbackData +{ + VCCollision *collision; +}; + +struct VCIntersection_CallbackData +{ + VCIntersection *intersection; +}; + +struct VCMaterial_CallbackData +{ + VCMaterial *material; +}; + +struct VCRadiator_CallbackData +{ + VCRadiator *radiator; +}; + +struct VCXWindowId_CallbackData +{ + VCXWindowId *xwindowId; +}; + +struct VCVisualViewResource_CallbackData +{ + VCVisualViewResource *view; +}; + +struct VCPseudoGravity_CallbackData +{ + VCPseudoGravity *pseudoGravity; +}; + +struct VCResourceAllocate_CallbackData +{ + char *name; +}; + + +struct VCPosition_CallbackData +{ + VCPosition *position; +}; + +struct VCTracker_CallbackData +{ + VCTracker *tracker; +}; + +struct VCSync_CallbackData +{ + VCSync *sync; +}; + +struct VCCollideMonitor_CallbackData +{ + VCCollideMonitor *collideMonitor; +}; + +struct VCTrackerMonitor_CallbackData +{ + VCTrackerMonitor *trackerMonitor; +}; + +struct VCVisualMonitor_CallbackData +{ + VCVisualMonitor *visualMonitor; +}; + +struct VCTexture_CallbackData +{ + VCTexture *texture; +}; + +struct VCRamp_CallbackData +{ + VCRamp *ramp; +}; + +typedef struct +{ + char *configName; + uint32 debug; + char *nameExt; + int logging; + char *logExt; + char *domainName; + int testMode; + uint32 verbose; +}VCCommandLineOptions ; + + +struct VCEntityDrop_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + VCEntity *droppedEntity; +}; + diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCTYPES.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCTYPES.H new file mode 100644 index 0000000..9849304 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCTYPES.H @@ -0,0 +1,178 @@ +/*************************************************************************** + * + * PROJECT: dVS + * SUBSYSTEM: VC Toolkit. + * MODULE: VC Type definitions. + * + *************************************************************************** + * + * File: $RCSfile: vctypes.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:19 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctypes.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * + * FUNCTION: + * + * + * + ************************************************************************** + * * + * Copyright (c) 1992 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +#ifndef _VCTYPES_H +#define _VCTYPES_H + +typedef struct VCBody VCBody; +typedef struct VCEntity VCEntity; +typedef struct VCAttribute VCAttribute; +typedef struct VCCollision VCCollision; +typedef struct VCIntersection VCIntersection; +typedef struct VCMaterial VCMaterial; +typedef struct VCRadiator VCRadiator; +typedef struct VCXWindowId VCXWindowId; +typedef struct VCVisualViewResource VCVisualViewResource; +typedef struct VCPseudoGravity VCPseudoGravity; +typedef struct VCTexture VCTexture; +typedef struct VCRamp VCRamp; +typedef struct VCInput VCInput; +typedef struct VCPosition VCPosition; +typedef struct VCTracker VCTracker; +typedef struct VCSync VCSync; +typedef struct VCMonitor VCCollideMonitor; +typedef struct VCMonitor VCTrackerMonitor; +typedef struct VCMonitor VCVisualMonitor; +typedef struct VCDynamicVisual VCDynamicVisual; +typedef struct VCLod VCLod; +typedef struct VCGeogroup VCGeogroup; +typedef struct VCGeometry VCGeometry; +typedef struct VCConnectionList VCConnectionList; + + +typedef struct VCCollisionReport_Traverse VCCollisionReport_Traverse; +typedef struct VCIntersectionReport_Traverse VCIntersectionReport_Traverse; +typedef struct VCEntity_Traverse VCEntity_Traverse; +typedef struct VCActorConfig VCActorConfig; +typedef struct VCEntity_AttributeTraverse VCEntity_AttributeTraverse; +typedef struct VCAttribute_EntityTraverse VCAttribute_EntityTraverse; + +typedef struct VCBody_Traverse VCBody_Traverse; +typedef struct VCBody_AttributeTraverse VCBody_AttributeTraverse; +typedef struct VCVisualView_Traverse VCVisualView_Traverse; +typedef struct VCUserDataList VCUserDataList; + +typedef struct VCCallbackFunctions VCCallbackFunctions; +typedef struct VCBodyCreate_CallbackData VCBodyCreate_CallbackData; +typedef struct VCBodyInput_CallbackData VCBodyInput_CallbackData; +typedef struct VCBodyCollision_CallbackData VCBodyCollision_CallbackData; +typedef struct VCBodyAttribute_CallbackData VCBodyAttribute_CallbackData; +typedef struct VCBodyPartCreate_CallbackData VCBodyPartCreate_CallbackData; + +typedef struct VLSignalEvent VCSignal_CallbackData; +typedef struct VLStreamEvent VCStream_CallbackData; +typedef struct VCResourceAllocate_CallbackData VCResourceAllocate_CallbackData; +typedef struct VCCollision_CallbackData VCCollision_CallbackData; +typedef struct VCIntersection_CallbackData VCIntersection_CallbackData; +typedef struct VCMaterial_CallbackData VCMaterial_CallbackData; +typedef struct VCRadiator_CallbackData VCRadiator_CallbackData; +typedef struct VCXWindowId_CallbackData VCXWindowId_CallbackData; +typedef struct VCVisualViewResource_CallbackData VCVisualViewResource_CallbackData; +typedef struct VCPseudoGravity_CallbackData VCPseudoGravity_CallbackData; +typedef struct VCPosition_CallbackData VCPosition_CallbackData; +typedef struct VCTracker_CallbackData VCTracker_CallbackData; +typedef struct VCSync_CallbackData VCSync_CallbackData; +typedef struct VCCollideMonitor_CallbackData VCCollideMonitor_CallbackData; +typedef struct VCTrackerMonitor_CallbackData VCTrackerMonitor_CallbackData; +typedef struct VCVisualMonitor_CallbackData VCVisualMonitor_CallbackData; +typedef struct VCTexture_CallbackData VCTexture_CallbackData; +typedef struct VCRamp_CallbackData VCRamp_CallbackData; +typedef struct VCInput_CallbackData VCInput_CallbackData; +typedef struct VCInput_UpdateCallbackData VCInput_UpdateCallbackData; +typedef struct VCAttribute_CallbackData VCAttribute_CallbackData; +typedef struct VCEntityRelocate_CallbackData VCEntityRelocate_CallbackData; +typedef struct VCEntityInvalid_CallbackData VCEntityInvalid_CallbackData; +typedef struct VCAttributeRelocate_CallbackData VCAttributeRelocate_CallbackData; +typedef struct VCEntityAttribute_CallbackData VCAttributeInvalid_CallbackData; +typedef struct VCEntityAttribute_CallbackData VCEntityAttribute_CallbackData; +typedef struct VCEntityDrop_CallbackData VCEntityDrop_CallbackData; +typedef struct VCTimer_CallbackData VCTimer_CallbackData; +typedef struct VCExit_CallbackData VCExit_CallbackData; +typedef struct VCGroup_CallbackData VCGroup_CallbackData; +typedef float32 VCSpecular[4]; + +/* + * function types for general callback routines + */ + +typedef void (*VC_SignalFunc) (VCSignal_CallbackData *callbackData, void *data); +typedef void (*VC_ExitFunc) (VCExit_CallbackData *callbackData, void *data); +typedef void (*VC_GroupFunc) (VCGroup_CallbackData *callbackData, void *data); +typedef void (*VC_StreamFunc) (VCStream_CallbackData *streamData, void *data); +typedef void (*VC_CallbackFunc) (VLInstanceEvent *instanceData, void *data); + +/* + * function types for body routines + */ + +typedef void (*VC_VersionFunc) (FILE *fp); +typedef void (*VCBody_CreateFunc) (VCBodyCreate_CallbackData *bodyData, void *data); +typedef void (*VCBody_CreateBodyPartFunc) (VCBodyPartCreate_CallbackData *callbackData, void *data); +typedef void (*VCBody_AttributeFunc) (VCBodyAttribute_CallbackData *callbackData, void *data); +typedef void (*VCBody_InputFunc) (VCBodyInput_CallbackData *callbackData, void *data); +typedef void (*VCBody_CollisionFunc) (VCBodyCollision_CallbackData *callbackData, void *data); +typedef void (*VCEntity_DropFunc) (VCEntityDrop_CallbackData *callbackData, void *data); + +/* + * function types for Resource routines + */ + +typedef VCAttribute *(*VCResource_AllocateFunc) (VCResourceAllocate_CallbackData *callbackData, void *data); + +/* + * function types for vchierarchy routines + */ + +typedef void (*VCEntity_TraverseFunc) (VCEntity * entity, void *data); +typedef void (*VCEntity_Func) (VCEntity *entity, int32 index, void *data); +typedef void (*VCAttribute_Func) (VCAttribute_CallbackData *attributeData, void *data); +typedef void (*VCAttribute_RelocateFunc) (VCAttributeRelocate_CallbackData *entityData, void *data); +typedef void (*VCEntity_RelocateFunc) (VCEntityRelocate_CallbackData *entityData, void *data); +typedef void (*VCEntity_InvalidFunc) (VCEntityInvalid_CallbackData *entityData, void *data); +typedef void (*VCEntity_AttributeFunc) (VCEntityAttribute_CallbackData *attributeData, void *data); +typedef void (*VCAttribute_InvalidFunc) (VCAttributeInvalid_CallbackData *atttributeData, void *data); +typedef void (*VCCollision_Func) (VCCollision_CallbackData *callbackData, void *data); +typedef void (*VCIntersection_Func) (VCIntersection_CallbackData *callbackData, void *data); +typedef void (*VCMaterial_Func) (VCMaterial_CallbackData *attributeData, void *data); +typedef void (*VCRadiator_Func) (VCRadiator_CallbackData *attributeData, void *data); +typedef void (*VCXWindowId_Func) (VCXWindowId_CallbackData *attributeData, void *data); +typedef void (*VCVisualViewResource_Func) (VCVisualViewResource_CallbackData *attributeData, void *data); +typedef void (*VCPseudoGravity_Func) (VCPseudoGravity_CallbackData *attributeData, void *data); +typedef void (*VCPosition_Func) (VCPosition_CallbackData *attributeData, void *data); +typedef void (*VCTracker_Func) (VCTracker_CallbackData *attributeData, void *data); +typedef void (*VCSync_Func) (VCSync_CallbackData *attributeData, void *data); +typedef void (*VCCollideMonitor_Func) (VCCollideMonitor_CallbackData *attributeData, void *data); +typedef void (*VCTrackerMonitor_Func) (VCTrackerMonitor_CallbackData *attributeData, void *data); +typedef void (*VCVisualMonitor_Func) (VCVisualMonitor_CallbackData *attributeData, void *data); +typedef void (*VCInput_Func) (VCInput_CallbackData *attributeData, void *data); +typedef void (*VCInput_UpdateFunc) (VCInput_UpdateCallbackData *attributeData, void *data); +typedef void (*VCTexture_Func) (VCTexture_CallbackData *callbackData, void *data); +typedef void (*VCRamp_Func) (VCRamp_CallbackData *callbakData, void *data); +typedef void (*VCTimer_Func) (VCTimer_CallbackData *callbackData, void *data); + +typedef int (VCCallback_QueryFunc) (void *callbackQueryData, void *systemData, void *callbackData); + + + +#endif + + + diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VCVBOSE.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VCVBOSE.H new file mode 100644 index 0000000..fe24cca --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VCVBOSE.H @@ -0,0 +1,100 @@ +/*************************************************************************** + * <110793.1226> + * PROJECT: dVS + * SUBSYSTEM: + * MODULE: + * + *************************************************************************** + * + * File: $RCSfile: vcvbose.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:20 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcvbose.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * Creator: Jon Green. + * + * FUNCTION: + * + * + * $Log: vcvbose.h,v $ + * Revision 1.1 95/05/18 10:24:20 10:24:20 john (John Harvey) + * Initial revision + * + * Revision 1.1 1995/03/10 14:52:46 john + * Initial revision + * + * Revision 0.6 94/10/05 12:51:43 12:51:43 john (John Harvey) + * Save JH on holiday. - Jon. + * + * Revision 0.5 94/03/30 15:17:49 15:17:49 mark (Mark Greening) + * New VCActorInit and error routines + * + * Revision 0.4 1993/09/24 11:24:53 jon + * Release 2.0.4 + * + * Revision 1.1 93/07/28 14:12:08 jon + * Initial revision + * + * + ************************************************************************** + * * + * Copyright (c) 1992 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +/*--- Include Definitions */ + +#ifndef _VCVBOSE_H +#define _VCVBOSE_H 1 + +/*--- Include Files */ + +/*--- External References */ + +extern void __vcVerboseStart(int level); +extern void __vcDebugStart(int level, char *file, int line); +extern void __vcVerboseMessage(char *format, ...); +extern uint32 __vcverbose_level; +extern uint32 __vcdebug_level; + +/*--- Local Macro Definitions */ + +#define VC_Verbose(x,y) do { \ + if (__vcverbose_level & (x)) \ + { \ + __vcVerboseStart(x); \ + __vcVerboseMessage y; \ + } \ + } while (0) + +#ifdef NVCDEBUG +#undef VC_Debug +#define VC_Debug(x,y) ((void)0) + +#else +#define VC_Debug(x,y) do { \ + if (__vcdebug_level & (x)) \ + { \ + __vcDebugStart(x, __FILE__, __LINE__); \ + __vcVerboseMessage y; \ + } \ + } while (0) +#endif + +#define VCVerbose_SetLevel(x) (__vcverbose_level = (x)) +#define VCVerbose_GetLevel __vcverbose_level +#define VCDebug_SetLevel(x) (__vcdebug_level = (x)) +#define VCDebug_GetLevel __vcdebug_level + +/*--- Local Type Definitions */ + +/*--- Local Variable Declarations */ + +#endif /* _VCVBOSE_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VL.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VL.H new file mode 100644 index 0000000..1f230a6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VL.H @@ -0,0 +1,476 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: vl + * MODULE: vl.h + * + * File: $RCSfile: vl.h,v $ + * Revision: $Revision: 1.23 $ + * Date: $Date: 1995/05/18 09:43:47 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: vl.h,v 1.23 1995/05/18 09:43:47 jeff beta $ + * + * FUNCTION: + * + * This file contains all the external definitions needed to use + * the vl library. + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _VL_H +#define _VL_H + +#include + +#ifndef _VLTYPES_H +#include +#endif + +/* + * type for return of event info + */ +typedef union VLEventData VLEventData; +typedef struct VLInstanceEvent VLInstanceEvent; + +typedef struct VLSignalEvent VLSignalEvent; +typedef struct VLStreamEvent VLStreamEvent; +typedef struct VLInstInterestEvent VLInstInterestEvent; +typedef struct VLElemInterestEvent VLElemInterestEvent; +typedef struct VLElementConfirmEvent VLElementConfirmEvent; +typedef struct VLElemCreateEvent VLElemCreateEvent; +typedef struct VLTimeServiceEvent VLTimeServiceEvent; +typedef struct VLPeerEvent VLPeerEvent; +typedef struct VLBadEvent VLBadEvent; + + +struct VLInstanceEvent{ + ElementHandle handle; + InstanceNo ino; + int32 repCount; +}; + +struct VLSignalEvent{ + uint32 signal; +}; + +struct VLStreamEvent { + void *buf; + VLStreamId id; + int32 type; +}; + +struct VLInstInterestEvent{ + InstanceNo ino; + uint32 type; + ActorId actor; + EventQ queue; +}; + +struct VLElemInterestEvent{ + ElementHandle handle; + uint32 type; + ActorId actor; + EventQ queue; +}; + +struct VLElementConfirmEvent{ + ElementHandle reference; + ElementHandle confirmed; +}; + +struct VLElemCreateEvent{ + ElementHandle handle; + uint32 descSize; +}; + +struct VLTimeServiceEvent{ + VLTime time; + ActorId who; +}; + +struct VLPeerEvent{ + ActorId peer; +}; + +struct VLBadEvent { + VLStatus stat; +}; + +union VLEventData { + VLInstanceEvent instanceEvent; + VLSignalEvent signalEvent; + VLStreamEvent streamEvent; + VLInstInterestEvent instInterestEvent; + VLElemInterestEvent elemInterestEvent; + VLElementConfirmEvent elementConfirmEvent; + VLElemCreateEvent elemCreateEvent; + VLTimeServiceEvent timeServiceEvent; + VLPeerEvent peerEvent; + VLBadEvent badEvent; +}; + +/* + * fundemenatal element handles, always around. + */ +extern const ElementHandle el_char8; +extern const ElementHandle el_int8; +extern const ElementHandle el_uint8; +extern const ElementHandle el_int16; +extern const ElementHandle el_uint16; +extern const ElementHandle el_int32; +extern const ElementHandle el_uint32; +extern const ElementHandle el_float32; +extern const ElementHandle el_float64; + +/* + * get the version + */ +extern void vlVersion(FILE *fp); + +/* + * Connecting to a database, finding out name etc. + */ +extern ActorId VLAttachActor(const char8 *agentName); +extern VLStatus VLDetachActor(VLExitMode); +extern uint32 VLDomainName(char8 *name, uint32 maxNameLen); +extern AgentId VLDomainId(void); + + +/* + * Creating elements + */ +extern VLStatus VLCreateElement(int32 (*efunc)(void)); + + +/* how epp generated code defines elements.. + * For error free code.. + * + * THIS ROUTINE IS FOR USE BY EPP-GENERATED CODE + * ONLY! + * That is why its name is prefixed with 'vl' not 'VL'. + */ +extern ElementHandle vlCreateElement(char8 *name, + int32 size, + int32 alignment, + int32 atomic, + int32 dynamic, + int32 subelems, ...); + +/* + * extract an element description into a buffer + * that could be transmited to a remote data base and + * used to recreate the element there. Used by agents + * to exchange element information. + */ +extern VLStatus VLExtractElemDesc(ElementHandle h, + ElementDesc *d); + + +/* + * take an element description, probably transmitted from a remote + * machine, and create an element from it. Such an element cannot be + * properly used on the local database, without a 'vlCreateElement()' + * being performed, as offset and alignment information (which is machine + * dependant) is not available here, but the form will be created here + * with a valid element handle. This will speed up future + * vlCreateElement(), or ' VLCreateElemFromDesc()' calls at this database. + * + * THIS CREATE IS ASYNCHRONOUS. + * + * If the element creation needs to be further negotiated with a peer + * database, then a potential for deadlock in the database coms exists. + * To avoid this, VLCreateElemFromDesc() always returns imediately, with + * no status. All return info is put onto the event queue for async handling. + */ +extern VLStatus VLPeerElement(ElementDesc *d, EventQ q); + +/* + * Setting the database peer. + */ +extern VLStatus VLSetPeerActor(EventQ q); + +/* + * Arrange to get an event when the peer attatches to the database, + * error status if there will be no peer. + */ +extern VLStatus VLGetPeerActor(void); + +/* + * check to see if tha database is a master or not. + */ +extern int VLIsMasterP(void); + +/* + * Define the data format (alignment, endianess etc) of a remote + * database to this database. Return value is used to identify + * the source type of remote machines for updates with reformating. + * returns negative if there is any form of error. + */ +extern VLFormat VLDefineFormat(dpTypeSpec *s); + + +/* + * The following calls are needed to find out when a time keeper has + * connected, and to set up the timekeeper, used on those systems that + * use a timekeeper. on systems that have a local timer, these calls will + * always fail. + */ +extern VLStatus VLGetTimeKeeper(void); +extern VLStatus VLSetTimeKeeper(EventQ q); + +/* + * used by a timekeeper to wakeup actors waiting on alarms, on systems + * without a timekeeper this funcion will still work. returns + * VL_ERR_BAD_AGENT if the actor id is not recognised. + */ +extern VLStatus VLWakeUpActor(ActorId actor); + +/* + * change the state of an element to confirmed. This may involve a change + * of element handle , from 'oldh' to 'newh'. To delete an element awaiting + * confirmation set the 'newh' element handle to 0. Will return + * VL_ERR_BAD_ELEM if 'oldh' is not waiting for confirmation or is not an + * element. else returns VL_ERR_OK. + */ +extern VLStatus VLConfirmElement(ElementHandle oldh, ElementHandle newh); + + +/* + * requesting info about other actors interest at this database. + */ +#define VLRegisterElementInterest() VLQRegisterElementInterest(0) +#define VLDeRegisterElementInterest() VLQDeRegisterElementInterest(0) + +extern VLStatus (VLRegisterElementInterest)(void); +extern VLStatus (VLDeRegisterElementInterest)(void); +extern VLStatus VLQRegisterElementInterest(EventQ q); +extern VLStatus VLQDeRegisterElementInterest(EventQ q); +extern VLStatus VLRequestElementInterest(EventQ q, ElementHandle h); + +#define VLRegisterInstanceInterest(x) VLQRegisterInstanceInterest(0,x) +#define VLDeRegisterInstanceInterest(x) VLQDeRegisterInstanceInterest(0,x) + +extern VLStatus (VLRegisterInstanceInterest)(AgentId id); +extern VLStatus (VLDeRegisterInstanceInterest)(AgentId id); +extern VLStatus VLQRegisterInstanceInterest(EventQ q, AgentId); +extern VLStatus VLQDeRegisterInstanceInterest(EventQ q, AgentId); + + +/* + * Low-level routines to create/delete/update/extract + * instances from the database. + * + * THESE ROUTINES SHOULD BE CALLED FROM EPP-GENERATED CODE ONLY + * + * Epp will write type-safe access routines for you, + * + * USE THEM. + */ +#define vlCreateInstance(e,i,d,t,m) vlQCreateDynamicFormattedInstance( 0,(e),(i),(d),(t),(m),-1, -1 ) +#define vlCreateDynamicInstance(e,i,d,t,m,c) vlQCreateDynamicFormattedInstance( 0,(e),(i),(d),(t),(m),-1, (c)) +#define vlQCreateInstance(q,e,i,d,t,m) vlQCreateDynamicFormattedInstance((q),(e),(i),(d),(t),(m),-1, -1 ) +#define vlQCreateDynamicInstance(q,e,i,d,t,m,c) vlQCreateDynamicFormattedInstance((q),(e),(i),(d),(t),(m),-1, (c)) + +extern InstanceNo (vlCreateInstance)(ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); +extern InstanceNo (vlQCreateInstance)(EventQ qid, + ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); + +extern InstanceNo (vlCreateDynamicInstance)(ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern InstanceNo (vlQCreateDynamicInstance)(EventQ qid, + ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern InstanceNo vlQCreateDynamicFormattedInstance(EventQ qid, + ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + VLFormat format, + int32 count); + +#define vlDeleteInstance(i,m) vlQDeleteInstance(0,(i),(m)) + +extern VLStatus (vlDeleteInstance)(InstanceNo ino, + VLUpdateMode mode); +extern VLStatus vlQDeleteInstance(EventQ qid, + InstanceNo ino, + VLUpdateMode mode); + +extern VLStatus vlUpdateInstance(InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); + +extern VLStatus vlQUpdateInstance(EventQ qid, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); + +extern VLStatus vlUpdateDynamicInstance(InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern VLStatus vlQUpdateDynamicInstance(EventQ qid, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern VLStatus vlQUpdateInstanceFormat(EventQ qid, + VLFormat format, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + + +extern VLStatus vlExtractInstance(InstanceNo ino, + void *data, + VLTime *vtime); + + + + +/* + * Miscellaneous instance routines + */ +extern ElementHandle VLInstanceType(InstanceNo ino); +extern uint32 VLInstanceSize(InstanceNo ino, uint32 *icount); +extern int32 VLInstanceOwnership(InstanceNo ino); +extern void *VLInstanceAddress(InstanceNo ino, + VLStatus *status, + VLTime *time, + VLUpdateMode mode, + uint32 count); +extern VLStatus VLInstanceUpdate(InstanceNo ino, + VLTime *vtime, + VLUpdateMode mode); + + +/* + * (de)registering of interest in elements and instances. + */ +#define VLRegisterElement(e, t) VLQRegisterElement(0,(e),(t)) +#define VLDeRegisterElement(e, t) VLQDeRegisterElement(0,(e),(t)) +#define VLRegisterInstance(i, t) VLQRegisterInstance(0,(i),(t)) +#define VLDeRegisterInstance(i, t) VLQDeRegisterInstance(0,(i),(t)) + +extern VLStatus (VLRegisterElement)(ElementHandle e, uint32 type); +extern VLStatus (VLDeRegisterElement)(ElementHandle e, uint32 type); +extern VLStatus (VLRegisterInstance)(InstanceNo ino, uint32 type); +extern VLStatus (VLDeRegisterInstance)(InstanceNo ino, uint32 type); + +extern VLStatus VLQRegisterElement(EventQ q, + ElementHandle e, + uint32 type); +extern VLStatus VLQDeRegisterElement(EventQ q, + ElementHandle e, + uint32 type); +extern VLStatus VLQRegisterInstance(EventQ q, + InstanceNo ino, + uint32 type); +extern VLStatus VLQDeRegisterInstance(EventQ q, + InstanceNo ino, + uint32 type); + + +/* + * Events, and their queues. + */ +#define VLAwaitEvent(e,w) VLQAwaitEvent((e),NULL,(w)) + +extern VLAction (VLAwaitEvent)(VLEventData *ev, + VLWaitMode wait); +extern VLAction VLQAwaitEvent(VLEventData *ev, + EventQ *q, + VLWaitMode wait); +extern VLAction VLSnoopEvent(EventQ qid,VLEventData *ev); + +extern EventQ VLNewEventQueue(void); +extern VLStatus VLDeleteEventQueue(EventQ q); +extern VLStatus VLBlockEventQueue(EventQ q); +extern VLStatus VLClearEventQueue(EventQ q); + + +/* + * signals + */ +extern void VLSigSet(int32 sig); +extern void VLSigUnset(int32 sig); + +/* + * Stream operations + */ +extern VLStreamId VLStreamOpen(char8 *name, + int32 buflen, + void *buffer, + char8 *format ); +extern VLStatus VLStreamWrite(VLStreamId streamId, + int32 type, + uint32 length, + void *data ); +extern VLStatus VLStreamClose(VLStreamId streamId ); + +/* + * Locking and groups + */ +extern VLStatus VLLock(void); +extern VLStatus VLUnlock(void); +extern int32 VLLockStatus(void); + +extern int32 VLGroup(void); +extern int32 VLUnGroup(void); +extern int32 VLGroupStatus(void); + +/* + * Virtual time and timers + */ +extern VLStatus VLVirtualTime(VLTime *t); +extern VLStatus VLSetVirtualTimeSkew(VLTime *t); +extern VLStatus VLGetVirtualTimeSkew(VLTime *t); + +#define VLAddVtimes(r,a,b) dpAddVtimes(r,a,b) +#define VLSubVtimes(r,a,b) dpSubVtimes(r,a,b) + +extern void (VLAddVtimes)(VLTime *r, VLTime *a, VLTime *b); +extern void (VLSubVtimes)(VLTime *r, VLTime *a, VLTime *b); + +extern VLStatus VLTimer(VLTime *period, VLTimerMode mode); + +/* + * converting status numbers, element handles to meaningful messages + */ +extern const char *VLErrorString(VLStatus s); +extern const char *VLElementName(ElementHandle h); + +#endif /* _VL_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/VLTYPES.H b/CODE/RP/MUNGA_L4/libDPL/dvs/VLTYPES.H new file mode 100644 index 0000000..a9306d1 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/VLTYPES.H @@ -0,0 +1,161 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: vl + * MODULE: vltypes.h + * + * File: $RCSfile: vltypes.h,v $ + * Revision: $Revision: 1.8 $ + * Date: $Date: 1995/05/18 09:43:47 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: vltypes.h,v 1.8 1995/05/18 09:43:47 jeff beta $ + * + * FUNCTION: + * This file contain the definitions of low-level types that are used + * throughout the vl system. These are all integers under a different + * guise. + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _VLTYPES_H +#define _VLTYPES_H + +#include +#include + + +/* + * The basic id type. all the specific id types are typedefed from this. + */ +typedef uint32 IdType; + +typedef IdType InstanceNo; +typedef IdType ElementHandle; +typedef int32 EventQ; +typedef IdType AgentId; +typedef uint16 ActorId; +/*the max number of actors is */ +#define VL_MAX_ACTORS 65534 + +/* ... a bad actorid is indicated by */ +#define VL_BAD_ACTOR ((ActorId) 65535) + +/* ... 'all actors' is indicated by */ +#define VL_ALL_ACTORS ((ActorId) 65535) + + + +typedef void (* VLSigFunc)(int32 sig); + +typedef IdType VLStreamId; +#ifndef VLSTREAM_MAX +#define VLSTREAM_MAX 21 +#endif + +typedef dpVtime VLTime; + +/* + * typedef for passing element descriptions around. + */ +typedef uint32 ElementDesc; + + +/* + * typedefs containing all of the magic flags that might be passed into + * vl, or returned as a status. + */ +typedef enum { + VL_NO_SYNC = 0x00000001, + VL_LOCAL = 0x00000002, + VL_GLOBAL = 0x00000004, + VL_TIME = 0x00000008 +} VLUpdateMode; + +typedef enum { + VL_NOISY = 0x00000000, + VL_QUIET = 0x00000100, + VL_AUDIO_MASK = 0x00000100 +} VLAudibility; + +#define VL_ACTION_NONE 0x00000000 +#define VL_ACTION_CREATE 0x00001000 +#define VL_ACTION_DELETE 0x00002000 +#define VL_ACTION_UPDATE 0x00004000 + +#define VL_ACTION_SIGNAL 0x00010000 +#define VL_ACTION_STREAM 0x00020000 + +#define VL_ACTION_IREG 0x00030000 +#define VL_ACTION_IDEREG 0x00040000 + +#define VL_ACTION_EREG 0x00050000 +#define VL_ACTION_EDEREG 0x00060000 + +#define VL_ACTION_ECREATE 0x00070000 +#define VL_ACTION_EDELETE 0x00080000 +#define VL_ACTION_ECONFIRM 0x00090000 + +#define VL_ACTION_GROUP 0x000a0000 +#define VL_ACTION_UNGROUP 0x000b0000 + +#define VL_ACTION_TIMEOUT 0x000c0000 +#define VL_ACTION_ALARM_REQ 0x000d0000 +#define VL_ACTION_TICK_REQ 0x000e0000 + +#define VL_ACTION_PEER 0x000f0000 +#define VL_ACTION_EXIT 0x00100000 +#define VL_ACTION_BAD 0xffff0000 +typedef uint32 VLAction; + +/* + * index used to identify different format rules + * (endinaess alignment etc) + */ +typedef int32 VLFormat; + +/* update vlerr.c if these are changed */ +typedef enum { + VL_ERR_OK, + VL_ERR_BAD_AGENT, + VL_ERR_BAD_DOMAIN, + VL_ERR_BAD_ELEM, + VL_ERR_BAD_INST, + VL_ERR_BAD_STREAM, + + VL_ERR_BAD_QUEUE, + VL_ERR_BAD_ACTION, + VL_ERR_NOT_SLAVE, + VL_ERR_ALREADY_PEERED, + VL_ERR_TIME, + VL_ERR_FORMAT, + VL_ERR_SEMAPHORE, + VL_ERR_NO_MEM, + VL_ERR_LAST +}VLStatus; + +typedef enum { + VL_DETACH_ACTOR, + VL_DETACH_AGENT, + VL_DETACH_LOCAL, + VL_DETACH_GLOBAL +}VLExitMode; + +typedef enum { + VL_TIME_ALARM, + VL_TIME_TICK, + VL_TIME_OFF +} VLTimerMode; + +typedef enum { + VL_POLL_EVENT, + VL_WAIT_EVENT +} VLWaitMode; + + +#endif /*_VLTYPES_H */ diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/_VCSTRUC.H b/CODE/RP/MUNGA_L4/libDPL/dvs/_VCSTRUC.H new file mode 100644 index 0000000..2b9a2a8 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/_VCSTRUC.H @@ -0,0 +1,569 @@ +#ifndef __VCSTRUCT_H +#define __VSTRUCT_H +struct VCAttribute { + ElementHandle type; /* The element handle */ + InstanceNo ino; + VCEntity *first; + int index; + uint32 mode; + uint32 cacheMode; + uint32 registerMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCCollision +{ + InstanceNo ino; + uint32 status; + uint32 instanceCount; + uint32 collReportCount; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCCollisionReportData *collReportData; + uint32 collReportDataSize; + uint32 collReportDataCount; + uint32 numCollisionsReported; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCIntersection +{ + InstanceNo ino; + uint32 status; + uint32 instanceCount; + uint32 intersectReportCount; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCIntersectionReportData *intersectReportData; + uint32 intersectReportDataSize; + uint32 intersectReportDataCount; + uint32 numIntersectionsReported; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCPosition +{ + InstanceNo ino; + VCEntity *entity; + uint32 status; + uint32 cacheMode; + void *instanceData; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCXWindowId +{ + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCVisualViewResource +{ + InstanceNo ino; + VCAttribute *attribute; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + + +struct VCPseudoGravity +{ + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCMaterial +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCRadiator +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + + + +struct VCTexture +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCRamp +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCInput +{ + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + uint32 numWraps; + uint32 head; +}; + +struct VCTracker +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCSync +{ + VCSync *next; + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCMonitor +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +typedef struct +{ + VCAttribute *attribute; + VCEntity *next; + int32 index; + int32 flags; + VCUserDataList *userDataList; +} VCAttributeData; + +typedef struct VCEntityData +{ + dmMatrix apos; + VCEntity *newParent; + uint32 traverseMode; + VCCallbackFunctions *createFuncList; + VCCallbackFunctions *updateFuncList; + VCCallbackFunctions *deleteFuncList; + VCUserDataList *userData; + void *vcPosCallbackInfo; + void *objPosCallbackInfo; + VCCallbackFunctions *entityRelocateCallbackList; + uint32 entityRelocateMode; +} VCEntityData; + +struct VCEntity { + VCEntity *parent; /* Local parental ptr */ + VCEntity *child; /* Local child ptr */ + VCEntity *sibling; /* Local sibling ptr */ + _VCObject *object; /* Hierarchy VL data */ + InstanceNo ino; /* VCObject Instance No */ + VCEntityData *systemData; + int numAttributes; + VCAttributeData *attributes;/* Hierarchy data objects */ +}; + + +typedef struct +{ + VCColour backgroundColour; + int backgroundColourSet; + float32 nearClip; + int nearClipSet; + float32 farClip; + int farClipSet; + VCColour fogColour; + uint32 fogMode; + int fogColourSet; + float32 nearFog; + int nearFogSet; + float32 farFog; + int farFogSet; + + void *callbackHandle; + +}_VCBodyVisResInfo; + +typedef struct +{ + char *resourceFile; + float32 volume; + int volumeSet; + float32 spreadingRollOff; + int spreadingRollOffSet; + float32 atmosphericAbsorption; + int atmosphericAbsorptionSet; + void *callbackHandle; +}_VCBodyAudioResInfo; + + +struct VCBody +{ + VCBody *next; + _VCBody *body; + uint32 bodySize; + uint32 bodyCount; + VCEntity *rootEntity; + VCEntity *bodyPosEntity; + InstanceNo ino; + VCCallbackFunctions *bodyPartCreateList; + _VCBodyPartList *bodyPartList; + VCCallbackFunctions *attributeFuncList; + VCCallbackFunctions *inputFuncList; + VCCallbackFunctions *collisionFuncList; + _VCBodyVisResInfo visualInfo; + _VCBodyAudioResInfo audioInfo; +}; + + +struct _VCBody_InputFuncData +{ + uint32 minKeyCode; + uint32 maxKeyCode; + char *limbName; +}; + +struct _VCBody_CollideFuncData +{ + char *limbName; +}; + +struct _VCInput_FuncData +{ + uint32 minKeyCode; + uint32 maxKeyCode; +}; + +struct VCUserDataList +{ + VCUserDataList *next; + uint32 vcId; + void *data; +}; + + +struct VCCollisionReport_Traverse +{ + uint32 instanceCount; + VCCollision *collision; + uint32 nextOffset; +}; + +struct VCIntersectionReport_Traverse +{ + uint32 instanceCount; + VCIntersection *intersection; + uint32 nextOffset; +}; + + + +struct VCEntity_Traverse +{ + VCEntity *currentObject; /* Current hierarchy pos */ + VCEntity *startObject; /* Start hierarchy pos */ +}; + +struct VCAttribute_EntityTraverse +{ + VCEntity *entity; + int32 index; +}; + +struct VCEntity_AttributeTraverse +{ + VCEntity *entity; + int32 nextIndex; + ElementHandle element; +}; + +struct VCBody_Traverse +{ + VCBody *body; +}; + +struct VCVisualView_Traverse +{ + duHashIterator hashIter; + VCAttribute *visResource; +}; + + +struct VCBody_AttributeTraverse +{ + VCBody *body; + char *limbName; /* Request limb */ + ElementHandle element; + _VCBodyPartList *currentBodyPart; + int currentAttribute; + VCBody *currentBody; + VCBody_Traverse bodyTraverseInfo; +}; + + + +struct VCCallbackFunctions +{ + VCCallbackFunctions *next; + VC_CallbackFunc function; + void *data; + void *systemData; +}; + +typedef union +{ + VCEntity_Traverse entityT; + VCEntity_AttributeTraverse entityAttributeT; + VCAttribute_EntityTraverse attributeEntityT; + VCBody_Traverse bodyT; + VCBody_AttributeTraverse bodyAttributeT; + VCCollisionReport_Traverse collReportT; + VCIntersectionReport_Traverse intersectReportT; + VCVisualView_Traverse viewT; +}VC_Traverse; + +typedef struct +{ + ElementHandle element; + char *limbName; +} _VCAttributeElementData; + +typedef struct +{ + InstanceNo inst; + VCCallbackFunctions *functionList; +} _VCInstCallback; + +typedef struct +{ + VCBody *body; + _VCBodyPartList *bodyPart; +}_VCBodyPartInfo; + + +struct _VCTimer_CallbackInfo +{ + VLTime lastTime; + VLTime time; + VLTimerMode mode; +}; + +struct _VCBodyPartList +{ + _VCBodyPartList *next; + VCAttribute *bodyPartAttr; + VCBody *body; + uint32 inputNeeded; +/* + VCEntity *pickedObject; + VCEntity_DropFunc dropFunc; + void *dropData; + VCAttribute *pickAttr; +*/ +}; + +typedef struct +{ + VCAttribute *bodyPartAttr; + VCBody *body; + VCEntity_DropFunc dropFunc; + void *dropData; + VCPickObjectData pickObject; +}_VCBodyPickInfo; + + + +typedef struct +{ + VCCallbackFunctions *relocateFunctionList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *invalidFunctionList; + VCCallbackFunctions *updateFunctionList; + VCCallbackFunctions *deleteFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + uint32 relocateMode; +} _VCObjectFunctions; + +typedef struct +{ + _VCObjectFunctions functions; + int explicitInstances; + duHashTab *instTable; + ElementHandle element; + uint32 registered; +} _VCAttributeCallback; + +typedef struct +{ + _VCAttributeCallback *callbackList; + int32 listSize; +} _VCAttributeCallbackList; + +typedef struct +{ + void *relocateCallbackHandle; + void *invalidCallbackHandle; +}_VCEntityRelocateCallbackHandles; + + +typedef struct _VCSyncCallbackInfo +{ + struct _VCSyncCallbackInfo *next; + char *actorName; + char *actorType; + VCSync_Func updateFunc; + VCSync_Func deleteFunc; + void *data; +}_VCSyncCallbackInfo; + + + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/_VCTYPES.H b/CODE/RP/MUNGA_L4/libDPL/dvs/_VCTYPES.H new file mode 100644 index 0000000..ad9bc88 --- /dev/null +++ b/CODE/RP/MUNGA_L4/libDPL/dvs/_VCTYPES.H @@ -0,0 +1,10 @@ +#ifndef __VCTYPES_H +#define __VCTYPES_H + +typedef struct _VCTimer_CallbackInfo _VCTimer_CallbackInfo; +typedef struct _VCBodyPartList _VCBodyPartList; +typedef struct _VCBody_InputFuncData _VCBody_InputFuncData; +typedef struct _VCBody_CollideFuncData _VCBody_CollideFuncData; +typedef struct _VCInput_FuncData _VCInput_FuncData; + +#endif diff --git a/CODE/RP/MUNGA_L4/libDPL/dvs/vssver.scc b/CODE/RP/MUNGA_L4/libDPL/dvs/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..a1b4652fc8fd7dfef1c9a59126d7d126aa8396f7 GIT binary patch literal 368 zcmXpJVq`d2=P%iL-obO(RqsctpMq+--iXF#VE%F-|G>vpDY@%3 z!2A_J{=Q=QHseD!VE#%VKWqLz;q9-kd;!_F3dmo#c@nd==wmQ{HIQ#y7tPWs(gfzO z0rKZ(8=U&Sa0Zya7RYy-*I44Zct4oG4#@YJ^!3_XNe3{0J&@1sn(H70AzCwqd^D#nazG?%xLF|6DR%pj+-Xm=6G^M0-R4 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/libDPL/vssver.scc b/CODE/RP/MUNGA_L4/libDPL/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..01c84d10d2afb024a5a13cdc5b3194db4a89e552 GIT binary patch literal 224 zcmXpJVq`d2=P%iL-obO(RqsctpMq*wa?Ka#STTS>E|BiI6i`tHq)$ literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/mssccprj.scc b/CODE/RP/MUNGA_L4/mssccprj.scc new file mode 100644 index 0000000..565025d --- /dev/null +++ b/CODE/RP/MUNGA_L4/mssccprj.scc @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[mungal4.mak] +SCC_Aux_Path = "M:\VWESS" +SCC_Project_Name = "$/Tesla_rp/MUNGA_L4", QYVAAAAA diff --git a/CODE/RP/MUNGA_L4/mungal4.mak b/CODE/RP/MUNGA_L4/mungal4.mak new file mode 100644 index 0000000..6f565fa --- /dev/null +++ b/CODE/RP/MUNGA_L4/mungal4.mak @@ -0,0 +1,160 @@ +.autodepend +.cacheautodepend +.suffixes: .asm .cpp .c + +!ifndef BTYPE +!error BTYPE macro not supplied +!endif + +!ifndef BPATH +!error BPATH macro not supplied +!endif + +!include make.cfg +!include $(BPATH) + +!ifndef MUNGAL4_ROOT +!error MUNGAL4_ROOT macro is not defined +!endif + +TARGET_DIR = $(MUNGAL4_ROOT)\$(BTYPE) +TARGET_PATH = $(TARGET_DIR)\\ +.path.obj = $(TARGET_DIR) +.path.lib = $(LIBRARY_PATH) + +LIB_PREFIX = -+$(TARGET_DIR)\\ + +CFG_FILE = $(TARGET_DIR)\$(BTYPE).cfg +HEADER_FILE = l4$(BTYPE).csm + +#------------------------------------------------------------------------------ +# Library targets +# +all: $(CFG_FILE) $(TARGET_DIR)\l4tstall.exe + +clean: + del $(TARGET_DIR)\*.obj + del $(TARGET_DIR)\*.lib + del $(TARGET_DIR)\*.exe + del $(TARGET_DIR)\*.bak + del $(TARGET_DIR)\*.cfg + +#------------------------------------------------------------------------------ +# Implicit rules +# +!include $(BTYPE).mak + +!ifndef STARTUP_OBJ +!error STARTUP_OBJ macro is not defined +!endif + +!ifndef STARTUP_LIBS +!error STARTUP_LIBS macro is not defined +!endif + +{$(INCLUDE_PATH)}.cpp{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(INCLUDE_PATH)}.c{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(MUNGAL4_ROOT)}.asm{$(TARGET_DIR)}.obj: + tasm32 -ml $(TASM_OPTIONS) -i$(MUNGAL4_ROOT) $<,$@ >>error.log + +#------------------------------------------------------------------------------ +# Test program +# +$(TARGET_DIR)\l4tstall.exe: \ + $(MUNGAL4_ROOT)\mungal4.mak $(TARGET_DIR)\l4stub.lib stub.lib munga.lib\ + $(TARGET_DIR)\mungal4.lib l4tstall.obj $(DPL_ROOT)\libdpl.lib\ + $(BTYPE).mak + tlink32 @&&| +$(LINK_OPTIONS) + +$(STARTUP_OBJ)+ +$(TARGET_DIR)\l4tstall.obj +$<,$* +$(TARGET_DIR)\l4stub.lib+ +stub.lib+ +munga.lib+ +$(TARGET_DIR)\mungal4.lib+ +$(DPL_ROOT)\libdpl.lib+ +$(STARTUP_LIBS) +| >>error.log + +l4tstall.obj: $(CFG_FILE) + +#------------------------------------------------------------------------------ +# Stub library +# +L4STUB_OBJS = \ + ?l4trace.obj \ + ?l4file.obj \ + ?l4time.obj + +$(L4STUB_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\l4stub.lib: $(L4STUB_OBJS:?=) $(MUNGAL4_ROOT)\mungal4.mak + tlib $@ $(LIB_OPTIONS) @&&| +$(L4STUB_OBJS:?=$(LIB_PREFIX)) +| >>error.log + +#------------------------------------------------------------------------------ +# MUNGAL4 library +# +ASSEMBLY_OBJS = \ + ?netshare.obj \ + ?l4serial.obj \ + ?l4svga16.obj \ + ?joystick.obj \ + ?pcspak.obj + +assemble: $(ASSEMBLY_OBJS:?=) + del $(TARGET_DIR)\mungal4.lib + +MUNGAL4_OBJS = \ + ?l4host.obj \ + ?l4net.obj \ + ?l4dplmem.obj \ + ?l4vidrnd.obj \ + ?l4video.obj \ + ?startdpl.obj \ + ?sosmawe.obj \ + ?l4audhdw.obj \ + ?l4audio.obj \ + ?l4audlvl.obj \ + ?l4audwtr.obj \ + ?l4audres.obj \ + ?l4audrnd.obj \ + ?l4wrhous.obj \ + ?l4vb8.obj \ + ?l4vb16.obj \ + ?l4gauima.obj \ + ?l4grend.obj \ + ?l4gauge.obj \ + ?l4lamp.obj \ + ?l4plasma.obj \ + ?l4ctrl.obj \ + ?l4keybd.obj \ + ?l4mouse.obj \ + ?l4rio.obj \ + ?l4mppr.obj \ + ?l4app.obj \ + ?l4splr.obj \ + ?l4icom.obj \ + ?l4vidtul.obj \ + ?l4audtul.obj \ + ?l4gautul.obj \ + ?l4ctltul.obj + +$(MUNGAL4_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\mungal4.lib:\ + $(MUNGAL4_ROOT)\mungal4.mak $(MUNGAL4_OBJS:?=)\ + $(SOS_ROOT)\sosdbxc.lib $(SOS_ROOT)\sosmbxc.lib + @del $(TARGET_DIR)\mungal4.lib + tlib $@ $(LIB_OPTIONS) @&&| +$(MUNGAL4_OBJS:?=$(LIB_PREFIX)) & +$(ASSEMBLY_OBJS:?=$(LIB_PREFIX)) & +-+$(SOS_ROOT)\sosdbxc.lib & +-+$(SOS_ROOT)\sosmbxc.lib +| >>error.log diff --git a/CODE/RP/MUNGA_L4/netshare.OBJ b/CODE/RP/MUNGA_L4/netshare.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..039ebdc70a475968177a0db46cab5dbbced9eccd GIT binary patch literal 676 zcmaKq!Hd&C6vp4A$z;*iMF}~nLX*^FQtJvk>_XBCb_>leco76I zu@PB8f-V$R7X(4Pc+kDAdfI~*51#jsgP#2Zbf%5M9@fjedB694?>&Zja0-g+!A3M# z9S4=wXgG~E060rF$7>@^kD_3>b~hMnS~nO+cSh@4wQ}i2tU&GOz3%Yh5vLFr7;dKm zz<^(0K1+)rQDXFn*l?Og`do%L-#{p!!&#xJ6J6xTXI>CMl+fE0gJ`yOa%Ecpypk>e zZnj*WAl@fV>hO* zLgOO9lP=6n#kv5Es{p@$j87BNa3(Jqu33zJ)N9666&jb(dPSuEOoG6bZWkoKfWE+(|xU9Np z0yU>37v=sifqNwrPEr%ZF^~BvB~%j$&||iNNG~bgJ$Ynm2E>NA2~_MOZmg{vXtD;K z!*E|vz*ljLCQSBrsR>v}jACI^7GB>ePJS#~I?YH*C6tSV4niqE|6_yes(cv*&&;b_@4jNh# ze>kwPn`0pDA`&dgU&YhhYK%LDIGV-BP;+_~8%}VbP>Z~SZX_+D*_C*zP&&$TR-S|X z#+_)a5UXy+89Ah|5}8`LoEo|W?3j=Afb1qR)q(m>QU}N56&?xc)K8jU4U0t}A}47& z;jw5ub=ayxE5#WmTC|}hw0uwa_oEIb7)6x8>Uvd+*?00*W_!F*StZ{5lsA$|+$1u6 z(}|c-p(wACirRZxq!UoHn91YaN@3UJVRhVqVF^enfg}=i$1d|q0?SmYnOfwHLRRG= z1-GJtl7J88N-buUOh-?RuB@6Oh((#Bpp-dDdTqx@brGEll6|_bQgmcWT;WwFqDB0( z&Otl|H5@WY(nzQzwHwiSN!r6;rCP-)m&2ePwu>(|;_X6nhNwxV zA5u%kGkK%^B1v1_(1aGo>`(!`dq*-mxDuWgk9j&wY24CbnjW`E3BMTz%)TCLCiYGz zfKE4h0-TPbjP8pPHYqgDM*lyt@Bc`F+o&fSq2ivQBxkeSy~Jk+G4Sn;T#Q9DPVS?@ z9ZR!0c1AX&9Apa**=(wbn5?98Joz!_9le;`;vzT-vyy6Q0_S~pLdvG2;a1KDsCLaX zI|A?>EuhdLr3fJx)PT$yV^g$w6KWJ3v;V;{q$>K;f>{`wL-sob7iFuf8gsu_`U``y%0PB^dE|!26F(9 zUxVq{@p(G6mdbhIUb}j0M&Sl?mP+^Vsf)rkLCv@mBFZ&|L%EWEo1moCam z0VfnX!cS+Gqn8tUCT;*5PXwZR}JMfHt51 zCeDP=glq1v#i1TC7`nO>ICutH!)UxUsvOzMEB&xJ4CpHP!U!!`-R^DmD@UP;?%`js CkEt>M literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/opt/L4HOST.obj b/CODE/RP/MUNGA_L4/opt/L4HOST.obj new file mode 100644 index 0000000000000000000000000000000000000000..5197683c7ff9f66849af0e03bb63f37e05f686d5 GIT binary patch literal 3421 zcma)9&rcgi6n+K+R^z5rO`4=YfRr{=kxIrz)xxi36A3@+TlAQvQfuIV4igz0&u*yS2fy+af??_S^4$?|bjf3_s4o zwDF}Da9^^j=W15duCuBvXtxWiYo+qS()v2I-vfYmZaJQ0wlTAG?b^(Zg-@Y95Agaw zU$!dNC(xb)cvHsJ zVy+u9eTXPGLyH z@dIImuqzSlgF!lig`lelBAeB9l!YFW^8HqwhAAZX1J4R63CPtzkNZy3)1z8Y9%PIn z4>TtDEXsrUgqp8~Fvp95@UQMMw-Mte5jQiRn>~ld)btyguyxrqxMn#1LL+RX zJ4mBwBxcuTB%V~6YE_6`Vlk! z-^f%4>N`ap98c6mlt@}XF~1RtBM^yGG+p5Fz9CE))qvGvhe;Np6ta9T@E=4SOfZV5 zfVK1ni`A#GnfwGBl~uv!_pwo$q)m~gFP%skwFvpDsHlCSMbd!G;!?!ZN?|wEVRan9 zumqGTffOm|j%|v150;oIlPqGRkPUUnKv;dla9^FN#jToj^uDbtsip|xk#iK3oKx6q zJ4Rm@(Yc_Q(^Hk&Qd3D`N3y5@np(dIxW{ml>6u1}D!j!+Jsx>W`e`Rp=x=b=cYsix z6zyT~TC?t$W*9W}WP1{i3r#yoQ|vP+t+zcB8_kQtwwA#H7RF4efGe9(nkiI)$Kq|C z4pZ80=`iizZc!3`a|{UW%Ms@NQy3<(chUfQ@WjP_fc8|xaQ+lS*rd>&j-FpQ^&BM# z8}msj=wvK*<`7`WRgr5c=Ds? zsVq`hBIq84Nv2vX!2Lei5K}q~M>!c#wVP6=0t{|;B_!9)KnPJ#7czB2cQ2%2L*s?> z%_Bt3pz(tj)-F&MLTLJ(sQ+#|jHK|}Jd9M!D|gG;rM2Z1TrV${7qj$hbor}|waxWx z^;W4gj6d*n4F1@M%n)=}0NIgvHI@T-{x;-_NRK5d!cZQbUxBIOH@M#wH^O@&t(P1N zJH?oLDBKog#^Co+7(E_79)e$ff-}Xrn!zQXdx+2G<5wkTKEI87-73B(xra}0mb#m* zTUf_ghUwx`sXGN5+{GIj-h#W=7a|J~-GWQSuBN$~PM^gW^r?(<*OYKJeiT7rZvh~4 zHBLkEN>h4|KaT?9zXq^(0bdyJy$}*<_+Lyse;xc# z89CUkj2%3!48#7raEMt@KL36_I}1lp&KzaSheJoXN*4C>aEMKTa;_gDV+Ysp57?-K ArT_o{ literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/opt/L4KEYBD.obj b/CODE/RP/MUNGA_L4/opt/L4KEYBD.obj new file mode 100644 index 0000000000000000000000000000000000000000..1cece0f17a6f2846c9c10a2849454394b51e08a2 GIT binary patch literal 3086 zcma);O>Y!O5Qb}QV-S)RMIj{Nb0H=%Lb9S@E;$8%hy#&ujM)I1Xwo~=v(s_U^rWYE ziEp_etpo>7QG^sJ2Ve3pkoYsnuOL-BGuqkRnhBOaM%u?!Z@pF3)4yGZZupJoWUhs8 zGcOsY1L5l}@4K!0dr!7^H+S~;Vf+yQe6Ve-7HQbsxpk|1XY(r<-vs#Q|NlGbB{yMw z1>oQA#+hs9Fz!%%vGNtM}*VSKFwKAQuS$(@xVA!Z$!LkxFmL9rJkS(>`d zILl!CIbs9EE-qrZ6HZR49#6@UtYVR@1EfgStVy28vLezK$o!1Vl?8^3)LS!Pz=EEY zfm9=Di-bJgJI!Ro39VDU%j9C`MLpU4B$fFkzID!A3zWD)nvAA~_R{+R8-BYtg7o(#DjTYf~zt5g}ihj;1ps z(gun|YE^A3rG3Pw4R8UA7Eq-GF(u%+8>zt*YphggQAVSbF`v?@q_zw{@s%br>1z|z zj;^MjA|y-aC@DF|*qfTLHbwMaVD@ybQ$O;dv`R}^)Bumyubi|351FZHR4C&u7HVbb zE$OF|h|wQQQG0<q6U3(wK7wrA?1#ibngw*ft7<6GhIJ z4rF>*me~@@Sy3JHP49S=gx?YqHeVEk#@T5D0(YF@Jiz!emPLp9$8(2zF{CiQT7Le? z+~+7krC3ih;p5Jb$;~Qr7Z%r<<|Lt3eG1VnWqdj(LzzUR3MZo(i6(AMu0+jws$!Z< zuV1X1qG**UH+dB{nVJZP=Y6vwkv0NXxf$@&q1LTHD5HslCXwhlA{2tAQ1Amixz`p0 zy@Av-r1*R91k_tol^#`r!{^<*hj&-#*Xr)Qg9nfH zSN!dV50~)={x}VPccHTclP7?cQ`OVyGXSqwVfEeeyCrz}A*}iX>4F&l9`$480A5`L z=$!j@f5*QskNZa0&_9qOT>oW+*L3)69XfO|$FJvahRe6#yse(kP9E0i+2VS5O_z!R+7`Xrd literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/opt/L4MOUSE.obj b/CODE/RP/MUNGA_L4/opt/L4MOUSE.obj new file mode 100644 index 0000000000000000000000000000000000000000..15f462d01e634f6e8905a91e822396be09c23784 GIT binary patch literal 3325 zcma);&u<$=6vxMj<3_X)q(a(4f275QRF$HF-3tOK%?}|ERYGD11P*4rJ8KV}o!RWp zy6r7UAldRICxke0gufs;27*9_iM?lL6R(xhL-ei8HcpVgL0A89HmlewSZa_Kw#Ww{V`wBQ>mp7bvvSN?`3m}tD;e2=Sz(oitUSe~E)124VGaIL z$C0k~9}N6W^`o!&e>LI~=M45rWe;@`o(qOK9b2hgvy|X6P74>HV$Ppy=2O^Y2Bu-525+HIpT*u{ z{z+ReqeBM>u9KlXY*q{F%5kEgsVCdR{fa3zu02bUR9xl9V*E0d0fB#79uc9nR79+5^AmFCfvIMX6N_#mk5BR zne!vS788s{#P{P8CAiwXE8z+)EtY?<*SrP5cYl%$A?40L+nw@k;rLO(dAr*U&&(a3 zw5JNcwcpD=IsNNO77$W6ZclZ7`egUy;NSrGBm4~i!FP8$>$9Ek`OfZ{&T{svWBp9w zar-R1{@j!6&e3V|s4#c<_WY+H+sgrDdIB?r aWBAB9njsE|;`=8U*~sKZ7}9|yA^!q|RDMqY literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/opt/L4TIME.obj b/CODE/RP/MUNGA_L4/opt/L4TIME.obj new file mode 100644 index 0000000000000000000000000000000000000000..a9a4cca7cd0006856cbd50f5320ff8ebac1ee8e5 GIT binary patch literal 4392 zcmb7HT}&KR6h5=Nz=G7@Qu~9J;###R8i5#VOhCYb@dw#q6}vdj?%v%UIyAb%*>s8 zzkBX?zI*PyXO8TF-HH8C&TL&(tZX!sGg7LecSaxWlm{Q{Z|@x%f|(lt;F^a_OIM9V zOK)3SOIQ0nFmpS=$`w1Ck<1-1(++T98cTbHL)oSsjm0~o_)Hpc-kye;-Pob!_TZiy zu|q8071fNmo=dQ(%@YZhB*cFy=0o_$H5V(+0vZ&2)_2 zhV7(2o({d*aR!t z+JmTJMD5sYOU-88@%AES95FX-jV*Sk|Pk269gT%SlJ@1uvEDkD=AF02qmCpTiib6 zMKHl=L;-9fo>oijt6593b=GKF1=j2`Yvd+z6S!&XrpJszgme|msIe|YssYsu)3wrS zrC~?J!^Uv|x>G=&5=h`e+%%F}Y7JJ=Q&m?zYcyn9JmlIIO%6OK_B6vXG2M)pZC#b- z6hX{Wjs_*=1o9eYqAZH&ToA0&4Kp<+Hl=HZM~nDJ#r!qSEEPAIHPOgXfwt(V#XN0^ zf2FOLsbvQU&66NJ5-gTWnMpj?uXwT@E-e>Y?L|wTTz^FRL4y6;70C9dei}6r7-*AJp zS^{Nh2KrMOq2QV!kt>tHBuq1_nLvQ9#R$>jIl6s=qnepf4GklsG9>A!g@ydi`bgS(< zF#N>GP(XPo9QNZ?s|-FqC@Vp_JMBvU)AUYvdWW~_;G>@<$p=oU83HwKsS)aePHC_f z>KjU>s~Q2`u7%oF|EdpOdjsl}6ywa8fS{roS<~V%s8`G!FBK{ErsV)z6lIb=W`-lG zo@200!4D1ReVC>2tYKC^rNVH-<@!NGcP2H~jUOFqfL$Nrwuz3K#vkE&v@?XEM znVhh&2?`h;()M+2;dG8C%t-@#uMnaYd+%C@;9C5UjXc5(kHZA&3I&XFY1=vwG9H$D zi6OOL2a>NrNvbwi9094W8S9#yS4&Cbcc9Kn&j2-VN0Zle%fwU}aGTK@w!pDP3B6v$ zsRbw&-X-*dtE&LHws9B-A`R20gAdfu$S*cb-9;6jz;<|_D%#v`#doQ;SSS=m^1p{8 z`LSTfiH;vT7H0jk;XoSW0%o@m!m&1*zx3)KT+V;}#a67E3+`{o9e8DdUq3e>?SDkd zJurR3H+{X(FnbzQOCQTQvTBD)OjQWaMY!{4r@TM2OTT%CV0-$Z1m{&KY3dGdVFfA(`Kw|zI;7&;ROEpGV?b-&n!T3qGG z_rr?6m|t{?9SiyIA8Gq(c57(%(NN&GJ43U5A(RyFjlb!k;MqT?Phb1&!6MoRIC5W_ z9xE^Zv${H3bj#aTsSHP7g(aWtTdJ3R$9F^mORZSmhgSz)_v6)#R}`-pwx=S}QVyT* zMCz74#JZ1V>G-FS+NCdL|I)Xz|M)N1|5vR49Wj4K>gT0MaK0(xpWhwv&3EC|8}Tj6 zvTvEo((+4@n&mmXzLNdR3$h=MwE*rR^dkZ2=k8j=@NiF9b}HVx8gTb&1PT8zR52_Y afb?tmlHQNjkRuXRQoyx*TV9zb+y4R|PP?)I literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/opt/L4TRACE.obj b/CODE/RP/MUNGA_L4/opt/L4TRACE.obj new file mode 100644 index 0000000000000000000000000000000000000000..b459a71da60a53245a6e2d46f236f5f62909e1f4 GIT binary patch literal 2969 zcma);!EX~s6vkf?6LKnt7AO>gp%fA!MF_&BCxR1ksYD14MQD*3@6Os&W@omuV*@uN zgk;GVPF2-Yul+Y#_0aw$RPD9r^gZvc?AUL&NO821fBxos-@G@oZ>~Ty`a1A3)1u?j zAQ_mR=;-a>o9*_&PHS(gwZ9LePXXZ6J?peEQL}a9M)S_rO&DzgeE9!g+sDZ!jIILw z)yAg_3yTF|k{aW;`e_QIFA?h@_QfKWdEw=hddyRDC`+x&sC9tUxkW9Jrn%BJWWGaY zeSx72^!70@WWm76P^zJHx#Cx-*hTQ-f?{B#e`(!|oTEUVBF6;Mx0zQ_j$J9R^NVtX z<Od1K1Vv@M)bi%_o2j+$dFQU{7eYE@1vEqll>8{z=wTR@c(#FP+P6RX}7tE^OL zQK-?9eSS%=l9^$6&R3eqq^oT>b97bhDMGSHjuxfln0SqiX1a*(1!hj?cIp`~rIjgc z(FO#(f90hUc*smcqe7W%u}~+AY{@^JM2!Ew6f+kH?Gw`;k?an7HjeW}Yj3vK<+#wa zlQrg?L2J|Fnbc@rnAnDq@FHKcW(QI|D9Wsn@=lb;JYA-A+|p$_d)%TW{FAsKjMfY0 z%p4;$_D&rT`qwG;1B@;f3a953@+O7RrQ-XubKj!{Ww4%VqJuL-Ay>Q1e57oh1Oi%h ziD(u!KA*FpY$A-p&ZtJ>Nm_WxR$HAGQx&?xn;$c;RnaO@esUF7g_;PD=Y4e`v9V1n4Aqnb2!8i2el{9bY4WwQo#lNynK)pRh>D7}*kGZ z0Vg``y(jHP>%s0GKJV_dcN+9>b@%?kgTwts=iZ}7EBJvQPr@(fVQCpAPXLV*<?JK9L5qW12sTkSiWzr*+@z?WnEyMCH(!1z~yuU&k% zS}7NVX{MCj9Ap`cuOXHo_DdDZEwg+|J@r$3#7nI;)Ow86#i|y|GN*JMnHR`ht}v8> z+&Th=UNA5`*gEY^bhpkO?GU@-QNq7Tv&e!UT5+LR#W zN4a?NOAN~fCAW%Pd;R3vkJxiRyb}l&%3;KVNavdaH%O0A#xqDvC9*J2u42C{qjBDZ zRxS>5MO}JaWm+hEd!|h)Tb-wX#j#4Q`DdDMV;-gAaVyh0(A;^}K^u{XqLHR~V)?+C zBZ$m-hRzy3vk7aqs%8B$VX{S($5w7^{<4^0!l78`J<-EGLm}6@%xxrelLP`%^oeK} zHh!A3A#}==z{#jb;z?R~$<|w)Hd7b6z?&a4Z&Z;Y6?SqJ)`glfi|2iPAhFa8w{ktu zQ$r~mfr!Tw3-#+3Awm)~h0H(DlZR3_(CbLOLaL3yS07p@pxkok2BP%nd7S6l7P9bu z9hQ3C{Xe^lyASvF@%`R*cYBe3E$`ib{P0OD`yQ&*XlR+`|ccfL8%NO~boW01HdK6t6b=`0olV0Nnon TGyHcN&`t+G;veYs7R$hQHB7E^V)% zQ3KQ^?XER75@Jji`O$9b52HWSMU8IRn8bz1AB-`^h;|(WO*+1;I=#N<_Lh}pWlaCN zrza}VdiN8Kpb!w9yuZ)UD|rt)dC}~!HdznUwQq$3U5Z}%2K(+mrkL!W{eZwtl_l$EpQ>xPs61saswU;PZC- z$k!ACI7QLtB7j1c_ufIQ(?pam5RonLpcXA#5bf&rsdg3;;Bk3_A`wuo5ttSbxU>0% z^zmL#w|GwvplR;y0q>PWRYD<+d~VkYiGUJfcNh7JdmqxgyMu<$MQ18e5pUxT+L(qW z3kPFMovn@`|MZqUtxfi3hOf6;X?V~Z2K3GZL+Ow@vQbP?c7%|DMd(dE(kry0L$AC5 zEFQlgAOoM>I;7`aqAwu8TMP)oQHcBc1TVb&g3}GFhlQZUidONw*hlp3v+T3@pKX-j zYUuWPk%@1yORzVb;0YL)=PJ=VCwSX$U3-ydIC^UJ?83;lnQg>vjHPoQTbDBgqB1%`D z_c3+HgqrQmejy+P>m`pz@T)R50BSAIAJe`#546wg7LM0a2%TjZ_-~hg2~DJ}xJ~Y4 zWoD2BLYWeY4V_o6_JY(S=mbKt-Pn4C@P;N>IUUL)`FHlN$3j*sU#8ZCLkjAbPtk^YR#yrqa|B2YIi$8~r~rt2Aj^m9d}o(GXA~*%a2akNi%OA6Zm%hJ=dmU$hyRLHo8m z(VAB|8Fwrj`HgVD2YcDCNd5Cx_GEWLvjXrakB9QBVznAhf;;x>_13ex_KowrExH$W;+wLt-` zSo9>RBb#E&+?<<)Eexruba@IIXAx3pUA31;6VG?94bs5A=3I7YVh!n^%EG;n>*E_x z^;(%WQ?f@+J9+$}4tctBTs@N+IFsN!rATv%l#%VM{8iM{5;eUBJ&?8kQojA9co7`h zYqg()x9C&2Dv->v(Ov!INMAF-c#HNdH#YOSGSQp2b zPWIY#$(Jyj?8j_;02jvxF%^$vI{pdP$G^sg4uJCdgv5phF-;V3iwiQ!P?u9KMLbX7+=Ktq3p4O;Ms}UncbKjw&3C!;GA*Tbi)E*L`)AqkLj6Huoi*mL%@9oxG}(e z3-g}%^> literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/opt/STARTDPL.obj b/CODE/RP/MUNGA_L4/opt/STARTDPL.obj new file mode 100644 index 0000000000000000000000000000000000000000..9a7b8ce81d70a6a267161f9f60190b3648329ad5 GIT binary patch literal 3343 zcmd5wl8|JJDGo?#@A3QbydUSB_ndPXew^$~9PH8sO^Weqs;l3SdtPcW^D?w#FbC zuO)<3A5l~(CMW#Cy?gyljZc&DJ%lVh()ldyf0B$h5pwt2;P$PXN=lwiq@=EdHl*!O zBnR}Nl%O>xgr5K1FHp?4_p|2{$@u5t<=^9ZydGYs<4s*jIW8Fqp-a;fNu?2hXNqB; z+AwTN+K=fJW&x*ta5{&%?|y_+7o1pXM!*9sn{$P)er4IH`iR8i47K z#NuaKRmG4K4+c1@^b+6Nh+#$5A9M|?N}mwdlZs5rE#xsdsbluMZm6e~qmmNS37M)Q zHoKcY%WKJV0xpb_V#rcBnPM{#6}&9OR6dR>u@hv<2VFVeQ&f4Gs(}z&4X?#jL6CV> z&=kpFxjAOr0-KLdB7ZU_ArUVO30fQWd8!VUN?tgdl9YtN$JAb}4Vyky4|Vlg2W;{< z440iw8zE8i&k=gcG`wcFhb|!j=``=>o<2n*mM}8w9h))yx$@B&!x@;#?F>#hzIws< zYjC1=^aD#%Xs1egE`oPTHMHFXlFSvZX(y5+PmZme`#KPyBJQ!DcM(pY7IV@g$wc)V% z{`Kq6mh`^7v79&R3I^a0i)`pC`k9ZhRvek#@%+f_ayok7tb|DBL-&u}+_5Wt{2sLP zp?l!_NXcbnwhpPLS)Ae3;cX_qT}ryOz;qVRTTv=jk28Z4=QX3gz|AM!cy zqoD6Yz6AMo@Na?UAiod!ci?Y>{to${)U{B-*%#_SPjL3>z0|gF0Q|F{7eHq?+rj{T zFTgfJZPRI5wlD?$W$-_w?uFODzXAT|)HD4Kt(yK7tz7sm@bl1rM60L&L4DZ>w@AUZCFW7~Pb8kyb2Tf$eo_%f3n7i!@)#UPZn~gaCzuU{4!`*D&>As2{84lv8wioaH^B(Ko3CyR@FHdYa81)&4#^&|i zlR;a!&~xdshops}3-OhSEu$ak&R}b<5n-N~ z{F<%3go&7;<*-@bVaY5^)iq}W^IJjwtmg!;lJ02DInBA8XTmf3p7D|83eTy+H8k9JfxSMH(czAzpA=jsj}Nz(rr^mN zTg_-)hk4xBjs)Q)bD6zTK5Kz49U_@Z>dWk-n{Nlu=0UXlw`fh~JG3@q((=qp)SG#g zZp!?I+B1Koj?5?2eq|fzDeAZ~P3y?zx7cgJ?o#%P<$jKkPg@3(2|*#UuEni^S9?#B zf!-KN#Uw_SEGF^V6OE~5Bd$n_O3uWRnxK-Xd`4CVWxo~0-=nDgG2Opgt01di0)F-- oP(kq35Yq+!moyzEh^5;&r>kf zGnm;S!r<^SD=b$NMdz;$L8vfijtS5tz0ADiX&pj9u?nD4u7c#0g4|4y;HwU1prFq* zCI*HK5Od*_X*>+9@gc4eAuP`RF0RvNursWzU|?cqv;s@GIEFZ~fQUmN2`&Z}R>mdM z*ce#cd>lh8XE8Cb#ZBX2U~_Q~@(&H@p2fnz{+}sof)oQIqi}qHbG(;-WN?V5vv+)G z0MHCqpy%QyNH8!m38F~)ItF`lFfe=o>0?6CXBZ#k7#<%9bgVZn$q1mKewdO*5S?rc z3~sn2BUl(1JSRv4?G!{)G#nIFq{C|6c8L3l(vI` z^Q>W7K-w-wrZnS|U8+F0GZ-Cs_eO~o%sNtHu!6CKJ*|@$D9*5g3Csj~fnfy;m~Yp9~zOd(tA#8ov200V0AyL>`b>w}6iUWD6AVGdOkuxg`K{>8Akz literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/opt/l4serial.OBJ b/CODE/RP/MUNGA_L4/opt/l4serial.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..c04f2444d03f490effb4fd9cea6eb64009211fc1 GIT binary patch literal 2312 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 E0gJHEz5oCK literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/sos/SOSDBXC.LIB b/CODE/RP/MUNGA_L4/sos/SOSDBXC.LIB new file mode 100644 index 0000000000000000000000000000000000000000..a65a0fbecb2cdb2f477af7781cc624edf26458a2 GIT binary patch literal 45568 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

QWBO^`VAih(^SKsAE*Xp5|Hbq9 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 KRR*49tK)xidI16e literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/sos/SOSDWXCS.LIB b/CODE/RP/MUNGA_L4/sos/SOSDWXCS.LIB new file mode 100644 index 0000000000000000000000000000000000000000..3b5f11165673ca8e805cfb3077334e325c65791b GIT binary patch literal 87552 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 literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/sos/SOSMAWE.C b/CODE/RP/MUNGA_L4/sos/SOSMAWE.C new file mode 100644 index 0000000..3eb8843 --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/SOSMAWE.C @@ -0,0 +1,443 @@ +/**************************************************************************** + + File : sosmawe.c + + Purpose : Module to handle AWE32 .SBK file uploads + + Date : 1-20-95 + + Programmer(s) : Don Fowler + + Last Updated : 1-29-95 + +**************************************************************************** + Copyright(c) 1992,1995 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sosm.h" + +WORD sosMIDIAWE32SetSBKFile( WORD, PSTR ); +WORD sosMIDIAWE32ReleaseSBKFiles( WORD ); +WORD sosMIDIAWE32NoteOn( WORD, WORD, WORD, WORD, WORD, WORD ); +WORD sosMIDIAWE32NoteOff( WORD, WORD, WORD ); + +// maximum number of .SBK files that can be set on the chip +#define _MAX_SBKS 0x10 + +// offset into slot list for .SBK files to start +#define _SBK_SLOT_OFFSET 0x01 + +// size of buffer needed to read in a chunk of .SBK file +#define _READ_BUFFER_SIZE 0x2000 + +// pointer to preset data for awe32 +#ifdef BORLAND +PSTR _lpSOSMIDIAwe32PresetBuffer[ _SOS_MIDI_MAX_DRIVERS ][ _MAX_SBKS ] = { +#else +LPSTR _lpSOSMIDIAwe32PresetBuffer[ _SOS_MIDI_MAX_DRIVERS ][ _MAX_SBKS ] = { +#endif + + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL } + + }; + +// index into list of presets to the currently available slot, +// start the index at 0 to leave slot 0 open for general midi +// rom on the AWE32 +WORD _wSOSMIDIAwe32PresetIndex[ _SOS_MIDI_MAX_DRIVERS ] = { + + _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET, + _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET + }; + +/*************************************************************************** + +Function : WORD sosMIDIAWE32SetSBKFile + +Parameters : WORD hDriver + Handle of SOS driver to set SBK file on. + PSTR szFileName + Name of .SBK file to set. + +Returns : -1 if error; otherwise, slot that the .SBK file was + assigned to on the AWE32. + +Description : Stream a .SBK file onto the awe32 and return the slot + streamed to. + +****************************************************************************/ + +WORD sosMIDIAWE32SetSBKFile( WORD hDriver, PSTR szFileName ) +{ + WORD wIndex; + WORD hFile; + WORD wReadSize; + PSTR pDataPtr; +#ifdef BORLAND + SFAR lpTemp; +#endif + + // attempt to find a slot to use for the .SBK file + if( _wSOSMIDIAwe32PresetIndex[ hDriver ] == ( _MAX_SBKS - 1 ) ) + return( -1 ); + + // attempt to open the sbk file + if( ( hFile = open( ( const char * )szFileName, O_RDONLY | O_BINARY ) ) == -1 ) + return( -1 ); + + // attempt to allocate a buffer to use for transfer + if( !( pDataPtr = ( PSTR )malloc( _READ_BUFFER_SIZE ) ) ) + { + // close the file + close( hFile ); + + // return an error + return( -1 ); + } + + // open the awe32 stream +#ifdef BORLAND + if( ( wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 5 ], + lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 5 ]( _NULL, + _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // free the previously allocated memory + free( pDataPtr ); + + // close the file + close( hFile ); + + // return error + return( -1 ); + } + + // read in a chunk of data from the file + if( read( hFile, pDataPtr, wReadSize ) == -1 ) + return( -1 ); + + // get the sample data seek location +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = pDataPtr; + if( ( wIndex = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 8 ], + lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wIndex = _lpSOSMIDIDrvFunction[ hDriver ][ 8 ]( ( LPSTR )pDataPtr, + _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // free the previously allocated memory + free( pDataPtr ); + + // close the file + close( hFile ); + + // return error + return( -1 ); + } + + // seek the file to the sample location + if( lseek( hFile, wIndex, SEEK_SET ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -1 ); + } + + // send chunks of data to the driver + do + { + // read in a chunk of data from the file + if( read( hFile, pDataPtr, wReadSize ) == -1 ) + return( -1 ); + + // send the data to the driver +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = pDataPtr; + if( ( wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ] + [ 6 ], lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 6 ]( + ( LPSTR )pDataPtr, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // close the file + close( hFile ); + + // free the memory + free( pDataPtr ); + + // return an error + return( -1 ); + } + } while( wReadSize ); + + // free the temporary memory buffer + free( pDataPtr ); + + // get the preset data size +#ifdef BORLAND + wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 7 ], + lpTemp, 0x00, 0x00 ); +#else + wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 7 ]( _NULL, 0x00, 0x00 ); +#endif + + // get the preset location in the file +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = &wIndex; + sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ], lpTemp, + 0x00, 0x00 ); +#else + _lpSOSMIDIDrvFunction[ hDriver ][ 9 ]( ( LPSTR )&wIndex, 0x00, 0x00 ); +#endif + + // allocate the memory for the preset information +#ifdef BORLAND + if( !( _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] = + ( PSTR )malloc( wReadSize ) ) ) +#else + if( !( _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] = + ( LPSTR )malloc( wReadSize ) ) ) +#endif + { + // close the file + close( hFile ); + + // return an error + return( -1 ); + } + + // seek the file to the preset location + if( lseek( hFile, wIndex, SEEK_SET ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -1 ); + } + + // read in the preset information + if( read( hFile, ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ + _wSOSMIDIAwe32PresetIndex[ hDriver ] ], wReadSize ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -1 ); + } + + // send the preset information to the driver +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ]; + if( ( sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 10 ], + lpTemp, 0x00, 0x00 ) ) == -1 ) +#else + if( ( _lpSOSMIDIDrvFunction[ hDriver ][ 10 ]( ( LPSTR ) + _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ], 0x00, 0x00 ) ) == -1 ) +#endif + { + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // close the file + close( hFile ); + + // return an error + return( -1 ); + } + + // close the SBK file + close( hFile ); + + // increment the preset buffer index to the next available slot + _wSOSMIDIAwe32PresetIndex[ hDriver ]++; + + // return no error + return( _wSOSMIDIAwe32PresetIndex[ hDriver ] ); +} + +/*************************************************************************** + +Function : WORD sosMIDIAWE32ReleaseAllSBKFiles + +Parameters : WORD hDriver + Handle of SOS driver to release .SBK files from + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Release all of the memory associated to the .SBK files + uploaded to the awe32. + +****************************************************************************/ + +WORD sosMIDIAWE32ReleaseSBKFiles( WORD hDriver ) +{ + WORD wIndex; +#ifdef BORLAND + SFAR lpTemp; +#endif + + // call the driver to release all of the .SBK files +#ifdef BORLAND + if( sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ], lpTemp, + 0x01, 0x00 ) == -1 ) +#else + if( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ]( ( LPSTR )_NULL, 0x01, 0x00 ) + == -1 ) +#endif + return( -1 ); + + // free the memory allocated for the awe32 preset information + for( wIndex = _SBK_SLOT_OFFSET; wIndex < _wSOSMIDIAwe32PresetIndex[ hDriver ]; + wIndex++ ) + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ wIndex ] ); + + // reset the available slot index + _wSOSMIDIAwe32PresetIndex[ hDriver ] = _SBK_SLOT_OFFSET; + + // return no error + return( _ERR_NO_ERROR ); +} + +/*************************************************************************** + +Function : WORD sosMIDIAWE32NoteOn + +Parameters : WORD hDriver + Handle of SOS driver + WORD wSlot + .SBK file slot to associate patch to + WORD wChannel + Channel to use + WORD wPatch + Patch to use + WORD wNote + MIDI relative pitch to use + WORD wVelocity + Velocity to use + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Turn a note on + +****************************************************************************/ + +WORD sosMIDIAWE32NoteOn( WORD hDriver, WORD wSlot, WORD wChannel, + WORD wPatch, WORD wNote, WORD wVelocity ) +{ + BYTE szMIDIData[ 0x10 ]; + + // setup the midi data structure to associate a slot to a channel + szMIDIData[ 0 ] = 0xb0 | wChannel; + szMIDIData[ 1 ] = 0x00; + szMIDIData[ 2 ] = wSlot; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x03 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x03 ); +#endif + + // select the patch for the channel + szMIDIData[ 0 ] = 0xc0 | wChannel; + szMIDIData[ 1 ] = wPatch; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x02 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x02 ); +#endif + + // turn the note on with the correct pitch and attack + szMIDIData[ 0 ] = 0x90 | wChannel; + szMIDIData[ 1 ] = wNote; + szMIDIData[ 2 ] = wVelocity; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x02 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x02 ); +#endif + + // return no error + return( _ERR_NO_ERROR ); +} + +/*************************************************************************** + +Function : WORD sosMIDIAWE32NoteOff + +Parameters : WORD hDriver + Handle of SOS driver + WORD wChannel + Channel to use + WORD wNote + MIDI relative pitch to use + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Turn a note on + +****************************************************************************/ + +WORD sosMIDIAWE32NoteOff( WORD hDriver, WORD wChannel, WORD wNote ) +{ + BYTE szMIDIData[ 0x10 ]; + + // turn the note off + szMIDIData[ 0 ] = 0x90 | wChannel; + szMIDIData[ 1 ] = wNote; + szMIDIData[ 2 ] = 0x00; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x03 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x03 ); +#endif + + // return no error + return( _ERR_NO_ERROR ); +} + + + + + + + + diff --git a/CODE/RP/MUNGA_L4/sos/SOSMBXC.LIB b/CODE/RP/MUNGA_L4/sos/SOSMBXC.LIB new file mode 100644 index 0000000000000000000000000000000000000000..65c1e57f5c1c35a4d23b0c43bc026389b3ac2ecb GIT binary patch literal 163328 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

s8HVZ;uOS4G-F__xI|4uNMQvevCt{a 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 + +#pragma pack(4) +extern WORD _sosDIGIData_Start; +extern WORD _sosDIGIData_End; +extern WORD _wSOSDriverLinear[]; +extern WORD _wSOSTimerLinear[]; +extern SFAR _lpSOSDriver[]; +extern SFAR _lpSOSTimer[]; +extern SFAR _lpSOSDriverCS[]; +extern SFAR _lpSOSTimerCS[]; +extern BOOL _wSOSDriverLoaded[]; +extern BOOL _wSOSTimerLoaded[]; +extern BOOL _wSOSDriverInitialized[]; +extern WORD _wSOSOutputRate[]; +extern WORD _wSOSDMABuffersize[]; +extern LONG _dwSOSDMABufferPhysical[]; +extern SFAR _lpSOSDMABuffer[]; +extern BOOL _wTimerUsed; +extern SFAR _lpSOSFillHandler[]; +extern WORD _wSOSTimerType[]; +extern WORD _wSOSDriverType[]; +extern SFAR _lpSOSSampleList[][ _MAX_VOICES ]; +extern SFAR _lpSOSDMAIrqCount[]; +extern SFAR _lpSOSDMAFillCount[]; +extern WORD _wSOSTmrNextCount; +extern SFAR _lpSOSOldTimer; +extern WORD _wSOSDriverID[]; +extern _SOS_CAPABILITIES _sSOSDriverCaps[]; +extern WORD _wSOSDMAPortList[]; +extern BYTE _bSOSDMAChannel[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern BYTE _pSOSDriverPath[]; +extern BYTE _pSOSTempDriverPath[]; +extern BOOL _wTIMERUsed; +extern WORD _wTIMERValue; +extern VOID ( * _pTIMEREvents[] )( VOID ); +extern WORD _wTIMEREventRate[]; +extern WORD _dwTIMEREventFraction[]; +extern WORD _dwTIMEREventFractionCurrent[]; +extern BYTE _bSOSMIDITimerSongHandler[]; +extern BYTE _bSOSMIDISongHandle; +extern WORD _wSOSTimerMemHandle[]; +extern WORD _wSOSDriverMemHandle[]; +extern WORD _wSOSRealSeg[]; +extern VOID ( *_pSOSFillHandlerThunks[] )( VOID ); + +extern _FILEHEADER sDETFileHeader; +extern _DRIVERHEADER sDETDriverHeader; +extern _FILEHEADER sLOADFileHeader; +extern _DRIVERHEADER sLOADDriverHeader; +extern BOOL wDETInitialized; +extern WORD wDETLinear; +extern SFAR lpDETDriverBuffer; +extern SFAR lpDETDriverBufferCS; +extern WORD hDETFile; +extern DWORD dwDETDriverIndex; +extern WORD wDETDriverIndexCur; +extern WORD wDETMemHandle; +extern _SOS_CAPABILITIES * pDETDeviceCaps; +extern _SOS_CAPABILITIES sDETCaps; +extern PSTR _pSOSErrorStrings[]; +extern BOOL wSOSBufferAllocated[]; +extern BOOL wSOSSystemInitialized; +extern VDS_STRUCT sSOSVDSInfo; +extern _SOS_FILL_INFO _sSOSFillInfo; +extern WORD _wSOSTimerEventIndex; +extern WORD _wSOSTimerEntered; +extern WORD _wSOSDriverSize[]; +extern WORD _wSOSTimerSize[]; +extern PSTR pDETBuffer; + +#ifdef __cplusplus +extern "C" { +#endif +extern WORD _sosDIGIData1_Start; +extern WORD _sosDIGIData1_End; +extern WORD _sosDIGIData2_Start; +extern WORD _sosDIGIData2_End; +extern BYTE _bTIMERInstalled; +extern BYTE _bTIMERDPMI; +extern WORD wDetectPort; +extern WORD wDetectIRQ; +extern WORD wDetectDMA; +extern WORD wDetectParam; +#ifdef __cplusplus +} +#endif + +#pragma pack() + +#endif + diff --git a/CODE/RP/MUNGA_L4/sos/bc4/SOSDEFS.H b/CODE/RP/MUNGA_L4/sos/bc4/SOSDEFS.H new file mode 100644 index 0000000..67b6cb6 --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/bc4/SOSDEFS.H @@ -0,0 +1,65 @@ +/**************************************************************************** + + File : sosdefs.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOSDEFS_DEFINED +#define _SOSDEFS_DEFINED + +#undef _TRUE +#undef _FALSE +#undef _NULL +enum + { + _FALSE, + _TRUE + }; + +#define _NULL 0 + +#ifndef VOID +#define VOID void +#endif +typedef int BOOL; +typedef unsigned int UINT; +typedef unsigned char BYTE; +typedef unsigned WORD; +#ifndef LONG +typedef signed long LONG; +#endif +typedef unsigned long DWORD; + +typedef BYTE * PBYTE; +typedef char * PSTR; +typedef WORD * PWORD; +typedef LONG * PLONG; +typedef VOID * PVOID; + +typedef BYTE * LPBYTE; +typedef BYTE * LPSTR; +typedef WORD * LPWORD; +typedef LONG * LPLONG; +typedef VOID * LPVOID; + +typedef BYTE * HPBYTE; +typedef BYTE * HPSTR; +typedef WORD * HPWORD; +typedef LONG * HPLONG; +typedef VOID * HPVOID; + +typedef unsigned HANDLE; + +#endif + diff --git a/CODE/RP/MUNGA_L4/sos/bc4/SOSFNCT.H b/CODE/RP/MUNGA_L4/sos/bc4/SOSFNCT.H new file mode 100644 index 0000000..bc04a6b --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/bc4/SOSFNCT.H @@ -0,0 +1,209 @@ +/**************************************************************************** + + File : sosfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_FUNCTIONS +#define _SOS_FUNCTIONS + +#pragma pack(4) + +#ifdef __cplusplus // HACK - ECH 96/01/26 +extern "C" { +#endif + +VOID sosDIGILockMemory ( VOID ); +VOID sosDIGIUnLockMemory ( VOID ); +WORD sosDIGIInitSystem ( PSTR, WORD ); +WORD sosDIGIUnInitSystem ( VOID ); +WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE *, + _SOS_INIT_DRIVER *, WORD * ); +WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL ); +WORD sosDIGILoadDriver ( WORD, WORD, SFAR *, SFAR *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadDriver ( WORD ); +WORD sosDIGIGetDeviceCaps ( WORD, PSOSDEVICECAPS ); + +#ifdef PHARLAP +WORD sosDIGIAllocateBuffer ( WORD , WORD *, WORD *, SFAR * ); +#else +WORD sosDIGIAllocateBuffer ( WORD , WORD *, WORD *, SFAR * ); +#endif + +WORD sosDIGIStopSample ( WORD, WORD ); +WORD sosDIGISamplesPlaying ( WORD ); +BOOL sosDIGISampleDone ( WORD, WORD ); +BOOL sosDIGISampleFilling ( WORD, WORD ); +WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE * ); +WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE * ); + + +WORD sosDIGIDetectInit ( PSTR ); +WORD sosDIGIDetectUnInit ( VOID ); +WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES *, WORD * ); +WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES *, WORD * ); +WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES *, WORD * ); +WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE * ); +WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES * ); +WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE * ); +PSTR sosGetErrorString ( WORD ); + +WORD sosDIGILoadTimer ( WORD , SFAR *, SFAR *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadTimer ( WORD ); + +WORD sosTIMERRegisterEvent ( WORD, VOID ( * )( VOID ), WORD * ); +WORD sosTIMERInitSystem ( WORD, WORD ); +WORD sosTIMERUnInitSystem ( WORD ); +WORD sosTIMERSetRate ( WORD ); +WORD sosTIMERRemoveEvent ( WORD ); +WORD sosTIMERAlterEventRate ( WORD, WORD ); +WORD sosTIMERGetEventRate ( WORD ); +VOID sosTIMEROldHandler ( VOID ); +VOID sosTIMERHandler ( VOID ); +VOID sosFillThunk0 ( VOID ); +VOID sosFillThunk1 ( VOID ); +VOID sosFillThunk2 ( VOID ); +VOID sosFillThunk3 ( VOID ); +VOID sosFillThunk4 ( VOID ); + +// functions in soscntl.c +WORD sosDIGISetSampleVolume ( WORD, WORD, WORD ); +WORD sosDIGIGetSampleVolume ( WORD, WORD ); +WORD sosDIGISetChannel ( WORD, WORD, WORD ); +WORD sosDIGIGetChannel ( WORD, WORD ); +WORD sosDIGIGetBytesProcessed ( WORD, WORD ); +WORD sosDIGIGetLoopCount ( WORD, WORD ); +WORD sosDIGISetPanLocation ( WORD, WORD, WORD ); +WORD sosDIGIGetPanLocation ( WORD, WORD ); +DWORD sosDIGISetPitch ( WORD, WORD, DWORD ); +DWORD sosDIGIGetPitch ( WORD, WORD ); +WORD sosDIGIGetDMAPosition ( WORD ); +WORD sosDIGISetPanSpeed ( WORD, WORD, WORD ); +WORD sosDIGIGetPanSpeed ( WORD, WORD ); +WORD sosDIGIGetSampleID ( WORD, WORD ); +WORD sosDIGIGetSampleHandle ( WORD, WORD ); +WORD sosDIGISetMasterVolume ( WORD, WORD ); +#ifdef PHARLAP +VOID sosFreeVDSPage ( WORD, WORD, LONG ); +WORD sosAllocVDSPage ( SFAR *, WORD *, WORD * ); +extern int cdecl sosRealAlloc( int, int *, int * ); +extern void cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD ); +extern int cdecl sosGetCS ( VOID ); +extern int cdecl sosGetES ( VOID ); +#else +WORD sosAllocVDSPage ( SFAR *, WORD *, WORD * ); +VOID sosFreeVDSPage ( WORD, WORD, LONG ); +extern int cdecl sosRealAlloc( int, int *, int * ); +extern int cdecl sosRealFree ( int ); +#endif + +extern BOOL cdecl _sos_read ( WORD, SFAR, WORD, WORD * ); +#ifdef __cplusplus // HACK - ECH 96/01/26 +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif +// sos driver functions +extern int cdecl sosDRVLockMemory ( DWORD, DWORD ); +extern int cdecl sosDRVUnLockMemory ( DWORD, DWORD ); +extern void cdecl sosDRVGetCapsInfo ( SFAR, SFAR, _SOS_CAPABILITIES * ); +extern void cdecl sosDetDRVGetCapsInfo ( SFAR, SFAR, _SOS_CAPABILITIES * ); +extern void cdecl sosDRVGetCapsPtr ( SFAR, SFAR, _SOS_CAPABILITIES * ); +extern void cdecl sosDRVInit ( SFAR, SFAR, int, int, int, int, int, int ); +extern void cdecl sosDRVStart ( SFAR, SFAR, int, int ); +extern void cdecl sosDRVSetRate ( SFAR, SFAR, int ); +extern void cdecl sosDRVSetAction ( SFAR, SFAR ); +extern void cdecl sosDRVStop ( SFAR, SFAR ); +extern void cdecl sosDRVUnInit ( SFAR, SFAR ); +extern void cdecl sosDRVGetFillInfo ( SFAR, SFAR, SFAR, int, int, int, _SOS_FILL_INFO * ); +extern void cdecl sosFillSampleStructs ( PSTR, SFAR ); +extern WORD cdecl sosDetDRVExist ( SFAR, SFAR ); +extern WORD cdecl sosDetDRVGetSettings ( SFAR, SFAR ); +extern WORD cdecl sosCreateAliasCS ( SFAR, SFAR * ); +extern WORD cdecl sosDetDRVVerifySettings( SFAR, WORD, WORD, WORD, SFAR ); +extern WORD cdecl sosDIGIInitForWindows( WORD ); +extern WORD cdecl sosDIGIUnInitForWindows( WORD ); +extern WORD cdecl sosAllocateFarMem ( WORD, PSTR, WORD *, SFAR * ); +extern VOID cdecl sosFreeSelector ( SFAR, DWORD ); +extern WORD cdecl sosMAKEDOSPtr ( PSTR, SFAR * ); +extern VOID cdecl sosDetDRVSetEnvString ( DWORD, PSTR ); +extern PSTR cdecl sosDetDRVGetEnvString ( DWORD ); +extern VOID cdecl sosDetDRVEnvStringInit ( SFAR, SFAR ); +extern VOID cdecl sosDRVSetupCallFunctions( SFAR, SFAR, SFAR, SFAR ); +extern WORD cdecl sosDRVGetFreeMemory ( VOID ); +extern WORD cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * ); +extern WORD cdecl sosDRVFreeVDSStruct ( WORD, WORD ); +extern WORD cdecl sosDRVIsWindowsActive ( VOID ); +extern WORD cdecl sosDRVVDSGetBuffer ( WORD ); +extern WORD cdecl sosDRVVDSFreeBuffer ( WORD ); +extern WORD cdecl sosSetupVDSBufferSize( WORD, WORD ); +extern WORD cdecl sfmemcpy( PSTR, WORD, WORD ); +extern WORD cdecl sfmemcpy1( PSTR, WORD, WORD ); +extern WORD cdecl getDS( VOID ); +extern WORD cdecl getCS( VOID ); +extern WORD cdecl sosDRVMakeDMASelector ( WORD ); +extern WORD cdecl sosDRVFreeDMASelector ( WORD ); +extern WORD cdecl sosSetPageAccess ( WORD, WORD ); +extern VOID cdecl sosCopyToFarMem ( SFAR, PSTR, WORD ); +extern VOID cdecl sosDRVCallFillHandler ( SFAR ); +extern VOID cdecl sosInitDMABuffer( SFAR, WORD, WORD ); +extern VOID cdecl sosDIGISetupDS( VOID ); + +extern void cdecl sosTIMERDRVInit( int wRate, void ( * )( void ) ); +extern void cdecl sosTIMERDRVUnInit( void ); +extern void cdecl sosTIMERDRVHandler( void ); +extern void cdecl sosTIMERDRVFHandler( void ); +extern void cdecl sosTIMERDRVEnable( void ); +extern void cdecl sosTIMERDRVDisable( void ); +extern void cdecl sosTIMERDRVCallOld( void ); +extern void cdecl sosTIMERDRVSetRate( WORD ); +extern void cdecl sosDIGITimer_Start( void ); +extern void cdecl sosDIGITimer_End( void ); +extern void cdecl sosDIGIDrv_Start( void ); +extern void cdecl sosDIGIDrv_End( void ); +extern void cdecl sosInt3( void ); +extern void cdecl sosFARRet( WORD ); +extern void cdecl sosDIGIFARRet( VOID ); +#ifdef __cplusplus +} +#endif + +// memory locking prototypes +VOID sosDIGICaps_Start( VOID ); +VOID sosDIGICaps_End( VOID ); +VOID sosDIGIErr_Start( VOID ); +VOID sosDIGIErr_End( VOID ); +VOID sosDIGITmr_Start( VOID ); +VOID sosDIGITmr_End( VOID ); +VOID sosDIGIStart_Start( VOID ); +VOID sosDIGIStart_End( VOID ); +VOID sosDIGIPlyng_Start( VOID ); +VOID sosDIGIPlyng_End( VOID ); +VOID sosDIGIRate_Start( VOID ); +VOID sosDIGIRate_End( VOID ); +VOID sosDIGIDone_Start( VOID ); +VOID sosDIGIDone_End( VOID ); +VOID sosDIGIDetec_Start( VOID ); +VOID sosDIGIDetec_End( VOID ); +VOID sosDIGIInit_Start( VOID ); +VOID sosDIGIInit_End( VOID ); +VOID sosDIGILoad_Start( VOID ); +VOID sosDIGILoad_End( VOID ); +VOID sosDIGICntl_Start( VOID ); +VOID sosDIGICntl_End( VOID ); + +#pragma pack() + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/bc4/SOSM.H b/CODE/RP/MUNGA_L4/sos/bc4/SOSM.H new file mode 100644 index 0000000..6d02ccd --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/bc4/SOSM.H @@ -0,0 +1,450 @@ +/**************************************************************************** + + File : sosm.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_MIDI_DEFINED +#define _SOS_MIDI_DEFINED + +#include "sosdefs.h" +#include "sos.h" + +#pragma pack(4) + +#define _SOS_MIDI_ERR -1 + +// number of drivers allowed to be open at one time +#define _SOS_MIDI_MAX_DRIVERS 5 + +// maximum number of allowed channels +#define _SOS_MIDI_MAX_CHANNELS 0x10 + +// structure definition for the capabilities +typedef struct +{ + BYTE szDeviceName[ 32 ]; // device name + WORD wDeviceVersion; // device version + WORD wFlags; // miscellaneous flags + WORD wProcessData; // process data before sending to driver + SFAR lpPortList; // list of usable ports + SFAR lpIRQList; // list of usable irq channels + WORD wDeviceID; // ID for the device + +} _SOS_MIDI_CAPABILITIES; + +// call indexes for the loadable drivers +enum +{ + _DRV_MIDI_GET_CAPS, + _DRV_MIDI_GET_CALL_TABLE, + _DRV_MIDI_SPECIAL1 +}; + +// file header for the driver +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // number of drivers in the file + WORD wDrivers; + + // offset of first driver + WORD lOffset; + + // size of the file + WORD lFileSize; + +} _MIDIFILEHEADER; + +// driver header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // offset of next driver + WORD lNextDriver; + + // size of current driver + WORD wSize; + + // id for the current device + WORD wDeviceID; + + // id for the extender type + WORD wExtenderType; + +} _MIDIDRIVERHEADER; + +// device hardware information +typedef struct +{ + // port to be used + WORD wPort; + + // IRQ for the board + WORD wIRQ; + + // extra parameter + WORD wParam; + +} _SOS_MIDI_HARDWARE; + +// structure for initializing a digital driver +typedef struct +{ + // ID for the digital driver + WORD wDriverID; + + // timer rate to use + WORD wTimerRate; + + // timer callback rate to use + WORD wTimerCallbackRate; + + // max voices for the driver to use + WORD wMaxVoices; + + // velocity sensing flag + WORD wVelocitySensing; + + // init driver info + _SOS_INIT_DRIVER * sDIGIDriverInfo; + + // hardware information + _SOS_HARDWARE * sDIGIHardwareInfo; + +} _SOS_MIDI_DIGI_INIT_DRIVER; + +// structure for initializing a driver +typedef struct +{ + // type of driver to use if using a digital driver + WORD wDIGIDriverID; + + // pointer to driver memory + SFAR lpDriverMemory; + SFAR lpDriverMemoryCS; + + // pointer to digital driver initialization information + _SOS_MIDI_DIGI_INIT_DRIVER * sDIGIInitInfo; + + // miscellaneous WORD parameter for driver + WORD wParam; + + // miscellaneous DWORD parameter for driver + DWORD dwParam; + +} _SOS_MIDI_INIT_DRIVER; + +// structure for starting a song +typedef struct +{ + // pointer to song memory + BYTE * pSongData; + + // pointer to callback function for pertinent song information + VOID ( * pSongCallback )( WORD ); + +} _SOS_MIDI_INIT_SONG; + +// define to indicate that track mapping can be used +// from the midi file for the song +#define _MIDI_MAP_TRACK 0xff + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ]; + +} _SOS_MIDI_TRACK_DEVICE; + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ][ 5 ]; + +} _SOS_MIDI_TRACK_DEVICE1; + +// header for the NDMF format MIDI file +typedef struct +{ + // ID for the file + BYTE szFileID[ 32 ]; + + WORD dwBranchOffset; + WORD temp1; + WORD temp2; + WORD temp3; + +// // name of the instrument file to use with the song +// BYTE szInstrumentFile[ 16 ]; + + // number of tracks in the song + WORD wNDMFTracks; + + // ticks/quarter note song is used at + WORD wTicksQuarterNote; + + // tempo + WORD wTempo; + + // time for song to play at current tempo + WORD wTimeToPlay; + + // channel mapping priority information + WORD wChannelPriority[ _SOS_MIDI_MAX_CHANNELS ]; + + // channel mapping information + _SOS_MIDI_TRACK_DEVICE1 sTrackMap; + + // array of flags for which controllers to restore on a loop/branch + BYTE bCtrlRestore[ 128 ]; + + // pointer to callback function for song to call with + // pertinent information + VOID ( * pSongCallback )( WORD ); + WORD wFiller; + +} _NDMF_FILE_HEADER; + +// header for the tracks in the NDMF format MIDI file +typedef struct +{ + // track number + WORD wTrackNumber; + + // length of the track + WORD wTrackLength; + + // channel used on the track + WORD wChannel; + +} _NDMF_TRACK_HEADER; + +// MIDI event structure +typedef struct +{ + // dummy name to access midi data from + BYTE bMidiData[ 256 ]; + +} _NDMF_MIDI_EVENT; + +// maximum number of songs that can be played at any time +#define _SOS_MIDI_MAX_SONGS 8 + +// maximum number of tracks that can be used +#define _SOS_MIDI_MAX_TRACKS 32 + +// number of driver functions +#define _SOS_MIDI_DRV_FUNCTIONS 13 + +// enumeration for all of the drv functions +enum +{ + _MIDI_DRV_SEND_DATA, + _MIDI_DRV_INIT, + _MIDI_DRV_UNINIT, + _MIDI_DRV_RESET, + _MIDI_DRV_SET_INST_DATA +}; + +// defines for the loadable driver ids +#define _MIDI_SOUND_MASTER_II 0xa000 +#define _MIDI_MPU_401 0xa001 +#define _MIDI_FM 0xa002 +#define _MIDI_OPL2 0xa002 +#define _MIDI_CALLBACK 0xa003 +#define _MIDI_MT_32 0xa004 +#define _MIDI_DIGI 0xa005 +#define _MIDI_INTERNAL_SPEAKER 0xa006 +#define _MIDI_WAVE_TABLE_SYNTH 0xa007 +#define _MIDI_AWE32 0xa008 +#define _MIDI_OPL3 0xa009 +#define _MIDI_GUS 0xa00a + +// structure for the hmi instrument file header +typedef struct +{ + // file id type + BYTE szFileID[ 32 ]; + + // file version + WORD wFileVersion; + + // size of the file + WORD dwFileSize; + +} _HMI_INS_FILE_HEADER; + + +// define for identifying a drum instrument +#define _SOS_MIDI_DRUM_INS ( short )0x8000 + +// maximum number of timer events that can be registered +#define _TIMER_MAX_EVENTS 0x10 + +// structure for digital driver queue element +typedef struct _tagQueueElement +{ + // handle for the sample + WORD wSampleHandle; + + // id for the sample + WORD wSampleID; + + // velocity for the sample + WORD wVelocity; + + // channel for the sample + WORD wChannel; + +} _DIGI_QUEUE_ELEMENT; + +// maximum number of instruments that can be set in the +// digital driver +#define _MAX_INS 128 + +// define for the maximum number of times a channel can be stolen +#define _SOS_MIDI_MAX_LEVELS 0x04 + +// structure for MIDI information to be stored on the local stack +// when a channel is stolen +typedef struct +{ + // used element + BYTE bUsed; + + // last pitch bend information sent + BYTE bPitchBend; + + // channel volume + BYTE bChannelVolume; + + // instrument information + BYTE bInstrument; + + // sustain pedal + BYTE bSustain; + +} _SOS_MIDI_CHANNEL_DATA; + +// flags for the debugging system +#define _SOS_DEBUG_NORMAL 0x0000 +#define _SOS_DEBUG_NO_TIMER 0x0001 + +// ID for 32 bit MIDI file +#define _SOS_MIDI_FILE_ID "HMIMIDIP" + +// structure for branch location controller +typedef struct +{ + // offset from start of track data + WORD dwOffset; + + // branch ID number + BYTE bBranchID; + + // current instrument + BYTE bInstrument; + + // current loop count for temporary storage + // so that a track can be looped without + // needing any data from the program + BYTE bLoopCount; + + // number of controller messages stored + BYTE bCtrlChangeCount; + + // offset of control change information from start of file + WORD lpCtrlChangeData; + WORD lpCtrlChangeDataTemp; + + // reserved fields + WORD wReserved1; + WORD wReserved2; + +} _SOS_BRANCH_POINT; + +#define _SOS_MIDI_FADE_IN 0x01 +#define _SOS_MIDI_FADE_OUT 0x02 +#define _SOS_MIDI_FADE_OUT_STOP 0x04 + +// structure for digital drums to use to store midi information +typedef struct +{ + // current volume + WORD wVolume; + + // current pan position + WORD wPanPosition; + + // reserved + DWORD dwReserved; + +} _SOS_MIDI_DIGI_CHANNEL; + +// instrument file header structure +typedef struct +{ + // file ID + BYTE szID[ 32 ]; + + // file version + WORD wVersion; + + // instruments in file + WORD wInstruments; + + // list of pointers to start sample structures + SFAR * lpStartSample[ _MAX_INS ]; + + DWORD temp1; + DWORD temp2; + +} _WAVE_FILE_HEADER; + +#pragma pack() + +// define for the busy error returned from send data +#define _ERR_DRIVER_BUSY 0xf000 + +// defines for the looping branch controllers +#define _SOS_SET_FLAG 103 +#define _SOS_RESET_FLAG 104 +#define _SOS_BRANCH1 108 +#define _SOS_BRANCH2 109 +#define _SOS_BRANCH3 110 +#define _SOS_BRANCH4 111 +#define _SOS_BRANCH5 112 +#define _SOS_BRANCH6 113 +#define _SOS_BRANCH7 114 +#define _SOS_BRANCH8 115 +#define _SOS_BRANCH9 116 +#define _SOS_BRANCH10 117 +#define _SOS_BRANCH11 118 +#define _SOS_BRANCH12 119 +#define _SOS_BRANCH13 120 +#define _SOS_BRANCH14 121 + +// define for the program change controller flag +#define _SOS_PROGRAM_CHANGE_FLAG 108 + +#include "sosmdata.h" +#include "sosmfnct.h" + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/bc4/SOSMAWE.H b/CODE/RP/MUNGA_L4/sos/bc4/SOSMAWE.H new file mode 100644 index 0000000..e6322ad --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/bc4/SOSMAWE.H @@ -0,0 +1,16 @@ + +#include "sosm.h" + +#ifdef __cplusplus // HACK - ECH 96/01/26 +extern "C" { +#endif + +WORD sosMIDIAWE32SetSBKFile( WORD, PSTR ); +WORD sosMIDIAWE32ReleaseSBKFiles( WORD ); +WORD sosMIDIAWE32NoteOn( WORD, WORD, WORD, WORD, WORD, WORD ); +WORD sosMIDIAWE32NoteOff( WORD, WORD, WORD ); + +#ifdef __cplusplus // HACK - ECH 96/01/26 +} +#endif + diff --git a/CODE/RP/MUNGA_L4/sos/bc4/SOSMDATA.H b/CODE/RP/MUNGA_L4/sos/bc4/SOSMDATA.H new file mode 100644 index 0000000..d302647 --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/bc4/SOSMDATA.H @@ -0,0 +1,125 @@ +/**************************************************************************** + + File : sosmdata.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOS_MIDI_DATA +#define _SOS_MIDI_DATA + +#include "sos.h" + +#pragma pack(4) + +extern WORD _wSOSMIDIDriverLinear[]; +extern SFAR _lpSOSMIDIDriver[]; +extern SFAR _lpSOSMIDIDriverCS[]; +extern WORD _wSOSMIDIMemHandle[]; +extern BOOL _wSOSMIDIDriverLoaded[]; +extern WORD _wSOSMIDIDriverType[]; +extern WORD _wSOSMIDIDriverID[]; +extern DWORD _dwSOSMIDITrackDeltaCurrent[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDIActiveTracks[]; +extern WORD _wSOSMIDITotalTracks[]; +extern DWORD _dwSOSMIDITrackDeltaTime[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDISongPaused[]; +extern WORD _wSOSMIDISongMuted[]; +extern BOOL _wSOSMIDISongActive[]; +extern BYTE _bSOSMIDIEventSize[]; +extern BYTE _bSOSMIDIEventSizeControl[]; +extern _SOS_MIDI_CAPABILITIES * _pSOSMIDIDriverCaps[]; +extern _SOS_MIDI_TRACK_DEVICE * _sSOSMIDITrackMap[]; +extern _NDMF_MIDI_EVENT * _pSOSMIDITrack[][_SOS_MIDI_MAX_TRACKS]; +extern SFAR _lpSOSMIDIDrvFunction[ _SOS_MIDI_MAX_DRIVERS ][ _SOS_MIDI_DRV_FUNCTIONS ]; +extern _NDMF_FILE_HEADER * _sSOSMIDISongHeader[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern WORD _wSOSMIDIEventHandle[]; +extern BYTE _szSOSMIDIDrvFile[]; +extern _MIDIFILEHEADER _sSOSMIDIDRVFileHeader; +extern _MIDIDRIVERHEADER _sSOSMIDIDRVDriverHeader; +extern BOOL _wSOSMIDISysInititalized; +extern SFAR _lpSOSMIDICBCKDrvFunctions[]; +extern VOID ( cdecl *_pSOSMIDICBCKFunctions )( SFAR, WORD, WORD ); +extern WORD _wMIDIDIGISampleQueueHead[]; +extern WORD _wMIDIDIGISampleQueueTail[]; +extern WORD _wMIDIDIGIMaxSamples[]; +extern WORD _wMIDIDIGIUsedSamples[]; +extern _DIGI_QUEUE_ELEMENT _sMIDIDIGIQueue[][ _MAX_VOICES ]; + + +extern SFAR _lpMIDIDIGIDrvFunctions[]; +extern _SOS_START_SAMPLE * _sMIDIDIGIStartSample[][ _MAX_INS ]; +extern _HMI_INS_FILE_HEADER * _sMIDIDIGIInsFileHeader[]; +extern WORD _wMIDIDIGIDriverHandle[]; +extern WORD _wMIDIDIGIDriverInitialized[]; +extern WORD _wMIDIDIGITimerEventHandle[]; +extern WORD _wMIDIDIGIDriverInitMIDI[]; +extern WORD _wMIDIDIGIVelocitySensing[]; +extern BYTE _szMIDIDIGIInsFileID[]; + +extern BYTE _bSOSMIDIMasterVolume; +extern BYTE _bSOSMIDIDeviceChannelVolume[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIMT32SendData; + +extern SFAR lpFake; +extern WORD wFake; + +extern _NDMF_TRACK_HEADER *_pSOSMIDITrackHeaders[][ _SOS_MIDI_MAX_TRACKS ]; +extern BYTE _bSOSMIDIChannelRemap[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIChannelPriority[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerChannel[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerSong[][ _SOS_MIDI_MAX_CHANNELS ]; +extern _SOS_MIDI_CHANNEL_DATA _sSOSMIDIChannelData[][ _SOS_MIDI_MAX_CHANNELS ][ _SOS_MIDI_MAX_LEVELS ]; +extern BYTE _bSOSMIDIChannelDataIndex[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIData[]; +extern BYTE _bSOSMIDIData1[]; +extern BYTE _bSOSMIDIDeviceLowPriority[]; +extern WORD _wSOSMIDIChannelStealing; +extern BYTE _bSOSMIDIDeviceChannelActive[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIDeviceChannelAvailable[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDISongHandle; +extern BYTE _szMIDIMIDIFileID[]; +extern BYTE _pSOSMIDIDriverPath[]; +extern BYTE _pSOSMIDITempDriverPath[]; +extern WORD sosMIDIData_Start; +extern WORD sosMIDIData_End; +extern WORD _wSOSGravisTimerHandle; +extern WORD _wSOSMIDISongVolume[]; + +extern _SOS_BRANCH_POINT * _pMIDIBranchData[][ _SOS_MIDI_MAX_TRACKS ]; +extern WORD ( *_pSOSMIDIBranchCallback[] )( WORD, BYTE, BYTE ); +extern WORD ( *_pSOSMIDILoopCallback[] )( WORD, BYTE, BYTE, BYTE ); +extern WORD ( *_pSOSMIDITriggerCallback[][ 127 ] )( WORD, BYTE, BYTE ); +extern BYTE _bSOSMIDIBranchOccurred; + +extern WORD _wSOSMIDIVolumeFadeDirection[]; +extern DWORD _dwSOSMIDIVolumeFadeFraction[]; +extern DWORD _dwSOSMIDIVolumeFadeVolume[]; +extern WORD _wSOSMIDIVolumeFadeTicks[]; +extern BYTE _bSOSMIDIHandleVolumeFade[]; +extern WORD _wSOSDIGIMIDIHandle[]; +extern SFAR _lpSOSMIDIGusFunction; + +extern _SOS_MIDI_DIGI_CHANNEL _sMIDIDIGIChannel[]; + +extern SFAR _lpMIDIWAVEDrvFunctions[]; +extern WORD _wSOSMIDIChannelMuted[][ _SOS_MIDI_MAX_CHANNELS ]; + +extern BYTE _szPLYMIDIBuffer[]; +extern WORD _wPLYMIDIBufferIndex; +extern WORD _wSOSMIDIDriverSize[]; + +#pragma pack() + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/bc4/SOSMFNCT.H b/CODE/RP/MUNGA_L4/sos/bc4/SOSMFNCT.H new file mode 100644 index 0000000..5e91d77 --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/bc4/SOSMFNCT.H @@ -0,0 +1,190 @@ +/**************************************************************************** + + File : sosmfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_MIDI_FUNCTIONS +#define _SOS_MIDI_FUNCTIONS + +#pragma pack(4) + +#ifdef __cplusplus // HACK - ECH 96/01/26 +extern "C" { +#endif + +WORD sosMIDILockMemory ( VOID ); +WORD sosMIDIUnLockMemory ( VOID ); +WORD sosMIDIGetDeviceCaps ( WORD, _SOS_MIDI_CAPABILITIES * ); +WORD sosMIDIInitSystem ( PSTR, WORD ); +WORD sosMIDIUnInitSystem ( VOID ); +WORD sosMIDIInitDriver ( WORD, _SOS_MIDI_HARDWARE *, + _SOS_MIDI_INIT_DRIVER *, WORD * ); +WORD sosMIDIUnInitDriver ( WORD, BOOL ); +WORD sosMIDILoadDriver ( WORD, WORD, SFAR *, SFAR *, PSTR, PSTR, WORD * ); +WORD sosMIDIUnLoadDriver ( WORD ); +WORD sosMIDIInitSong ( _SOS_MIDI_INIT_SONG *, + _SOS_MIDI_TRACK_DEVICE *, + WORD * ); +WORD sosMIDIUnInitSong ( WORD ); +WORD sosMIDIResetSong ( WORD, _SOS_MIDI_INIT_SONG * ); +WORD sosMIDIStartSong ( WORD ); +WORD sosMIDIStopSong ( WORD ); +WORD sosMIDIPauseSong ( WORD, WORD ); +WORD sosMIDIMuteSong ( WORD ); +WORD sosMIDIUnMuteSong ( WORD ); +WORD sosMIDIResumeSong ( WORD ); +BOOL sosMIDISongDone ( WORD ); +WORD sosMIDISongAlterTempo ( WORD, WORD ); +WORD sosMIDIGetDeltaTime ( PSTR, DWORD * ); +WORD sosMIDISongGetTimeToPlay ( WORD ); +BYTE * sosMIDINormalizePtr ( BYTE * ); +WORD sosMIDISetInsData ( WORD, PSTR, WORD ); +WORD sosMIDIResetDriver ( WORD ); +BOOL sosMIDIHandleMIDIData ( WORD, PSTR, WORD, WORD ); +WORD sosMIDISendMIDIData ( WORD, PSTR, WORD ); +VOID sosMIDISetTrackState ( WORD, WORD, WORD ); + +// compiled in drivers function interface +VOID digiGetCallTable ( WORD * ); +VOID callbackGetCallTable ( WORD * ); + +WORD cdecl callbackSendData ( SFAR, WORD, WORD ); +WORD cdecl callbackInit ( SFAR, WORD, WORD ); +WORD cdecl callbackUnInit ( SFAR, WORD, WORD ); +WORD cdecl callbackReset ( SFAR, WORD, WORD ); +WORD cdecl callbackSetInstrumentData ( SFAR, WORD, WORD ); + +// function prototypes +WORD cdecl digiSendData ( SFAR, WORD, WORD ); +WORD cdecl digiInit ( SFAR, WORD, WORD ); +WORD cdecl digiUnInit ( SFAR, WORD, WORD ); +WORD cdecl digiReset ( SFAR, WORD, WORD ); +WORD cdecl digiSetInstrumentData ( SFAR, WORD, WORD ); + +VOID waveGetCallTable ( WORD * ); +WORD cdecl waveSendData ( SFAR, WORD, WORD ); +WORD cdecl waveInit ( SFAR, WORD, WORD ); +WORD cdecl waveUnInit ( SFAR, WORD, WORD ); +WORD cdecl waveReset ( SFAR, WORD, WORD ); +WORD cdecl waveSetInstrumentData ( SFAR, WORD, WORD ); +VOID cdecl waveSampleCallback( WORD, WORD, WORD ); + +WORD cdecl callbackSendDataStub ( SFAR, WORD, WORD ); +WORD cdecl callbackInitStub ( SFAR, WORD, WORD ); +WORD cdecl callbackUnInitStub ( SFAR, WORD, WORD ); +WORD cdecl callbackResetStub ( SFAR, WORD, WORD ); +WORD cdecl callbackSetInstrumentDataStub ( SFAR, WORD, WORD ); + +// function prototypes +WORD cdecl digiSendDataStub ( SFAR, WORD, WORD ); +WORD cdecl digiInitStub ( SFAR, WORD, WORD ); +WORD cdecl digiUnInitStub ( SFAR, WORD, WORD ); +WORD cdecl digiResetStub ( SFAR, WORD, WORD ); +WORD cdecl digiSetInstrumentDataStub ( SFAR, WORD, WORD ); + +WORD cdecl waveSendDataStub ( SFAR, WORD, WORD ); +WORD cdecl waveInitStub ( SFAR, WORD, WORD ); +WORD cdecl waveUnInitStub ( SFAR, WORD, WORD ); +WORD cdecl waveResetStub ( SFAR, WORD, WORD ); +WORD cdecl waveSetInstrumentDataStub ( SFAR, WORD, WORD ); + +VOID digiQueueInit ( WORD, WORD ); +VOID digiQueueUnInit ( WORD ); +WORD digiQueueAddItem ( WORD, WORD, WORD, WORD, WORD ); +WORD digiQueueGetItem ( WORD, WORD ); +WORD digiQueueGetItemWAVE ( WORD ); +WORD digiQueueDeleteItem ( WORD, WORD ); +WORD digiQueueDeleteItemWAVE ( WORD, WORD ); +WORD digiQueueDeleteItemMIDI ( WORD, WORD, WORD ); +WORD digiQueueFindItemMIDI ( WORD, WORD, WORD ); + +// function prototypes +VOID cdecl digiSampleCallback( WORD, WORD, WORD ); + +WORD sosMIDIRegisterBranchFunction ( WORD, WORD ( * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIRegisterLoopFunction ( WORD, WORD ( * )( WORD, BYTE, BYTE, BYTE ) ); +WORD sosMIDIRegisterTriggerFunction( WORD, BYTE, WORD ( * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIBranchToTrackLocation ( WORD, BYTE, BYTE ); +WORD sosMIDIBranchToSongLocation ( WORD, BYTE ); + +//#ifdef __cplusplus // ECH +//extern "C" { +//#endif + +extern void cdecl sosMIDIDRVGetCapsInfo( SFAR, SFAR, PSTR ); +extern void cdecl sosMIDIDRVGetCapsPtr ( SFAR, SFAR, PSTR ); +extern void cdecl sosMIDIDRVGetFuncsPtr( SFAR, SFAR, PSTR ); +extern VOID cdecl sosMIDIDRVSpecialFunction( SFAR, SFAR, WORD, SFAR * ); +extern WORD cdecl xgetES( void ); + +extern WORD cdecl sosMIDIDRVCall32Func( SFAR, SFAR, WORD, WORD ); + +//#ifdef __cplusplus // ECH +//} +//#endif + +BOOL sosMIDIResetChannelStealing ( WORD ); +WORD sosMIDIEnableChannelStealing( WORD ); +VOID sosMIDISongHandler( VOID ); + +WORD sosMIDISetMT32InsData ( WORD, PSTR, WORD ); +WORD sosMIDISetMasterVolume ( BYTE ); +VOID sosMIDIMT32Timer ( VOID ); + +WORD sosMIDISetSongVolume ( WORD, BYTE ); +WORD sosMIDIFadeSong ( WORD, WORD, WORD, BYTE, BYTE, WORD ); +VOID sosMIDIGusFunction( VOID ); +VOID sosMIDIGusFunction1( SFAR ); + +// functions for memory locking +VOID sosMIDICaps_Start( VOID ); +VOID sosMIDICaps_End( VOID ); +VOID sosMIDICbck_Start( VOID ); +VOID sosMIDICbck_End( VOID ); +VOID sosMIDIDigi_Start( VOID ); +VOID sosMIDIDigi_End( VOID ); +VOID sosMIDIDone_Start( VOID ); +VOID sosMIDIDone_End( VOID ); +VOID sosMIDIDq_Start( VOID ); +VOID sosMIDIDq_End( VOID ); +VOID sosMIDIInit_Start( VOID ); +VOID sosMIDIInit_End( VOID ); +VOID sosMIDIIns_Start( VOID ); +VOID sosMIDIIns_End( VOID ); +VOID sosMIDILoad_Start( VOID ); +VOID sosMIDILoad_End( VOID ); +VOID sosMIDIPause_Start( VOID ); +VOID sosMIDIPause_End( VOID ); +VOID sosMIDIPtr_Start( VOID ); +VOID sosMIDIPtr_End( VOID ); +VOID sosMIDISong_Start( VOID ); +VOID sosMIDISong_End( VOID ); +VOID sosMIDISt_Start( VOID ); +VOID sosMIDISt_End( VOID ); +VOID sosMIDITmpo_Start( VOID ); +VOID sosMIDITmpo_End( VOID ); +VOID sosMIDITmr_Start( VOID ); +VOID sosMIDITmr_End( VOID ); +VOID sosMIDIAWE_Start( VOID ); +VOID sosMIDIAWE_End( VOID ); + +void StringOut( BYTE X, BYTE Y, BYTE * String, BYTE Color ); + +#ifdef __cplusplus // HACK - ECH 96/01/26 +} +#endif + +#pragma pack() + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/bc4/SOSRES.H b/CODE/RP/MUNGA_L4/sos/bc4/SOSRES.H new file mode 100644 index 0000000..91050dd --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/bc4/SOSRES.H @@ -0,0 +1,110 @@ +/**************************************************************************** + + File : sosres.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#define _SOS_RESOURCE +#ifndef _SOS_RESOURCE +#define _SOS_RESOURCE + +// structure for resource file header +typedef struct +{ + // file version + WORD wVersion; + + // file size + LONG dwFileSize; + + // number of resources in file + WORD wResCount; + + // offset of resource data from top of file + LONG dwResOffset; + + // offset of sync track from top of file + LONG dwSyncTrackOffset; + +} _RES_FILE_HEADER; + +// structure for resource block header +typedef struct +{ + // resource id + WORD wID; + + // resource type + WORD wResType; + + // offset of next block + LONG dwNextBlock; + + // size of the current resource information + LONG dwResSize; + + // rate to play block at + WORD wBlockRate; + + // id for the sync track to use + WORD wSyncTrackID; + +} _RES_BLOCK_HEADER; + +// structure for sync mark tag +typedef struct _tagSYNCMARK +{ + // ID of the type of mark being used + WORD wID; + + // location in data of sync mark + LONG dwSyncOffset; + + // length of sync block + LONG dwSyncSize; + + // start sample data + _SOS_START_SAMPLE sampleData; + +} _RES_SYNCMARK; + +typedef union +{ + // structure for sync mark tag + _RES_SYNCMARK syncMark; + +} _RES_TAG; + +// union for filter information for prepareWave +typedef union +{ + // filter type + WORD wFilterID; + + // structure for volume + struct volume + { + WORD wVolume; + }; + + // structure for delay + struct delay + { + WORD wDelaySamples; + }; + +} _SOS_FILTER; + + +#endif + diff --git a/CODE/RP/MUNGA_L4/sos/bc4/vssver.scc b/CODE/RP/MUNGA_L4/sos/bc4/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..342f5d0381b645d304b0cedc47413c1ca9fa0f10 GIT binary patch literal 192 zcmXpJVq`d2=P%iL-obO(RqsctpMq-csEPi%YQ+Es*MRhS*^7TQw-)?l1d3b-^5-$E z7u>%^9L&D~{Q&8|4dj1%>hWgb z*_&Yg9U!0U;M)_ToKM00yFk9!@72duzkCGq?*aMCkIgpt`nU(ozYpZ+yvY|)&Y213 F0{}i#L$Uw> literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/sos/vssver.scc b/CODE/RP/MUNGA_L4/sos/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..3ba43d825bd53d1f8d8eefbcc328f4087a671504 GIT binary patch literal 176 zcmXpJVq`d2=P%iL-obO(RqsctpMq+(E!gLF+KK@T&H!m!Ba7`%bBez)0!7XO`Kt2{ zm1Ium2J_DW`F1u@2P~V^!2I(-{;fW_S*ps%e}dFs0P_7d%Wsrze*)%T1oEYMH3~RY qTEYBFApJe{5jTY=fcck!eD&8>ZMmAe!Tc*gzSE-4qQe?dU_Jm39yibc literal 0 HcmV?d00001 diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOS.H b/CODE/RP/MUNGA_L4/sos/wc/SOS.H new file mode 100644 index 0000000..419448f --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOS.H @@ -0,0 +1,553 @@ +/**************************************************************************** + + File : sos.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_DEFINED +#define _SOS_DEFINED +#include "sosdefs.h" + +#pragma pack(4) + +// error definition for sound operating system +#define _SOS_ERR -1 + +// number of drivers allowed to be open at one time +#define _SOS_MAX_DRIVERS 5 + +// structure definition for the capabilities +typedef struct _tagCAPABILITIES +{ + BYTE szDeviceName[ 32 ]; // device name + WORD wDeviceVersion; // device version + WORD wBitsPerSample; // bits per sound sample + WORD wChannels; // stereo/mono sound card + WORD wMinRate; // minimum rate + WORD wMaxRate; // maximum rate + WORD wMixerOnBoard; // board contains mixer + WORD wMixerFlags; // mixer capabilities + WORD wFlags; // miscellaneous flags + short far * lpPortList; // list of usable ports + short far * lpDMAList; // list of usable dma channels + short far * lpIRQList; // list of usable irq channels + short far * lpRateList; // list of usable rates, -1 if any in min to max + WORD fBackground; // foreground or background driver + WORD wDeviceID; // ID for the device + WORD wTimerID; // ID for the timer + +} _SOS_CAPABILITIES; + +// far pointer to the device capabilities structure +typedef _SOS_CAPABILITIES far * LPSOSDEVICECAPS; + +// flag types for driver +#define _FLAGS_SIGNED 0x8000 + +// devices that can be loaded +#define _SOUND_BLASTER_8_MONO 0xe000 +#define _SOUND_BLASTER_8_ST 0xe001 +#define _SBPRO_8_ST _SOUND_BLASTER_8_ST +#define _SBPRO_8_MONO 0xe00f +#define _SOUND_MASTER_II_8_MONO 0xe002 +#define _MV_PAS_8_MONO 0xe003 +#define _MV_PAS_16_MONO 0xe004 +#define _MV_PAS_8_ST 0xe005 +#define _MV_PAS_16_ST 0xe006 +#define _ADLIB_GOLD_8_ST 0xe007 +#define _ADLIB_GOLD_16_ST 0xe008 +#define _ADLIB_GOLD_8_MONO 0xe009 +#define _ADLIB_GOLD_16_MONO 0xe00a +#define _MICROSOFT_8_MONO 0xe00b +#define _MICROSOFT_8_ST 0xe00c +#define _MICROSOFT_16_MONO 0xe00d +#define _MICROSOFT_16_ST 0xe00e +#define _SOUND_SOURCE_8_MONO_PC 0xe010 +#define _SOUND_SOURCE_8_MONO_TANDY 0xe011 +#define _GENERAL_PORT_8_MONO 0xe012 +#define _GENERAL_PORT_8_MONO_R 0xe013 +#define _SIERRA_8_MONO 0xe014 +#define _SB16_8_MONO 0xe015 +#define _SB16_8_ST 0xe016 +#define _SB16_16_MONO 0xe017 +#define _SB16_16_ST 0xe018 +#define _ESS_AUDIODRIVE_8_MONO 0xe019 +#define _ESS_AUDIODRIVE_8_ST 0xe01a +#define _ESS_AUDIODRIVE_16_MONO 0xe01b +#define _ESS_AUDIODRIVE_16_ST 0xe01c +#define _SOUNDSCAPE_8_MONO 0xe01d +#define _SOUNDSCAPE_8_ST 0xe01e +#define _SOUNDSCAPE_16_MONO 0xe01f +#define _SOUNDSCAPE_16_ST 0xe020 +#define _RAP10_8_MONO 0xe021 +#define _RAP10_16_MONO 0xe022 +#define _GUS_8_MONO 0xe023 +#define _GUS_8_ST 0xe024 +#define _GUS_16_MONO 0xe025 +#define _GUS_16_ST 0xe026 +#define _GUS_MAX_8_MONO 0xe027 +#define _GUS_MAX_8_ST 0xe028 +#define _GUS_MAX_16_MONO 0xe029 +#define _GUS_MAX_16_ST 0xe02a +#define _WAVEJAMMER_8_MONO 0xe02b +#define _WAVEJAMMER_8_ST 0xe02c +#define _WAVEJAMMER_16_MONO 0xe02d +#define _WAVEJAMMER_16_ST 0xe02e +#define _TEMPOCS_8_MONO 0xe02f +#define _TEMPOCS_8_ST 0xe030 +#define _TEMPOCS_16_MONO 0xe031 +#define _TEMPOCS_16_ST 0xe032 +#define _WAVEJAMMERCD_8_MONO 0xe033 +#define _WAVEJAMMERCD_8_ST 0xe034 +#define _WAVEJAMMERCD_16_MONO 0xe035 +#define _WAVEJAMMERCD_16_ST 0xe036 +#define _SOUND_BLASTER_8_MONO_R 0xe050 +#define _MICROSOFT_8_MONO_R 0xe051 +#define _SOUND_MASTER_II_8_MONO_R 0xe052 +#define _ADLIB_GOLD_8_MONO_R 0xe053 +#define _MV_PAS_8_MONO_R 0xe054 +#define _RAP10_8_MONO_R 0xe058 +#define _RAP10_16_MONO_R 0xe059 +#define _SB16_8_MONO_R 0xe05a +#define _SB16_8_ST_R 0xe05b +#define _SB16_16_MONO_R 0xe05c +#define _SB16_16_ST_R 0xe05d +#define _MV_PAS_16_MONO_R 0xe060 +#define _SOUNDSCAPE_8_MONO_R 0xe061 +#define _SOUNDSCAPE_8_ST_R 0xe062 +#define _SOUNDSCAPE_16_MONO_R 0xe063 +#define _SOUNDSCAPE_16_ST_R 0xe064 +#define _ESS_AUDIODRIVE_8_MONO_R 0xe065 +#define _ESS_AUDIODRIVE_8_ST_R 0xe066 +#define _ESS_AUDIODRIVE_16_MONO_R 0xe067 +#define _ESS_AUDIODRIVE_16_ST_R 0xe068 +#define _SPEECH_THING_8_MONO 0xe090 +#define _YAMAHA_8_MONO 0xe106 +#define _INT_SPEAKER_8_MONO 0xe107 + +// call indexes for the loadable drivers +enum +{ + _DRV_INIT, + _DRV_UNINIT, + _DRV_SETRATE, + _DRV_SETACTION, + _DRV_START, + _DRV_STOP, + _DRV_PAUSE, + _DRV_RESUME, + _DRV_CAPABILITIES, + _DRV_PLAY_FOREGROUND, + _DRV_GET_FILL_INFO, + _DRV_GET_CALL_FUNCTIONS, + _DRV_SET_CALL_FUNCTIONS +}; + +// fill info +typedef struct _tagFillInfo + { + + LPSTR lpFillHandler; // pointer to fill handler + LPWORD lpDMAFillCount; // pointer to dma count + LPSTR lpSampleList; // pointer to sample list + LPWORD lpDMAMasterVolume; // pointer to dma count + + } _SOS_FILL_INFO; + +// caps info structure +typedef struct _tagCapsInfo + { + + LPSTR lpPortList; // pointer to port list + LPSTR lpDMAList; // pointer to DMA list + LPSTR lpIRQList; // pointer to IRQ list + LPSTR lpRateList; // pointer to rate list + + } _SOS_CAPS_INFO; + +// maximum number of available voice +#define _MAX_VOICES 32 + +// structure definition +typedef struct _tagSAMPLE +{ + LPSTR samplePtr; // pointer to data buffer + LPSTR sampleData; // pointer to active data + LPSTR sampleLoopPtr; // pointer for loop back + + WORD sampleLength; // length of sample + WORD sampleIndex; // index into sample + WORD sampleLoopLength; // length of loop + + WORD sampleBytesLeft; // bytes left to play in sample + + WORD sampleLoopPoint; // byte count for loop point + WORD sampleLoopEndLength; // length of remaining chunk + + short sampleFlags; // control sample + short sampleVolume; // volume control + short sampleID; // sample ID + + short sampleChannel; // channel to play sample on + short sampleLoopCount; // loop count + short sampleLastFill; // last fill position + VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample + + WORD samplePitchAdd; + short samplePitchFraction; + + short samplePort; // port to use for non-dma digitized + + WORD sampleTotalBytes; + WORD sampleByteLength; + + short samplePanLocation; + short samplePanSpeed; + short samplePanDirection; + short samplePanStart; + short samplePanEnd; + + short sampleDelayBytes; + short sampleDelayRepeat; + + WORD sampleADPCMPredicted; + short sampleADPCMIndex; + + short sampleRootNoteMIDI; + + WORD sampleTemp1; + +} _SOS_SAMPLE; + +// enumeration for left or right channel +enum +{ + _LEFT_CHANNEL, + _RIGHT_CHANNEL, + _CENTER_CHANNEL, + _INTERLEAVED +}; + +// enumeration for foreground and background +enum +{ + _FOREGROUND, + _BACKGROUND +}; + +// defines for the sample flags +#define _ACTIVE 0x8000 +#define _LOOPING 0x4000 +#define _FIRST_TIME 0x2000 +#define _PENDING_RELEASE 0x1000 +#define _CONTINUE_BLOCK 0x0800 +#define _PITCH_SHIFT 0x0400 +#define _PANNING 0x0200 +#define _VOLUME 0x0100 +#define _TRANSLATE16TO8 0x0080 +#define _STAGE_LOOP 0x0040 +#define _TRANSLATE8TO16 0x0020 +#define _STEREOTOMONO 0x0010 + +// defines for the wParam flags +#define _SINGLE_SAMPLE 0x01 + +#define _SOS_DCAPS_AUTO_REINIT 0x01 +#define _SOS_DCAPS_MPU_401 0x02 +#define _SOS_DCAPS_OPL2 0x04 +#define _SOS_DCAPS_OPL3 0x08 +#define _SOS_DCAPS_OPL4 0x10 +#define _SOS_DCAPS_WAVETABLE 0x20 +#define _SOS_DCAPS_DL_SAMPLES 0x40 +#define _SOS_DCAPS_FIFO_DEVICE 0x80 +#define _SOS_DCAPS_ENV_NEEDED 0x100 +#define _SOS_DCAPS_PSEUDO_DMA1 0x200 +#define _SOS_DCAPS_SIGNED_DATA 0x8000 + +// file header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // number of drivers in the file + WORD wDrivers; + + // offset of first driver + WORD lOffset; + + // size of the file + WORD lFileSize; + +} _FILEHEADER; + +// driver header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // offset of next driver + WORD lNextDriver; + + // size of current driver + WORD wSize; + + // id for the current device + WORD wDeviceID; + + // id for the type of DOS extender + WORD wExtenderType; + +} _DRIVERHEADER; + +// device hardware information +typedef struct +{ + // port to be used + WORD wPort; + + // irq to use + WORD wIRQ; + + // dma channel to se + WORD wDMA; + + // extra parameter + WORD wParam; + +} _SOS_HARDWARE; + +// structure definition for start sample +typedef struct +{ + // pointer to sample + LPSTR lpSamplePtr; + + // size of the sample + WORD dwSampleSize; + + // number of times to loop the sample -1 is infinite + WORD wLoopCount; + + // channel to play sample on + WORD wChannel; + + // volume to play sample at + WORD wVolume; + + // id for the sample + WORD wSampleID; + + // far pointer to the callback function + VOID ( far cdecl *lpCallback )( WORD, WORD, WORD ); + + // port to use if driver is a non-dma background driver + WORD wSamplePort; + + // flags field + WORD wSampleFlags; + + // total length of sample including loops, etc.. + WORD dwSampleByteLength; + + // loop point for the sample + WORD dwSampleLoopPoint; + WORD dwSampleLoopLength; + + // pitch shifting components + WORD dwSamplePitchAdd; + WORD wSamplePitchFraction; + + // pan components + WORD wSamplePanLocation; + WORD wSamplePanSpeed; + WORD wSamplePanDirection; + WORD wSamplePanStart; + WORD wSamplePanEnd; + + // delay parts + WORD wSampleDelayBytes; + WORD wSampleDelayRepeat; + + // compression components + WORD dwSampleADPCMPredicted; + WORD wSampleADPCMIndex; + + // root note for pitch shifting + WORD wSampleRootNoteMIDI; + + // filler for future upgrades + WORD dwSampleTemp1; + WORD dwSampleTemp2; + WORD dwSampleTemp3; + +} _SOS_START_SAMPLE; + +// structure for initializing a driver +typedef struct +{ + WORD wBufferSize; + LPSTR lpBuffer; + BOOL wAllocateBuffer; + WORD wSampleRate; + WORD wParam; + LONG dwParam; + VOID ( far *lpFillHandler )( VOID ); + LPSTR lpDriverMemory; + LPSTR lpDriverMemoryCS; + LPSTR lpTimerMemory; + LPSTR lpTimerMemoryCS; + WORD wTimerID; + WORD wPhysical; + +} _SOS_INIT_DRIVER; + +// define for the timer types to use +#define _SOS_NORMAL_TIMER 0x00 + +// enumeration for the timer types +enum +{ + _TIMER_8_MONO = 0x1000, + _TIMER_8_ST, + _TIMER_16_MONO, + _TIMER_16_ST, + _TIMER_8_MONO_ULAW, + _TIMER_8_ST_ULAW, + _TIMER_16_MONO_ULAW, + _TIMER_16_ST_ULAW, + _TIMER_8_MONO_REC, + _TIMER_8_MONO_ULAW_REC, + _TIMER_UNDEFINED_1, + _TIMER_UNDEFINED_2, + _TIMER_UNDEFINED_3, + _TIMER_UNDEFINED_4, + _TIMER_UNDEFINED_5, + _TIMER_UNDEFINED_6, + _TIMER_UNDEFINED_7, + _TIMER_UNDEFINED_8, + _TIMER_UNDEFINED_9, + _TIMER_UNDEFINED_A, + _TIMER_UNDEFINED_B, + _TIMER_UNDEFINED_C, + _TIMER_UNDEFINED_D, + _TIMER_UNDEFINED_E, + _TIMER_UNDEFINED_F, + _TIMER_UNDEFINED_10, + _TIMER_UNDEFINED_11, + _TIMER_UNDEFINED_12, + _TIMER_UNDEFINED_13, + _TIMER_UNDEFINED_14, + _TIMER_UNDEFINED_15, + _TIMER_UNDEFINED_16, + _TIMER_8_SOUND_SOURCE, + _TIMER_8_SOUND_SOURCE_TANDY, + _TIMER_8_GENERAL_PORT, + _TIMER_8_GENERAL_PORT_REC +}; + +// define for no slots available +#define _ERR_NO_SLOTS ( WORD )-1 + +// error codes for the system +enum +{ + _ERR_NO_ERROR, + _ERR_DRIVER_NOT_LOADED, + _ERR_INVALID_POINTER, + _ERR_DETECT_INITIALIZED, + _ERR_FAIL_ON_FILE_OPEN, + _ERR_MEMORY_FAIL, + _ERR_INVALID_DRIVER_ID, + _ERR_NO_DRIVER_FOUND, + _ERR_DETECTION_FAILURE, + _ERR_DRIVER_LOADED, + _ERR_INVALID_HANDLE, + _ERR_NO_HANDLES, + _ERR_PAUSED, + _ERR_NOT_PAUSED, + _ERR_INVALID_DATA, + _ERR_DRV_FILE_FAIL, + _ERR_INVALID_PORT, + _ERR_INVALID_IRQ, + _ERR_INVALID_DMA, + _ERR_INVALID_DMA_IRQ, +// STREAM + _ERR_STREAM_PLAYING, + _ERR_STREAM_EMPTY, + _ERR_STREAM_PAUSED, + _ERR_STREAM_NOT_PAUSED +// END +}; + +// maximum number of timer events that can be registered +#define _TIMER_MAX_EVENTS 0x10 + +// flags for the debugging system +#define _SOS_DEBUG_NORMAL 0x0000 +#define _SOS_DEBUG_NO_TIMER 0x0001 +#define _SOS_TIMER_DPMI 0x0002 + +// define for types of DOS extenders +#define _SOS_RATIONAL 0x8000 +#define _SOS_FLASHTECK 0x4000 + +// defines for the types of timers for different +// dos extenders +#define _SOS_TIMER_NEAR 0x8000 +#define _SOS_TIMER_FAR 0x4000 + +// values for callback information +enum +{ + _SAMPLE_PROCESSED, + _SAMPLE_LOOPING, + _SAMPLE_DONE +}; + +// define for special 18.2 callback rate to dos +#define _TIMER_DOS_RATE 0xff00 + +#pragma pack() + +#pragma aux int_3 = "int 3" + +#pragma pack( 1 ) +typedef struct +{ + unsigned region_size; + unsigned offset; + unsigned segment; + unsigned short number_available; + unsigned short number_used; + unsigned page0; + +} EVDS_STRUCT; + +typedef struct +{ + unsigned region_size; + unsigned offset; + unsigned short segment; + unsigned short ID; + unsigned physical; + +} VDS_STRUCT; + +#pragma pack() + +#include "sosdata.h" +#include "sosfnct.h" + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOSDATA.H b/CODE/RP/MUNGA_L4/sos/wc/SOSDATA.H new file mode 100644 index 0000000..b2db154 --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOSDATA.H @@ -0,0 +1,110 @@ +/**************************************************************************** + + File : sosdata.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_DATA +#define _SOS_DATA + +#include + +#pragma pack(4) +extern WORD _sosDIGIData_Start; +extern WORD _sosDIGIData_End; +extern WORD _wSOSDriverLinear[]; +extern WORD _wSOSTimerLinear[]; +extern LPSTR _lpSOSDriver[]; +extern LPSTR _lpSOSTimer[]; +extern LPSTR _lpSOSDriverCS[]; +extern LPSTR _lpSOSTimerCS[]; +extern BOOL _wSOSDriverLoaded[]; +extern BOOL _wSOSTimerLoaded[]; +extern BOOL _wSOSDriverInitialized[]; +extern WORD _wSOSOutputRate[]; +extern WORD _wSOSDMABuffersize[]; +extern LONG _dwSOSDMABufferPhysical[]; +extern LPSTR _lpSOSDMABuffer[]; +extern BOOL _wTimerUsed; +extern VOID ( far *_lpSOSFillHandler[] )( VOID ); +extern WORD _wSOSTimerType[]; +extern WORD _wSOSDriverType[]; +extern _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ]; +extern LPWORD _lpSOSDMAIrqCount[]; +extern LPWORD _lpSOSDMAFillCount[]; +extern WORD _wSOSTmrNextCount; +extern VOID ( interrupt far *_lpSOSOldTimer )( VOID ); +extern WORD _wSOSDriverID[]; +extern _SOS_CAPABILITIES _sSOSDriverCaps[]; +extern WORD _wSOSDMAPortList[]; +extern BYTE _bSOSDMAChannel[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern BYTE _pSOSDriverPath[]; +extern BYTE _pSOSTempDriverPath[]; +extern BOOL _wTIMERUsed; +extern WORD _wTIMERValue; +extern VOID ( far * _lpTIMEREvents[] )( VOID ); +extern WORD _wTIMEREventRate[]; +extern WORD _dwTIMEREventFraction[]; +extern WORD _dwTIMEREventFractionCurrent[]; +extern BYTE _bSOSMIDITimerSongHandler[]; +extern BYTE _bSOSMIDISongHandle; +extern WORD _wSOSTimerMemHandle[]; +extern WORD _wSOSDriverMemHandle[]; +extern WORD _wSOSRealSeg[]; + +extern _FILEHEADER _sDETFileHeader; +extern _DRIVERHEADER _sDETDriverHeader; +extern _FILEHEADER sLOADFileHeader; +extern _DRIVERHEADER sLOADDriverHeader; +extern BOOL _wDETInitialized; +extern WORD _wDETLinear; +extern LPSTR _lpDETDriverBuffer; +extern LPSTR _lpDETDriverBufferCS; +extern WORD _hDETFile; +extern DWORD _dwDETDriverIndex; +extern WORD _wDETDriverIndexCur; +extern WORD _wDETMemHandle; +extern LPSOSDEVICECAPS _lpDETDeviceCaps; +extern _SOS_CAPABILITIES _sDETCaps; +extern PSTR _pSOSErrorStrings[]; +extern BOOL _wSOSBufferAllocated[]; +extern BOOL _wSOSSystemInitialized; +extern VDS_STRUCT _sSOSVDSInfo; +extern _SOS_FILL_INFO _sSOSFillInfo; +extern WORD _wSOSTimerEventIndex; +extern WORD _wSOSTimerEntered; +extern WORD _wSOSDriverSize[]; +extern WORD _wSOSTimerSize[]; + +#ifdef __cplusplus +extern "C" { +#endif +extern WORD _sosDIGIData1_Start; +extern WORD _sosDIGIData1_End; +extern WORD _sosDIGIData2_Start; +extern WORD _sosDIGIData2_End; +extern BYTE _bTIMERInstalled; +extern BYTE _bTIMERDPMI; +extern WORD wDetectPort; +extern WORD wDetectIRQ; +extern WORD wDetectDMA; +extern WORD wDetectParam; +#ifdef __cplusplus +} +#endif + +#pragma pack() + +#endif + diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOSDEFS.H b/CODE/RP/MUNGA_L4/sos/wc/SOSDEFS.H new file mode 100644 index 0000000..e5792cb --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOSDEFS.H @@ -0,0 +1,65 @@ +/**************************************************************************** + + File : sosdefs.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOSDEFS_DEFINED +#define _SOSDEFS_DEFINED + +#undef _TRUE +#undef _FALSE +#undef _NULL +enum + { + _FALSE, + _TRUE + }; + +#define _NULL 0 + +#ifndef VOID +#define VOID void +#endif +typedef int BOOL; +typedef unsigned int UINT; +typedef unsigned char BYTE; +typedef unsigned WORD; +#ifndef LONG +typedef signed long LONG; +#endif +typedef unsigned long DWORD; + +typedef BYTE * PBYTE; +typedef char near * PSTR; +typedef WORD * PWORD; +typedef LONG * PLONG; +typedef VOID * PVOID; + +typedef BYTE far * LPBYTE; +typedef BYTE far * LPSTR; +typedef WORD far * LPWORD; +typedef LONG far * LPLONG; +typedef VOID far * LPVOID; + +typedef BYTE huge * HPBYTE; +typedef BYTE huge * HPSTR; +typedef WORD huge * HPWORD; +typedef LONG huge * HPLONG; +typedef VOID huge * HPVOID; + +typedef unsigned HANDLE; + +#endif + diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOSFNCT.H b/CODE/RP/MUNGA_L4/sos/wc/SOSFNCT.H new file mode 100644 index 0000000..5af1642 --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOSFNCT.H @@ -0,0 +1,208 @@ +/**************************************************************************** + + File : sosfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_FUNCTIONS +#define _SOS_FUNCTIONS + +#ifdef __cplusplus // ECH +extern "C" { +#endif + +#pragma pack(4) + +WORD sosDIGILockMemory ( VOID ); +WORD sosDIGIUnLockMemory ( VOID ); +WORD sosDIGIInitSystem ( LPSTR, WORD ); +WORD sosDIGIUnInitSystem ( VOID ); +WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE far *, + _SOS_INIT_DRIVER far *, WORD far * ); +WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL ); +WORD sosDIGILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadDriver ( WORD ); +WORD sosDIGIGetDeviceCaps ( WORD, LPSOSDEVICECAPS ); + +#ifdef PHARLAP +LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * ); +#else +LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * ); +#endif + +WORD sosDIGIStopSample ( WORD, WORD ); +WORD sosDIGISamplesPlaying ( WORD ); +BOOL sosDIGISampleDone ( WORD, WORD ); +BOOL sosDIGISampleFilling ( WORD, WORD ); +WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE far * ); +WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE far * ); + + +WORD sosDIGIDetectInit ( LPSTR ); +WORD sosDIGIDetectUnInit ( VOID ); +WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES far *, WORD far * ); +WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES far *, WORD far * ); +WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES far *, WORD far * ); +WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE far * ); +WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES far * ); +WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE far * ); +PSTR sosGetErrorString ( WORD ); + +WORD sosDIGILoadTimer ( WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadTimer ( WORD ); + +WORD sosTIMERRegisterEvent ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle ); +WORD sosTIMERInitSystem ( WORD, WORD ); +WORD sosTIMERUnInitSystem ( WORD ); +WORD sosTIMERSetRate ( WORD ); +WORD sosTIMERRemoveEvent ( WORD ); +WORD sosTIMERAlterEventRate ( WORD, WORD ); +WORD sosTIMERGetEventRate ( WORD ); +VOID far sosTIMEROldHandler ( VOID ); +VOID far sosTIMERHandler ( VOID ); + +// functions in soscntl.c +WORD sosDIGISetSampleVolume ( WORD, WORD, WORD ); +WORD sosDIGIGetSampleVolume ( WORD, WORD ); +WORD sosDIGISetChannel ( WORD, WORD, WORD ); +WORD sosDIGIGetChannel ( WORD, WORD ); +WORD sosDIGIGetBytesProcessed ( WORD, WORD ); +WORD sosDIGIGetLoopCount ( WORD, WORD ); +WORD sosDIGISetPanLocation ( WORD, WORD, WORD ); +WORD sosDIGIGetPanLocation ( WORD, WORD ); +DWORD sosDIGISetPitch ( WORD, WORD, DWORD ); +DWORD sosDIGIGetPitch ( WORD, WORD ); +WORD sosDIGIGetDMAPosition ( WORD ); +WORD sosDIGISetPanSpeed ( WORD, WORD, WORD ); +WORD sosDIGIGetPanSpeed ( WORD, WORD ); +WORD sosDIGIGetSampleID ( WORD, WORD ); +WORD sosDIGIGetSampleHandle ( WORD, WORD ); +WORD sosDIGISetMasterVolume ( WORD, WORD ); +#ifdef PHARLAP +VOID sosFreeVDSPage ( unsigned short, unsigned short, DWORD ); +WORD sosAllocVDSPage ( unsigned short *, unsigned short *, DWORD * ); +#else +WORD sosAllocVDSPage ( LPSTR *, WORD *, WORD * ); +VOID sosFreeVDSPage ( WORD, WORD, LONG ); +#endif + +//#ifdef __cplusplus // ECH +//extern "C" { +//#endif + +#ifdef PHARLAP +extern int cdecl sosRealFree ( int ); +extern BOOL cdecl _sos_read( WORD, LPSTR, WORD, WORD * ); +extern int cdecl sosRealAlloc( int, int *, int * ); +extern void cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD ); +extern int cdecl sosGetCS( VOID ); +extern int cdecl sosGetES( VOID ); +#else +extern int cdecl sosRealAlloc ( int, int *, int * ); +extern int cdecl sosRealFree ( int ); +#endif + +// sos driver functions +extern WORD cdecl sosDRVLockMemory ( DWORD, DWORD ); +extern WORD cdecl sosDRVUnLockMemory ( DWORD, DWORD ); +extern void cdecl sosDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * ); +extern void cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * ); +extern void cdecl sosDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_CAPABILITIES far * ); +extern void cdecl sosDRVInit ( LPSTR, LPSTR, int, int, int, int, int, int ); +extern void cdecl sosDRVStart ( LPSTR, LPSTR, int, int ); +extern void cdecl sosDRVSetRate ( LPSTR, LPSTR, int ); +extern void cdecl sosDRVSetAction ( LPSTR, LPSTR ); +extern void cdecl sosDRVStop ( LPSTR, LPSTR ); +extern void cdecl sosDRVUnInit ( LPSTR, LPSTR ); +extern void cdecl sosDRVGetFillInfo ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * ); +extern void cdecl sosFillSampleStructs ( PSTR, LPSTR ); +extern WORD cdecl sosDetDRVExist ( LPSTR, LPSTR ); +extern WORD cdecl sosDetDRVGetSettings ( LPSTR, LPSTR ); +extern WORD cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR ); +extern WORD cdecl sosDIGIInitForWindows( WORD ); +extern WORD cdecl sosDIGIUnInitForWindows( WORD ); +extern LPSTR cdecl sosAllocateFarMem ( WORD, PSTR, WORD * ); +extern LPSTR cdecl sosCreateAliasCS ( LPSTR ); +extern VOID cdecl sosFreeSelector ( LPSTR, DWORD ); +extern LPSTR cdecl sosMAKEDOSPtr ( PSTR ); +extern VOID cdecl sosDetDRVSetEnvString ( DWORD, PSTR ); +extern PSTR cdecl sosDetDRVGetEnvString ( DWORD ); +extern VOID cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR ); +extern VOID cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR ); +extern WORD cdecl sosDRVGetFreeMemory ( VOID ); +extern WORD cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * ); +extern WORD cdecl sosDRVFreeVDSStruct ( WORD, WORD ); +extern WORD cdecl sosDRVIsWindowsActive ( VOID ); +extern WORD cdecl sosDRVVDSGetBuffer ( WORD ); +extern WORD cdecl sosDRVVDSFreeBuffer ( WORD ); +extern WORD cdecl getDS( VOID ); +extern WORD cdecl sosDRVMakeDMASelector ( WORD ); +extern WORD cdecl sosDRVFreeDMASelector ( WORD ); + + +extern void cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) ); +extern void cdecl sosTIMERDRVUnInit( void ); +extern void cdecl sosTIMERDRVHandler( void ); +extern void cdecl sosTIMERDRVFHandler( void ); +extern void cdecl sosTIMERDRVEnable( void ); +extern void cdecl sosTIMERDRVDisable( void ); +extern void cdecl sosTIMERDRVCallOld( void ); +extern void cdecl sosTIMERDRVSetRate( WORD ); +extern void cdecl sosDIGITimer_Start( void ); +extern void cdecl sosDIGITimer_End( void ); +extern void cdecl sosDIGIDrv_Start( void ); +extern void cdecl sosDIGIDrv_End( void ); +//#ifdef __cplusplus //ECH +//} +//#endif + +// external functions for handling system initialization and +// uninitialization +WORD sosEXDIGInitDriver ( WORD, WORD, WORD, LPSTR, + _SOS_HARDWARE far *, WORD * ); +WORD sosEXDIGIUnInitDriver ( VOID ); + +WORD sosEXDETFindDriver ( WORD, LPSTR, _SOS_HARDWARE far *, + _SOS_CAPABILITIES far * ); + +// memory locking prototypes +VOID sosDIGICaps_Start( VOID ); +VOID sosDIGICaps_End( VOID ); +VOID sosDIGIErr_Start( VOID ); +VOID sosDIGIErr_End( VOID ); +VOID sosDIGITmr_Start( VOID ); +VOID sosDIGITmr_End( VOID ); +VOID sosDIGIStart_Start( VOID ); +VOID sosDIGIStart_End( VOID ); +VOID sosDIGIPlyng_Start( VOID ); +VOID sosDIGIPlyng_End( VOID ); +VOID sosDIGIRate_Start( VOID ); +VOID sosDIGIRate_End( VOID ); +VOID sosDIGIDone_Start( VOID ); +VOID sosDIGIDone_End( VOID ); +VOID sosDIGIDetec_Start( VOID ); +VOID sosDIGIDetec_End( VOID ); +VOID sosDIGIInit_Start( VOID ); +VOID sosDIGIInit_End( VOID ); +VOID sosDIGILoad_Start( VOID ); +VOID sosDIGILoad_End( VOID ); +VOID sosDIGICntl_Start( VOID ); +VOID sosDIGICntl_End( VOID ); + +#pragma pack() + +#ifdef __cplusplus // ECH +} +#endif + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOSM.H b/CODE/RP/MUNGA_L4/sos/wc/SOSM.H new file mode 100644 index 0000000..183175e --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOSM.H @@ -0,0 +1,455 @@ +/**************************************************************************** + + File : sosm.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_MIDI_DEFINED +#define _SOS_MIDI_DEFINED + +#include "sosdefs.h" +#include "sos.h" + +#pragma pack(4) + +#define _SOS_MIDI_ERR -1 + +// number of drivers allowed to be open at one time +#define _SOS_MIDI_MAX_DRIVERS 5 + +// maximum number of allowed channels +#define _SOS_MIDI_MAX_CHANNELS 0x10 + +// structure definition for the capabilities +typedef struct +{ + BYTE szDeviceName[ 32 ]; // device name + WORD wDeviceVersion; // device version + WORD wFlags; // miscellaneous flags + WORD wProcessData; // process data before sending to driver + short far * lpPortList; // list of usable ports + short far * lpIRQList; // list of usable irq channels + WORD wDeviceID; // ID for the device + +} _SOS_MIDI_CAPABILITIES; + +#define LPSOSMIDIDEVICECAPS _SOS_MIDI_CAPABILITIES far * + +// call indexes for the loadable drivers +enum +{ + _DRV_MIDI_GET_CAPS, + _DRV_MIDI_GET_CALL_TABLE, + _DRV_MIDI_SPECIAL1 +}; + +// file header for the driver +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // number of drivers in the file + WORD wDrivers; + + // offset of first driver + WORD lOffset; + + // size of the file + WORD lFileSize; + +} _MIDIFILEHEADER; + +// driver header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // offset of next driver + WORD lNextDriver; + + // size of current driver + WORD wSize; + + // id for the current device + WORD wDeviceID; + + // id for the extender type + WORD wExtenderType; + +} _MIDIDRIVERHEADER; + +// device hardware information +typedef struct +{ + // port to be used + WORD wPort; + + // IRQ for the board + WORD wIRQ; + + // extra parameter + WORD wParam; + +} _SOS_MIDI_HARDWARE; + +// structure for initializing a digital driver +typedef struct +{ + // ID for the digital driver + WORD wDriverID; + + // timer rate to use + WORD wTimerRate; + + // timer callback rate to use + WORD wTimerCallbackRate; + + // max voices for the driver to use + WORD wMaxVoices; + + // velocity sensing flag + WORD wVelocitySensing; + + // init driver info + _SOS_INIT_DRIVER far * sDIGIDriverInfo; + + // hardware information + _SOS_HARDWARE far * sDIGIHardwareInfo; + +} _SOS_MIDI_DIGI_INIT_DRIVER; + +// structure for initializing a driver +typedef struct +{ + // type of driver to use if using a digital driver + WORD wDIGIDriverID; + + // pointer to driver memory + VOID far * lpDriverMemory; + VOID far * lpDriverMemoryCS; + + // pointer to digital driver initialization information + _SOS_MIDI_DIGI_INIT_DRIVER far * sDIGIInitInfo; + + // miscellaneous WORD parameter for driver + WORD wParam; + + // miscellaneous DWORD parameter for driver + DWORD dwParam; + +} _SOS_MIDI_INIT_DRIVER; + +// structure for starting a song +typedef struct +{ + // pointer to song memory + BYTE _huge * lpSongData; + + // pointer to callback function for pertinent song information + VOID ( far * lpSongCallback )( WORD ); + +} _SOS_MIDI_INIT_SONG; + +// define to indicate that track mapping can be used +// from the midi file for the song +#define _MIDI_MAP_TRACK 0xff + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ]; + +} _SOS_MIDI_TRACK_DEVICE; + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ][ 5 ]; + +} _SOS_MIDI_TRACK_DEVICE1; + +// NEW +// header for the NDMF format MIDI file +typedef struct +{ + // ID for the file + BYTE szFileID[ 32 ]; + + WORD dwBranchOffset; + WORD temp1; + WORD temp2; + WORD temp3; + +// // name of the instrument file to use with the song +// BYTE szInstrumentFile[ 16 ]; + + // number of tracks in the song + WORD wNDMFTracks; + + // ticks/quarter note song is used at + WORD wTicksQuarterNote; + + // tempo + WORD wTempo; + + // time for song to play at current tempo + WORD wTimeToPlay; + + // channel mapping priority information + WORD wChannelPriority[ _SOS_MIDI_MAX_CHANNELS ]; + + // channel mapping information + _SOS_MIDI_TRACK_DEVICE1 sTrackMap; + + // array of flags for which controllers to restore on a loop/branch + BYTE bCtrlRestore[ 128 ]; + + // pointer to callback function for song to call with + // pertinent information + VOID ( far * lpSongCallback )( WORD ); + +} _NDMF_FILE_HEADER; +// END + +// header for the tracks in the NDMF format MIDI file +typedef struct +{ + // track number + WORD wTrackNumber; + + // length of the track + WORD wTrackLength; + + // channel used on the track + WORD wChannel; + +} _NDMF_TRACK_HEADER; + +// MIDI event structure +typedef struct +{ + // dummy name to access midi data from + BYTE bMidiData[ 256 ]; + +} _NDMF_MIDI_EVENT; + +// maximum number of songs that can be played at any time +#define _SOS_MIDI_MAX_SONGS 8 + +// maximum number of tracks that can be used +#define _SOS_MIDI_MAX_TRACKS 32 + +// number of driver functions +#define _SOS_MIDI_DRV_FUNCTIONS 13 + +// enumeration for all of the drv functions +enum +{ + _MIDI_DRV_SEND_DATA, + _MIDI_DRV_INIT, + _MIDI_DRV_UNINIT, + _MIDI_DRV_RESET, + _MIDI_DRV_SET_INST_DATA +}; + +// defines for the loadable driver ids +#define _MIDI_SOUND_MASTER_II 0xa000 +#define _MIDI_MPU_401 0xa001 +#define _MIDI_FM 0xa002 +#define _MIDI_OPL2 0xa002 +#define _MIDI_CALLBACK 0xa003 +#define _MIDI_MT_32 0xa004 +#define _MIDI_DIGI 0xa005 +#define _MIDI_INTERNAL_SPEAKER 0xa006 +#define _MIDI_WAVE_TABLE_SYNTH 0xa007 +#define _MIDI_AWE32 0xa008 +#define _MIDI_OPL3 0xa009 +#define _MIDI_GUS 0xa00a + +// structure for the hmi instrument file header +typedef struct +{ + // file id type + BYTE szFileID[ 32 ]; + + // file version + WORD wFileVersion; + + // size of the file + WORD dwFileSize; + +} _HMI_INS_FILE_HEADER; + + +// define for identifying a drum instrument +#define _SOS_MIDI_DRUM_INS ( short )0x8000 + +// maximum number of timer events that can be registered +#define _TIMER_MAX_EVENTS 0x10 + +// structure for digital driver queue element +typedef struct _tagQueueElement +{ + // handle for the sample + WORD wSampleHandle; + + // id for the sample + WORD wSampleID; + + // velocity for the sample + WORD wVelocity; + + // channel for the sample + WORD wChannel; + +} _DIGI_QUEUE_ELEMENT; + +// maximum number of instruments that can be set in the +// digital driver +#define _MAX_INS 128 + +// define for the maximum number of times a channel can be stolen +#define _SOS_MIDI_MAX_LEVELS 0x04 + +// structure for MIDI information to be stored on the local stack +// when a channel is stolen +typedef struct +{ + // used element + BYTE bUsed; + + // last pitch bend information sent + BYTE bPitchBend; + + // channel volume + BYTE bChannelVolume; + + // instrument information + BYTE bInstrument; + + // sustain pedal + BYTE bSustain; + +} _SOS_MIDI_CHANNEL_DATA; + +// flags for the debugging system +#define _SOS_DEBUG_NORMAL 0x0000 +#define _SOS_DEBUG_NO_TIMER 0x0001 + +// ID for 32 bit MIDI file +#define _SOS_MIDI_FILE_ID "HMIMIDIP" + +// structure for branch location controller +typedef struct +{ + // offset from start of track data + WORD dwOffset; + + // branch ID number + BYTE bBranchID; + + // current instrument + BYTE bInstrument; + + // current loop count for temporary storage + // so that a track can be looped without + // needing any data from the program + BYTE bLoopCount; + + // number of controller messages stored + BYTE bCtrlChangeCount; + + // offset of control change information from start of file + WORD lpCtrlChangeData; + WORD lpCtrlChangeDataTemp; + + // reserved fields + WORD wReserved1; + WORD wReserved2; + +} _SOS_BRANCH_POINT; + +#define _SOS_MIDI_FADE_IN 0x01 +#define _SOS_MIDI_FADE_OUT 0x02 +#define _SOS_MIDI_FADE_OUT_STOP 0x04 + +// structure for digital drums to use to store midi information +typedef struct +{ + // current volume + WORD wVolume; + + // current pan position + WORD wPanPosition; + + // reserved + DWORD dwReserved; + +} _SOS_MIDI_DIGI_CHANNEL; + +// instrument file header structure +typedef struct +{ + // file ID + BYTE szID[ 32 ]; + + // file version + WORD wVersion; + + // instruments in file + WORD wInstruments; + + // list of pointers to start sample structures + _SOS_START_SAMPLE far * lpStartSample[ _MAX_INS ]; + + DWORD temp1; + DWORD temp2; + +} _WAVE_FILE_HEADER; + +#pragma pack() + +// define for the busy error returned from send data +#define _ERR_DRIVER_BUSY 0xf000 + +// NEW +// defines for the looping branch controllers +#define _SOS_SET_FLAG 103 +#define _SOS_RESET_FLAG 104 +#define _SOS_BRANCH1 108 +#define _SOS_BRANCH2 109 +#define _SOS_BRANCH3 110 +#define _SOS_BRANCH4 111 +#define _SOS_BRANCH5 112 +#define _SOS_BRANCH6 113 +#define _SOS_BRANCH7 114 +#define _SOS_BRANCH8 115 +#define _SOS_BRANCH9 116 +#define _SOS_BRANCH10 117 +#define _SOS_BRANCH11 118 +#define _SOS_BRANCH12 119 +#define _SOS_BRANCH13 120 +#define _SOS_BRANCH14 121 + +// define for the program change controller flag +#define _SOS_PROGRAM_CHANGE_FLAG 108 + +// END +#include "sosmdata.h" +#include "sosmfnct.h" + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOSMDATA.H b/CODE/RP/MUNGA_L4/sos/wc/SOSMDATA.H new file mode 100644 index 0000000..46808df --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOSMDATA.H @@ -0,0 +1,125 @@ +/**************************************************************************** + + File : sosmdata.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOS_MIDI_DATA +#define _SOS_MIDI_DATA + +#include "sos.h" + +#pragma pack(4) + +extern WORD _wSOSMIDIDriverLinear[]; +extern LPSTR _lpSOSMIDIDriver[]; +extern LPSTR _lpSOSMIDIDriverCS[]; +extern WORD _wSOSMIDIMemHandle[]; +extern BOOL _wSOSMIDIDriverLoaded[]; +extern WORD _wSOSMIDIDriverType[]; +extern WORD _wSOSMIDIDriverID[]; +extern DWORD _dwSOSMIDITrackDeltaCurrent[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDIActiveTracks[]; +extern WORD _wSOSMIDITotalTracks[]; +extern DWORD _dwSOSMIDITrackDeltaTime[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDISongPaused[]; +extern WORD _wSOSMIDISongMuted[]; +extern BOOL _wSOSMIDISongActive[]; +extern BYTE _bSOSMIDIEventSize[]; +extern BYTE _bSOSMIDIEventSizeControl[]; +extern _SOS_MIDI_CAPABILITIES far * _lpSOSMIDIDriverCaps[]; +extern _SOS_MIDI_TRACK_DEVICE far * _sSOSMIDITrackMap[]; +extern _NDMF_MIDI_EVENT _huge * _lpSOSMIDITrack[][_SOS_MIDI_MAX_TRACKS]; +extern WORD ( cdecl far *_lpSOSMIDIDrvFunction[ _SOS_MIDI_MAX_DRIVERS ][ _SOS_MIDI_DRV_FUNCTIONS ] )( LPSTR, WORD, WORD ); +extern _NDMF_FILE_HEADER far * _sSOSMIDISongHeader[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern WORD _wSOSMIDIEventHandle[]; +extern BYTE _szSOSMIDIDrvFile[]; +extern _MIDIFILEHEADER _sSOSMIDIDRVFileHeader; +extern _MIDIDRIVERHEADER _sSOSMIDIDRVDriverHeader; +extern BOOL _wSOSMIDISysInititalized; +extern WORD ( cdecl far *_lpSOSMIDICBCKDrvFunctions[] )( LPSTR, WORD, WORD ); +extern VOID ( cdecl far *_lpSOSMIDICBCKFunctions )( LPSTR, WORD, WORD ); +extern WORD _wMIDIDIGISampleQueueHead[]; +extern WORD _wMIDIDIGISampleQueueTail[]; +extern WORD _wMIDIDIGIMaxSamples[]; +extern WORD _wMIDIDIGIUsedSamples[]; +extern _DIGI_QUEUE_ELEMENT _sMIDIDIGIQueue[][ _MAX_VOICES ]; + + +extern WORD ( cdecl far *_lpMIDIDIGIDrvFunctions[] )( LPSTR, WORD, WORD ); +extern _SOS_START_SAMPLE far * _sMIDIDIGIStartSample[][ _MAX_INS ]; +extern _HMI_INS_FILE_HEADER far * _sMIDIDIGIInsFileHeader[]; +extern WORD _wMIDIDIGIDriverHandle[]; +extern WORD _wMIDIDIGIDriverInitialized[]; +extern WORD _wMIDIDIGITimerEventHandle[]; +extern WORD _wMIDIDIGIDriverInitMIDI[]; +extern WORD _wMIDIDIGIVelocitySensing[]; +extern BYTE _szMIDIDIGIInsFileID[]; + +extern BYTE _bSOSMIDIMasterVolume; +extern BYTE _bSOSMIDIDeviceChannelVolume[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIMT32SendData; + +extern LPSTR lpFake; +extern WORD wFake; + +extern _NDMF_TRACK_HEADER _huge *_lpSOSMIDITrackHeaders[][ _SOS_MIDI_MAX_TRACKS ]; +extern BYTE _bSOSMIDIChannelRemap[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIChannelPriority[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerChannel[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerSong[][ _SOS_MIDI_MAX_CHANNELS ]; +extern _SOS_MIDI_CHANNEL_DATA _sSOSMIDIChannelData[][ _SOS_MIDI_MAX_CHANNELS ][ _SOS_MIDI_MAX_LEVELS ]; +extern BYTE _bSOSMIDIChannelDataIndex[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIData[]; +extern BYTE _bSOSMIDIData1[]; +extern BYTE _bSOSMIDIDeviceLowPriority[]; +extern WORD _wSOSMIDIChannelStealing; +extern BYTE _bSOSMIDIDeviceChannelActive[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIDeviceChannelAvailable[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDISongHandle; +extern BYTE _szMIDIMIDIFileID[]; +extern BYTE _pSOSMIDIDriverPath[]; +extern BYTE _pSOSMIDITempDriverPath[]; +extern WORD sosMIDIData_Start; +extern WORD sosMIDIData_End; +extern WORD ( cdecl far *_lpSOSMIDIAWEDrvFunctions[5] )( LPSTR, WORD, WORD ); +extern WORD _wSOSGravisTimerHandle; +extern WORD _wSOSMIDISongVolume[]; + +extern _SOS_BRANCH_POINT far * _lpMIDIBranchData[][ _SOS_MIDI_MAX_TRACKS ]; +extern WORD ( far *_lpSOSMIDIBranchCallback[] )( WORD, BYTE, BYTE ); +extern WORD ( far *_lpSOSMIDILoopCallback[] )( WORD, BYTE, BYTE, BYTE ); +extern WORD ( far *_lpSOSMIDITriggerCallback[][ 127 ] )( WORD, BYTE, BYTE ); +extern BYTE _bSOSMIDIBranchOccurred; + +extern WORD _wSOSMIDIVolumeFadeDirection[]; +extern DWORD _dwSOSMIDIVolumeFadeFraction[]; +extern DWORD _dwSOSMIDIVolumeFadeVolume[]; +extern WORD _wSOSMIDIVolumeFadeTicks[]; +extern BYTE _bSOSMIDIHandleVolumeFade[]; +extern WORD _wSOSDIGIMIDIHandle[]; + +extern _SOS_MIDI_DIGI_CHANNEL _sMIDIDIGIChannel[]; + +extern WORD ( cdecl far *_lpMIDIWAVEDrvFunctions[] )( LPSTR, WORD, WORD ); +extern WORD _wSOSMIDIChannelMuted[][ _SOS_MIDI_MAX_CHANNELS ]; + +extern BYTE _szPLYMIDIBuffer[]; +extern WORD _wPLYMIDIBufferIndex; +extern WORD _wSOSMIDIDriverSize[]; + +#pragma pack() + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOSMFNCT.H b/CODE/RP/MUNGA_L4/sos/wc/SOSMFNCT.H new file mode 100644 index 0000000..0a0298c --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOSMFNCT.H @@ -0,0 +1,175 @@ +/**************************************************************************** + + File : sosmfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_MIDI_FUNCTIONS +#define _SOS_MIDI_FUNCTIONS + +#ifdef __cplusplus // ECH +extern "C" { +#endif + +#pragma pack(4) + +VOID interrupt far sosMIDITimerHandler ( VOID ); +WORD sosMIDILockMemory ( VOID ); +WORD sosMIDIUnLockMemory ( VOID ); +WORD sosMIDIGetDeviceCaps ( WORD, LPSOSMIDIDEVICECAPS ); +WORD sosMIDIInitSystem ( LPSTR, WORD ); +WORD sosMIDIUnInitSystem ( VOID ); +WORD sosMIDIInitDriver ( WORD, _SOS_MIDI_HARDWARE far *, + _SOS_MIDI_INIT_DRIVER far *, WORD far * ); +WORD sosMIDIUnInitDriver ( WORD, BOOL ); +WORD sosMIDILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * ); +WORD sosMIDIUnLoadDriver ( WORD ); +WORD sosMIDIInitSong ( _SOS_MIDI_INIT_SONG far *, + _SOS_MIDI_TRACK_DEVICE far *, + WORD far * ); +WORD sosMIDIUnInitSong ( WORD ); +WORD sosMIDIResetSong ( WORD, _SOS_MIDI_INIT_SONG far * ); +WORD sosMIDIStartSong ( WORD ); +WORD sosMIDIStopSong ( WORD ); +WORD sosMIDIPauseSong ( WORD, WORD ); +WORD sosMIDIMuteSong ( WORD ); +WORD sosMIDIUnMuteSong ( WORD ); +WORD sosMIDIResumeSong ( WORD ); +BOOL sosMIDISongDone ( WORD ); +WORD sosMIDISongAlterTempo ( WORD, WORD ); +WORD sosMIDIGetDeltaTime ( LPSTR, DWORD far * ); +WORD sosMIDISongGetTimeToPlay ( WORD ); +BYTE _huge * sosMIDINormalizePtr ( BYTE _huge * ); +WORD sosMIDISetInsData ( WORD, LPSTR, WORD ); +WORD sosMIDIResetDriver ( WORD ); +BOOL sosMIDIHandleMIDIData ( WORD, LPSTR, WORD, WORD ); +WORD sosMIDISendMIDIData ( WORD, LPSTR, WORD ); +// NEW +VOID sosMIDISetTrackState ( WORD, WORD, WORD ); +// END + +// compiled in drivers function interface +LPSTR digiGetCallTable ( VOID ); +LPSTR callbackGetCallTable ( VOID ); +LPSTR aweGetCallTable ( VOID ); + +WORD cdecl far callbackSendData ( LPSTR, WORD, WORD ); +WORD cdecl far callbackInit ( LPSTR, WORD, WORD ); +WORD cdecl far callbackUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far callbackReset ( LPSTR, WORD, WORD ); +WORD cdecl far callbackSetInstrumentData ( LPSTR, WORD, WORD ); + +WORD cdecl far aweSendData ( LPSTR, WORD, WORD ); +WORD cdecl far aweInit ( LPSTR, WORD, WORD ); +WORD cdecl far aweUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far aweReset ( LPSTR, WORD, WORD ); +WORD cdecl far aweSetInstrumentData ( LPSTR, WORD, WORD ); + +// function prototypes +WORD cdecl far digiSendData ( LPSTR, WORD, WORD ); +WORD cdecl far digiInit ( LPSTR, WORD, WORD ); +WORD cdecl far digiUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far digiReset ( LPSTR, WORD, WORD ); +WORD cdecl far digiSetInstrumentData ( LPSTR, WORD, WORD ); + +LPSTR waveGetCallTable ( VOID ); +WORD cdecl far waveSendData ( LPSTR, WORD, WORD ); +WORD cdecl far waveInit ( LPSTR, WORD, WORD ); +WORD cdecl far waveUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far waveReset ( LPSTR, WORD, WORD ); +WORD cdecl far waveSetInstrumentData ( LPSTR, WORD, WORD ); +VOID cdecl far waveSampleCallback( WORD, WORD, WORD ); + +VOID digiQueueInit ( WORD, WORD ); +VOID digiQueueUnInit ( WORD ); +WORD digiQueueAddItem ( WORD, WORD, WORD, WORD, WORD ); +WORD digiQueueGetItem ( WORD, WORD ); +WORD digiQueueGetItemWAVE ( WORD ); +WORD digiQueueDeleteItem ( WORD, WORD ); +WORD digiQueueDeleteItemWAVE ( WORD, WORD ); +WORD digiQueueDeleteItemMIDI ( WORD, WORD, WORD ); +WORD digiQueueFindItemMIDI ( WORD, WORD, WORD ); + +// function prototypes +VOID cdecl far digiSampleCallback( WORD, WORD, WORD ); + +WORD sosMIDIRegisterBranchFunction ( WORD, WORD ( far * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIRegisterLoopFunction ( WORD, WORD ( far * )( WORD, BYTE, BYTE, BYTE ) ); +WORD sosMIDIRegisterTriggerFunction( WORD, BYTE, WORD ( far * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIBranchToTrackLocation ( WORD, BYTE, BYTE ); +WORD sosMIDIBranchToSongLocation ( WORD, BYTE ); + +//#ifdef __cplusplus // ECH +//extern "C" { +//#endif + +extern void cdecl sosMIDIDRVGetCapsInfo( LPSTR, LPSTR, _SOS_MIDI_CAPABILITIES far * ); +extern void cdecl sosMIDIDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_MIDI_CAPABILITIES far * ); +extern void cdecl sosMIDIDRVGetFuncsPtr( LPSTR, LPSTR, LPSTR ); +extern LPSTR cdecl sosMIDIDRVSpecialFunction( LPSTR, LPSTR, WORD ); +extern WORD cdecl xgetES( void ); + +//#ifdef __cplusplus // ECH +//} +//#endif + +BOOL sosMIDIResetChannelStealing ( WORD ); +WORD sosMIDIEnableChannelStealing( WORD ); +VOID far sosMIDISongHandler( VOID ); + +WORD sosMIDISetMT32InsData ( WORD, LPSTR, WORD ); +WORD sosMIDISetMasterVolume ( BYTE ); +VOID far sosMIDIMT32Timer ( VOID ); + +WORD sosMIDISetSongVolume ( WORD, BYTE ); +WORD sosMIDIFadeSong ( WORD, WORD, WORD, BYTE, BYTE, WORD ); + +// functions for memory locking +VOID sosMIDICaps_Start( VOID ); +VOID sosMIDICaps_End( VOID ); +VOID sosMIDICbck_Start( VOID ); +VOID sosMIDICbck_End( VOID ); +VOID sosMIDIDigi_Start( VOID ); +VOID sosMIDIDigi_End( VOID ); +VOID sosMIDIDone_Start( VOID ); +VOID sosMIDIDone_End( VOID ); +VOID sosMIDIDq_Start( VOID ); +VOID sosMIDIDq_End( VOID ); +VOID sosMIDIInit_Start( VOID ); +VOID sosMIDIInit_End( VOID ); +VOID sosMIDIIns_Start( VOID ); +VOID sosMIDIIns_End( VOID ); +VOID sosMIDILoad_Start( VOID ); +VOID sosMIDILoad_End( VOID ); +VOID sosMIDIPause_Start( VOID ); +VOID sosMIDIPause_End( VOID ); +VOID sosMIDIPtr_Start( VOID ); +VOID sosMIDIPtr_End( VOID ); +VOID sosMIDISong_Start( VOID ); +VOID sosMIDISong_End( VOID ); +VOID sosMIDISt_Start( VOID ); +VOID sosMIDISt_End( VOID ); +VOID sosMIDITmpo_Start( VOID ); +VOID sosMIDITmpo_End( VOID ); +VOID sosMIDITmr_Start( VOID ); +VOID sosMIDITmr_End( VOID ); + +void StringOut( BYTE X, BYTE Y, BYTE * String, BYTE Color ); + +#pragma pack() + +#ifdef __cplusplus // ECH +} +#endif + +#endif diff --git a/CODE/RP/MUNGA_L4/sos/wc/SOSRES.H b/CODE/RP/MUNGA_L4/sos/wc/SOSRES.H new file mode 100644 index 0000000..91050dd --- /dev/null +++ b/CODE/RP/MUNGA_L4/sos/wc/SOSRES.H @@ -0,0 +1,110 @@ +/**************************************************************************** + + File : sosres.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#define _SOS_RESOURCE +#ifndef _SOS_RESOURCE +#define _SOS_RESOURCE + +// structure for resource file header +typedef struct +{ + // file version + WORD wVersion; + + // file size + LONG dwFileSize; + + // number of resources in file + WORD wResCount; + + // offset of resource data from top of file + LONG dwResOffset; + + // offset of sync track from top of file + LONG dwSyncTrackOffset; + +} _RES_FILE_HEADER; + +// structure for resource block header +typedef struct +{ + // resource id + WORD wID; + + // resource type + WORD wResType; + + // offset of next block + LONG dwNextBlock; + + // size of the current resource information + LONG dwResSize; + + // rate to play block at + WORD wBlockRate; + + // id for the sync track to use + WORD wSyncTrackID; + +} _RES_BLOCK_HEADER; + +// structure for sync mark tag +typedef struct _tagSYNCMARK +{ + // ID of the type of mark being used + WORD wID; + + // location in data of sync mark + LONG dwSyncOffset; + + // length of sync block + LONG dwSyncSize; + + // start sample data + _SOS_START_SAMPLE sampleData; + +} _RES_SYNCMARK; + +typedef union +{ + // structure for sync mark tag + _RES_SYNCMARK syncMark; + +} _RES_TAG; + +// union for filter information for prepareWave +typedef union +{ + // filter type + WORD wFilterID; + + // structure for volume + struct volume + { + WORD wVolume; + }; + + // structure for delay + struct delay + { + WORD wDelaySamples; + }; + +} _SOS_FILTER; + + +#endif + diff --git a/CODE/RP/MUNGA_L4/sos/wc/vssver.scc b/CODE/RP/MUNGA_L4/sos/wc/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..faf0de0e5b909eed145fdedaefc28db0dc644cb5 GIT binary patch literal 160 zcmXpJVq`d2=P%iL-obO(RqsctpMq*~CWl^nV8s9i4}r9|H0R&HMw@>y0!1DH`91Nu z%gdX5!2HKRKG(D+t@%H~!2BmbzL#;)?xU^AVE$7eKZ4y{^SL)GnEwpOPk(+rf4i9g enExEe=QBC~L9JfwrSyV7>%4B8c*0ZYGq*b*>SJ`T0 zX?E?Vop+{bIp?ZXxpgbHGjFCZ^Qu(^p&s?vH{b6+zx#aee&73jzrVY$`%VKwdw#T) zv^yZYa)A3UZ87%C#q(F?OWp*GWjOz-4y=Bq+?->{j>UdufRWC?5vhi3eX#RKd(7%YyC5N z6KwzW<{b4>1e)SQAe7t^Hr(e(&{p8rxiP7wwQgu@u$tAJt4(Ux>g!X%8F6>(EC;&K zHsI#V{2oz#FWMG-GFTv$+K-}lf#)W=$jZ%e^lrV|z7LA_)}r@-#fdbQ@a>mqJ8&lR z+q}AGTWEW*&{b-FY`XyM0OpwYIFH_FMmvIY#`3KczuiXDz&yUX)4(qh?F4>&NbW*5 z=c4K0y0ka_{)pkBoxzUFUUON$C!pU2vv`%Qa&`*Z1zhEw**a#Kj%I-QnwFmg{2a6^ zxUBNgP!%H|{T?_W_6l8XNJ764)>=DU8_6?6?*;GG$jFRX3-ms4B0r;o-$g+)!3C8; z)>`J`oPORca2xfZyDFpz?FLTuFfwbixrlZLUymOylCG4YJ-~k-5Ju9=PBuSy7Jzm2(qDo4J1)^n3>t^gAA^h87iP(_X>=O+ zF1dB%Ht88!3>Hh`YO?~D(Vu_=6eIq*lnwMT@HG2`3s+Z&P6rRDA|41j&!RKH9s9mJ z{D!d%ZRJZKOg#zd9*Pp+KDGu&i29d(JF4(MsNf}1Sf=zrDB1?h_|@ykxrg(3-xi!! LznS*j;t~3PLw)e$ literal 0 HcmV?d00001 diff --git a/CODE/RP/OPT.mak b/CODE/RP/OPT.mak new file mode 100644 index 0000000..2f58a56 --- /dev/null +++ b/CODE/RP/OPT.mak @@ -0,0 +1,47 @@ +LINK_OPTIONS = -Tpe -ax -L$(LIBRARY_PATH) -m +BCC = bcc32 +TASM_OPTIONS = +MAKE_TEST = 1 + +STARTUP_OBJ = $(STARTUP_ROOT)\c0x32.obj +STARTUP_LIBS = $(STARTUP_ROOT)\dpmi32.lib $(STARTUP_ROOT)\cw32.lib + +LIB_OPTIONS = /P32 + +$(CFG_FILE): opt.mak make.cfg $(BPATH) + copy &&| +-DLBE4;DEBUG_LEVEL=0;DEBUG_STREAM=cout;MESSAGE_BUFFERING=False +-b +-r +-ff +-AT +-k- +-N- +-v- +-5 +-a4 +-V +-Jg +-x- +-RT- +-O2 +-Ot +-Oc +-Og +-O +-Ol +-Z +-Ob +-Oe +-Oi +-Om +-Op +-Ov +-w +-c +-I$(INCLUDE_PATH) +-H +-H=$(HEADER_FILE) +-Hc +-n$(TARGET_DIR) +| $(CFG_FILE) diff --git a/CODE/RP/RP/BLOCKER.HPP b/CODE/RP/RP/BLOCKER.HPP new file mode 100644 index 0000000..bba37b4 --- /dev/null +++ b/CODE/RP/RP/BLOCKER.HPP @@ -0,0 +1,90 @@ +//===========================================================================// +// File: blocker.hh // +// Project: Red Planet // +// Contents: Blocker Implementation for Martian football // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/09/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(BLOCKER_HPP) +# define BLOCKER_HPP + +# if !defined(CRUSHER_HPP) +# include +# endif + + //########################################################################## + //########################### Blocker ################################ + //########################################################################## +class Blocker: + public Crusher + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + public: + void + DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + void + ScoreMessageHandler(RPPlayer::ScoreMessage *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + typedef void + (Blocker::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + PlayerSimulation(Scalar time_slice); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + + static Blocker* + Make(MakeMessage *creation_message); + + Blocker( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~Blocker(); + + Logical + TestInstance() const; + + void + AddOffensivePlayer(OffensivePlayer &offensive_player); + + + }; + +#endif diff --git a/CODE/RP/RP/BOOSTER.HPP b/CODE/RP/RP/BOOSTER.HPP new file mode 100644 index 0000000..9f23aa4 --- /dev/null +++ b/CODE/RP/RP/BOOSTER.HPP @@ -0,0 +1,174 @@ +//===========================================================================// +// File: booster.hh // +// Project: Red Planet // +// Contents: Interface specification for vectored thrust vehicles // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/13/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(BOOSTER_HPP) +# define BOOSTER_HPP + +# if !defined(VTVSUB_HPP) +# include +# endif + + //########################################################################## + //##################### Booster::SubsystemResource ################### + //########################################################################## + + struct Booster__SubsystemResource: + public VTVSubsystem::SubsystemResource + { + int boosterCount; + Scalar + burnTime, + boosterAcceleration; + }; + + //########################################################################## + //############################ Booster ############################### + //########################################################################## + + class Booster: + public VTVSubsystem + { + friend class VTV; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Messageing Support + // + public: + enum { + ActivateMessageID = VTVSubsystem::NextMessageID, + ConfigureMappablesMessageID, + ChooseButtonMessageID, + NextMessageID + }; + + void + ActivateMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigureMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChooseButtonMessageHandler( + ReceiverDataMessageOf *message + ); + + protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + BurnTimeRemainingAttributeID = VTVSubsystem::NextAttributeID, + BoostersRemainingAttributeID, + ScaleFactorAttributeID, + SmokeDensityAttributeID, + PercentDoneAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Scalar burnTimeRemaining; + Scalar boostersRemaining; + Vector3D scaleFactor; + Scalar smokeDensity; + Scalar percentDone; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + enum { + BoosterBurning = Subsystem::StateCount, + StateCount + }; + + typedef void + (Booster::*Performance)(Scalar time_slice); + + void + BoosterSimulation(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Damage Support + // + void + DeathReset(int reset_command); + void + DeathShutdown(int shutdown_command); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef Booster__SubsystemResource SubsystemResource; + + static int + CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ); + + Booster( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Booster(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local data for the Booster class + // + protected: + Scalar burnTimeMax; + Scalar acceleration; + int maxBoosters; + }; + +#endif diff --git a/CODE/RP/RP/CRUSHER.HPP b/CODE/RP/RP/CRUSHER.HPP new file mode 100644 index 0000000..91c3f08 --- /dev/null +++ b/CODE/RP/RP/CRUSHER.HPP @@ -0,0 +1,98 @@ +//===========================================================================// +// File: crusher.hh // +// Project: Red Planet // +// Contents: Crusher Implementation for Martian football // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/09/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(CRUSHER_HPP) +# define CRUSHER_HPP + +# if !defined(RPPLAYER_HPP) +# include +# endif + + //########################################################################## + //########################### Crusher ################################ + //########################################################################## +class Crusher: + public RPPlayer + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + public: + void + DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + void + ScoreZoneReplyMessageHandler(ScoreZone__ReplyMessage *message); + void + ScoreMessageHandler(RPPlayer::ScoreMessage *message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + typedef void + (Crusher::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + PlayerSimulation(Scalar time_slice); + + RPPlayer + *teamRunner, + *enemyRunner; + + void + InitTeamRunner(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + static Crusher* + Make(MakeMessage *creation_message); + + Crusher( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~Crusher(); + + Logical + TestInstance() const; + + void + AddOffensivePlayer(OffensivePlayer &offensive_player); + + void + PointVTVTowardGoal(); + }; + +#endif diff --git a/CODE/RP/RP/DEMOPACK.HPP b/CODE/RP/RP/DEMOPACK.HPP new file mode 100644 index 0000000..0395ed4 --- /dev/null +++ b/CODE/RP/RP/DEMOPACK.HPP @@ -0,0 +1,142 @@ +//===========================================================================// +// File: demopack.hpp // +// Project: Red Planet // +// Contents: Interface specification for vectored thrust vehicles // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(DEMOPACK_HPP) +# define DEMOPACK_HPP + +# if !defined(RIVET_HPP) +# include +# endif + + struct DemolitionPack__ModelResource : + public Rivet::ModelResource + { + Scalar + blastRadiusSquared; + Scalar + detectionRadiusSquared; + Scalar + fuseTime; + Scalar + concussiveForce; + }; + + //########################################################################## + //#################### DemolitionPack ############################# + //########################################################################## + + class DemolitionPack : + public Rivet + { + public: + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + #if 0 + public: + enum { + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model support + // + public: + enum { + DefaultFlags = Mover::DefaultFlags|NoCollisionTestFlag + }; + + typedef void (DemolitionPack::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + MoveAndHunt(Scalar time_slice); + void + Hunt(Scalar time_slice); + void + ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef DemolitionPack__ModelResource ModelResource; + + static DemolitionPack* + Make(MakeMessage *creation_message); + + DemolitionPack( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~DemolitionPack(); + + Logical + TestInstance() const; + + static int + CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local Data + // + public: + Scalar + blastRadiusSquared; + + Scalar + detectionRadiusSquared; + + Scalar + fuseTime; + + Scalar + concussiveForce; + }; + + + +#endif + diff --git a/CODE/RP/RP/DEMOPACK.bak b/CODE/RP/RP/DEMOPACK.bak new file mode 100644 index 0000000..651dca8 --- /dev/null +++ b/CODE/RP/RP/DEMOPACK.bak @@ -0,0 +1,144 @@ +//===========================================================================// +// File: demopack.hpp // +// Project: Red Planet // +// Contents: Interface specification for vectored thrust vehicles // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/11/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(DEMOPACK_HPP) +# define DEMOPACK_HPP + +# if !defined(RIVET_HPP) +# include +# endif + + struct DemolitionPack__ModelResource : + public Rivet::ModelResource + { + Scalar + blastRadiusSquared; + Scalar + detectionRadiusSquared; + Scalar + fuseTime; + Scalar + concussiveForce; + }; + + //########################################################################## + //#################### DemolitionPack ############################# + //########################################################################## + + class DemolitionPack : + public Rivet + { + public: + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + #if 0 + public: + enum { + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model support + // + public: + enum { + DefaultFlags = Mover::DefaultFlags|NoCollisionTestFlag + }; + + typedef void (DemolitionPack::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + MoveAndHunt(Scalar time_slice); + void + SelfDestruct(Scalar time_slice); + void + Hunt(Scalar time_slice); + void + ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef DemolitionPack__ModelResource ModelResource; + + static DemolitionPack* + Make(MakeMessage *creation_message); + + DemolitionPack( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~DemolitionPack(); + + Logical + TestInstance() const; + + static int + CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local Data + // + public: + Scalar + blastRadiusSquared; + + Scalar + detectionRadiusSquared; + + Scalar + fuseTime; + + Scalar + concussiveForce; + }; + + + +#endif + diff --git a/CODE/RP/RP/RP.HPP b/CODE/RP/RP/RP.HPP new file mode 100644 index 0000000..3f1fccd --- /dev/null +++ b/CODE/RP/RP/RP.HPP @@ -0,0 +1,22 @@ +#if !defined(RP_HPP) +# define RP_HPP + +# if !defined(MUNGA_HPP) +# include +# endif + +# if !defined(NO_PRECOMPILED_HEADERS) +# if !defined(VTVSUB_HPP) +# include +# endif + +# if !defined(VTV_HPP) +# include +# endif + +# if !defined(VTVMPPR_HPP) +# include +# endif +# endif + +#endif diff --git a/CODE/RP/RP/RPCNSL.CPP b/CODE/RP/RP/RPCNSL.CPP new file mode 100644 index 0000000..40f2464 --- /dev/null +++ b/CODE/RP/RP/RPCNSL.CPP @@ -0,0 +1,99 @@ +//===========================================================================// +// File: cnslmsgs.cpp // +// Project: MUNGA Brick: // +// Contents: Console messages // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 06/02/95 ECH Initial coding. // +// 06/03/95 GAH Added corresponding Macintosh message defintions. // +// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RPCNSL_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoredMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVScoredMessage:: + ConsolePlayerVTVScoredMessage(HostID player_host_ID): + NetworkClient::Message( + ConsolePlayerVTVScoredMessageID, + sizeof(ConsolePlayerVTVScoredMessage) + ) +{ + playerHostID = player_host_ID; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVKilledMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVKilledMessage:: + ConsolePlayerVTVKilledMessage( + HostID player_host_ID, + HostID killer_host_ID + ): + NetworkClient::Message( + ConsolePlayerVTVKilledMessageID, + sizeof(ConsolePlayerVTVKilledMessage) + ) +{ + playerHostID = player_host_ID; + killerHostID = killer_host_ID; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVBoosterMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVBoosterMessage:: + ConsolePlayerVTVBoosterMessage( + HostID player_host_ID, + int booster_on + ): + NetworkClient::Message( + ConsolePlayerVTVBoosterMessageID, + sizeof(ConsolePlayerVTVBoosterMessage) + ) +{ + playerHostID = player_host_ID; + boosterOn = booster_on; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoreUpdateMessage ~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVScoreUpdateMessage:: + ConsolePlayerVTVScoreUpdateMessage( + HostID player_host_ID, + int score + ): + NetworkClient::Message( + ConsolePlayerVTVScoreUpdateMessageID, + sizeof(ConsolePlayerVTVScoreUpdateMessage) + ) +{ + playerHostID = player_host_ID; + playerScore = score; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVDamagedMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVDamagedMessage:: + ConsolePlayerVTVDamagedMessage( + HostID player_host_ID, + HostID damager_host_ID, + int loss, + int points_transfered + ): + NetworkClient::Message( + ConsolePlayerVTVDamagedMessageID, + sizeof(ConsolePlayerVTVDamagedMessage) + ) +{ + playerHostID = player_host_ID; + damagerHostID = damager_host_ID; + damageLoss = loss; + pointsTransfered = points_transfered; +} + +//============================================================================== diff --git a/CODE/RP/RP/RPDIRECT.HPP b/CODE/RP/RP/RPDIRECT.HPP new file mode 100644 index 0000000..095a4ba --- /dev/null +++ b/CODE/RP/RP/RPDIRECT.HPP @@ -0,0 +1,80 @@ +//===========================================================================// +// File: rpdirect.hh // +// Project: Red Planet // +// Contents: Chooses from a Selection of Camerea's and provides information // +// to any number of cameraship's as to which player to follow // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 12/12/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined (RPDIRECT_HPP) +#define RPDIRECT_HPP + +# if !defined (DIRECTOR_HPP) +# include +# endif + + class RPPlayer; + + class RPCameraDirector : + public CameraDirector + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Simulation Support + // + public: + typedef void + (RPCameraDirector::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + CreateRPCameraShip(Scalar); + + void + BeARPDirector(Scalar); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction Support + // + RPCameraDirector( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + + static RPCameraDirector* + RPCameraDirector::Make(CameraDirector::MakeMessage *creation_message); + + ~RPCameraDirector(); + + Logical + TestInstance() const; + + protected: + RPPlayer + *currentWatchedPlayer; + + Logical + martianFootball; + }; + +#endif diff --git a/CODE/RP/RP/RPMSSN.CPP b/CODE/RP/RP/RPMSSN.CPP new file mode 100644 index 0000000..6bb1539 --- /dev/null +++ b/CODE/RP/RP/RPMSSN.CPP @@ -0,0 +1,49 @@ +//===========================================================================// +// File: rpmssn.cc // +// Project: Red Planet // +// Contents: Implementation Details for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 06/19/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RPMSSN_HPP) +# include +#endif + +//########################################################################## +//########################### Mission ################################ +//########################################################################## + +RPMission::RPMission( + NotationFile *notation_file, + ResourceFile *resource_file +): + Mission(notation_file, resource_file) +{ + Check(notation_file); + Check(resource_file); + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPMission::~RPMission() +{ + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPMission::SetPlayerData(NotationFile*) +{ + Fail("RPMission::SetPlayerData shouldn't be reached\n"); +} + diff --git a/CODE/RP/RP/RPMSSN.HPP b/CODE/RP/RP/RPMSSN.HPP new file mode 100644 index 0000000..264449a --- /dev/null +++ b/CODE/RP/RP/RPMSSN.HPP @@ -0,0 +1,51 @@ +//===========================================================================// +// File: rpmission.hh // +// Project: MUNGA Brick: Application // +// Contents: Interface specification for missions // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/19/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPMSSN_HPP) +# define RPMSSN_HPP + +# if !defined(MISSION_HPP) +# include +# endif + + //########################################################################## + //########################### Mission ################################ + //########################################################################## + + + class RPMission : + public Mission + { + + public: + RPMission( + NotationFile *notation_file, + ResourceFile *resources + ); + + ~RPMission(); + + void + SetPlayerData(NotationFile *notation_file); + + Logical + ScoreCompressionOn() + { Check(this); return scoreCompression;} + + protected: + Logical + scoreCompression; + }; + +#endif diff --git a/CODE/RP/RP/RPREG.HPP b/CODE/RP/RP/RPREG.HPP new file mode 100644 index 0000000..9b03743 --- /dev/null +++ b/CODE/RP/RP/RPREG.HPP @@ -0,0 +1,74 @@ +//===========================================================================// +// File: registry.hh // +// Project: MUNGA Brick: Registry Manager // +// Contents: Interface specification for Registry Manager // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 11/22/94 ECH Initial coding. // +// 11/29/94 JMA Changed Identities to IDs // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPREG_HPP) +# define RPREG_HPP + +# if !defined(REGISTRY_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Registry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // + //-------------------------------------------------------------------- + // Registry + // + // Provides construction methods for entities. + // Provides access to a classes static data. + //-------------------------------------------------------------------- + // + + class RPRegistry: + public Registry + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Construction, Destruction, and testing + //-------------------------------------------------------------------- + // + RPRegistry(ResourceFile *resources); + ~RPRegistry(); + + // + //-------------------------------------------------------------- + // GetStaticData + // + // Provides an interface by which the static data for a class + // may be accessed. + //-------------------------------------------------------------- + // + Entity__SharedData* + GetStaticData(ClassID entity_class); + + // + //------------------------- + // Create the player object + //------------------------- + // + Player* + MakePlayer(Mission *mission); + }; + +#endif diff --git a/CODE/RP/RP/RPTOOL.CPP b/CODE/RP/RP/RPTOOL.CPP new file mode 100644 index 0000000..b3a1ee3 --- /dev/null +++ b/CODE/RP/RP/RPTOOL.CPP @@ -0,0 +1,209 @@ +//===========================================================================// +// File: txttores.cpp // +// Project: Resource Tools // +// Author: Jerry Edsall // +// Purpose: Program to convert Notation files to MUNGA .res files. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RPTOOL_HPP) +# include +#endif + +#if !defined(FILEUTIL_HPP) +# include +#endif + +#if !defined(VTV_HPP) +# include +#endif + +#if !defined(SCORZONE_HPP) +# include +#endif + +#if !defined(RIVET_HPP) +# include +#endif + +#if !defined(DEMOPACK_HPP) +# include +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RPTool::CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(class_name,"VTVClassID")) + { + VTV::CreateMakeMessage( + (VTV::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name,"ScoreZoneClassID")) + { + ScoreZone::CreateMakeMessage( + (ScoreZone::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + + return + ApplicationTool::CreateMakeMessage( + class_name, + creation_message, + model_file, + directories + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPTool::CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(model_class, "VTVClassID")) + { +#if 0 + strcpy(ops_file_data, ops_name); + strcat(ops_file_data, "::Standard::Vehicle::"); + strcat(ops_file_data, model_name ); + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::Standard::VehicleList"); + + ops_file->AppendEntry(ops_file_page, "vehicle", ops_file_data); + ops_file->SetEntry(ops_file_data, "tag", model_name ); + ops_file->SetEntry(ops_file_data, "classID", "RPVh"); + ops_file->AppendEntry(ops_file_data, NULL, (char *)NULL); +#endif + + model_resources.gameResourceID = + VTV::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + model_resources.subsystemResourceID = + VTV::CreateSubsystemStream( + resource_file, + model_name, + model_file, + directories + ); + model_resources.skeletonResourceID = + VTV::CreateSkeletonStream( + resource_file, + model_name, + model_file, + directories + ); + model_resources.damageZoneResourceID = + VTV::CreateDamageZoneStream( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "RivetClassID")) + { + model_resources.gameResourceID = + Rivet::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "DemolitionPackClassID")) + { + model_resources.gameResourceID = + DemolitionPack::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "ScoreZoneClassID")) + { + model_resources.gameResourceID = + ScoreZone::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else + { + ApplicationTool::CreateModelResource( + model_resources, + model_class, + resource_file, + model_name, + model_file, + directories + ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + RPTool::CreateControlMappingStream( + const char *model_class, + const char *mapping_name, + NotationFile *mapping_file, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + ) +{ + if (!stricmp(model_class, "VTVClassID")) + { + return + VTV::CreateControlMappingStream( + mapping_name, + mapping_file, + platformTool->GetControlMappingFunction(), + resource_file, + model_name, + model_file, + directories, + current_tool + ); + } + else + { + return -1; + } +} + diff --git a/CODE/RP/RP/RPTOOL.HPP b/CODE/RP/RP/RPTOOL.HPP new file mode 100644 index 0000000..fd19196 --- /dev/null +++ b/CODE/RP/RP/RPTOOL.HPP @@ -0,0 +1,64 @@ +//===========================================================================// +// File: txttores.hpp // +// Project: Art Tools // +// Author: Jerry Edsall // +// Purpose: Program to convert Notation files to MUNGA .res files. // +//---------------------------------------------------------------------------// +// Copyright (c) 1995 Virtual World Entertainment, Inc. // +// All rights reserved worldwide. // +// This unpublished source code is PROPRIETARY and CONFIDENTIAL. // +//===========================================================================// + +#if !defined(RPTOOL_HPP) +# define RPTOOL_HPP + +# if !defined(TOOL_HPP) +# include +# endif + + //########################################################################## + //############################ RPTool ################################ + //########################################################################## + + class RPTool: + public ApplicationTool + { + protected: + Logical + CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + void + CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateControlMappingStream( + const char *model_class, + const char *mapping_name, + NotationFile *mapping_file, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + ); + + public: + RPTool(PlatformTool *platform): + ApplicationTool(platform) + {} + }; + +#endif + diff --git a/CODE/RP/RP/RUNNER.HPP b/CODE/RP/RP/RUNNER.HPP new file mode 100644 index 0000000..cf63122 --- /dev/null +++ b/CODE/RP/RP/RUNNER.HPP @@ -0,0 +1,94 @@ +//===========================================================================// +// File: runner.hh // +// Project: Red Planet // +// Contents: Runner Implementation for Martian football // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 05/09/95 JM Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +#if !defined(RUNNER_HPP) +# define RUNNER_HPP + +# if !defined(RPPLAYER_HPP) +# include +# endif + + //########################################################################## + //########################### Runner ################################ + //########################################################################## +class Runner: + public RPPlayer + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + public: + void + ScoreZoneReplyMessageHandler(ScoreZone__ReplyMessage *message); + void + ScoreMessageHandler(ScoreMessage *message); + void + VehicleDeadMessageHandler(VehicleDeadMessage *message); + void + DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + + typedef void + (Runner::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + Time + dropZonePenaltyOver; + Scalar + scoreMultiplier; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + Runner( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~Runner() {} + + Logical + TestInstance() const; + + static Runner* + Make(MakeMessage *creation_message); + + void + AddOffensivePlayer(OffensivePlayer &offensive_player); + + }; + +#endif diff --git a/CODE/RP/RP/THRUSTER.HPP b/CODE/RP/RP/THRUSTER.HPP new file mode 100644 index 0000000..394e573 --- /dev/null +++ b/CODE/RP/RP/THRUSTER.HPP @@ -0,0 +1,161 @@ +//===========================================================================// +// File: vtvpwr.hh // +// Project: Red Planet // +// Contents: Interface specification for vectored thrust vehicles // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/23/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(THRUSTER_HPP) +# define THRUSTER_HPP + +# if !defined(VTVSUB_HPP) +# include +# endif + + class Joint; + + //########################################################################## + //################## Thruster::SubsystemResource ##################### + //########################################################################## + + struct Thruster__SubsystemResource: + public Subsystem::SubsystemResource + { + int jointIndex; + Scalar maxThrusterRotationRate; + Logical primeThruster; + }; + + //########################################################################## + //################### Thruster::UpdateRecord #################### + //########################################################################## + + struct Thruster__UpdateRecord : + public VTVSubsystem::UpdateRecord + { + Scalar + thrusterRotation; + }; + + //########################################################################## + //############################ Thruster ############################## + //########################################################################## + + class Thruster: + public Subsystem + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + #if 0 + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + ThrusterOffsetAttributeID = Subsystem::NextAttributeID, + ThrusterPositionAttributeID, + CurrentAccelerationAttributeID, + CurrentHeightAttributeID, + MaxThrusterRotationRateAttributeID, + MomentArmAttributeID, + MomentArmLengthAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Point3D thrusterOffset; + Joint *thrusterPosition; + Scalar + currentAcceleration, + currentHeight, + maxThrusterRotationRate, + powerScale, + momentArmLength; + Vector3D + momentArm; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (Thruster::*Performance)(Scalar time_slice); + typedef Thruster__UpdateRecord UpdateRecord; + + void + PrimeThruster(Scalar time_slice); + void + SlaveThruster(Scalar time_slice); + void + PrimeDeadReckon(Scalar time_slice); + void + SlaveDeadReckon(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + VTV* + GetEntity() + {Check(this); return Cast_Object(VTV*, Subsystem::GetEntity());} + + protected: + void + WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + Scalar + updatedPosition; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef Thruster__SubsystemResource SubsystemResource; + Thruster( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Thruster(); + + Logical + TestInstance() const; + }; + +#endif diff --git a/CODE/RP/RP/VTVPWR.CPP b/CODE/RP/RP/VTVPWR.CPP new file mode 100644 index 0000000..71a6822 --- /dev/null +++ b/CODE/RP/RP/VTVPWR.CPP @@ -0,0 +1,154 @@ +//===========================================================================// +// File: vtvpwr.cc // +// Project: Red Planet // +// Contents: Implementation details of vectored thrust vehicles // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/23/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(VTVPWR_HPP) +# include +#endif + +#if !defined(THRUSTER_HPP) +# include +#endif + +#if !defined(VTV_HPP) +# include +#endif + +//############################################################################# +// Shared Data Support +// +VTVPower::SharedData + VTVPower::DefaultData( + VTVPower::ClassDerivations, + VTVPower::MessageHandlers, + VTVPower::AttributeIndex, + VTVPower::StateCount + ); + +Derivation + VTVPower::ClassDerivations( + Subsystem::ClassDerivations, + "VTVPower" + ); + +//############################################################################# +// Attribute Support +// +const VTVPower::IndexEntry + VTVPower::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(VTVPower, MaxAccelerationOutput, maxAccelerationOutput) +}; + +VTVPower::AttributeIndexSet + VTVPower::AttributeIndex( + ELEMENTS(VTVPower::AttributePointers), + VTVPower::AttributePointers, + Subsystem::AttributeIndex + ); + +//############################################################################# +// Model Support +// +void + VTVPower::PowerSimulation(Scalar) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + Scalar average_moment_arm = 0.0f; + + // + //--------------------------------------- + // Find out the average moment arm length + //--------------------------------------- + // + JointSubsystem *joint_subsystem = vtv->GetJointSubsystem(); + Check(joint_subsystem); + Verify(joint_subsystem->GetJointCount()); + + int i; + for (i=0; iGetSubsystem(VTV::Thruster1Subsystem + i); + + if(thruster != NULL) + { + average_moment_arm += thruster->momentArmLength; + } + } + average_moment_arm /= joint_subsystem->GetJointCount(); + Scalar average_accel = maxAccelerationOutput / joint_subsystem->GetJointCount(); + Check_Fpu(); + + for (i=0; iGetSubsystem(VTV::Thruster1Subsystem + i); + + if(thruster != NULL) + { + Check(thruster); + Verify(!Small_Enough(thruster->momentArmLength)); + thruster->powerScale = average_moment_arm / thruster->momentArmLength; + thruster->currentAcceleration = average_accel * thruster->powerScale; + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVPower::VTVPower( + VTV *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + Subsystem(entity, subsystem_ID, subsystem_resource, DefaultData) +{ + if (entity->GetInstance() != VTV::ReplicantInstance) + { + SetPerformance(&VTVPower::PowerSimulation); + } + + maxAccelerationOutput = subsystem_resource->maxAcceleration; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVPower::~VTVPower() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTVPower::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + diff --git a/CODE/RP/RP/VTVPWR.HPP b/CODE/RP/RP/VTVPWR.HPP new file mode 100644 index 0000000..1ab987f --- /dev/null +++ b/CODE/RP/RP/VTVPWR.HPP @@ -0,0 +1,118 @@ +//===========================================================================// +// File: vtvpwr.hh // +// Project: Red Planet // +// Contents: Interface specification for vectored thrust vehicles // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/23/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(VTVPWR_HPP) +# define VTVPWR_HPP + +# if !defined(VTVSUB_HPP) +# include +# endif + + //########################################################################## + //#################### Subsystem::SubsystemResource ################## + //########################################################################## + + struct VTVPower__SubsystemResource: + public Subsystem::SubsystemResource + { + Scalar + maxAcceleration; + }; + + //########################################################################## + //############################ VTVPower ############################## + //########################################################################## + + class VTVPower: + public Subsystem + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + #if 0 + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute Support + // + public: + enum { + MaxAccelerationOutputAttributeID = Subsystem::NextAttributeID, + NextAttributeID + }; + + private: + static const IndexEntry AttributePointers[]; + + protected: + static AttributeIndexSet AttributeIndex; + + // + // public attribute declarations go here + // + public: + Scalar + maxAccelerationOutput; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (VTVPower::*Performance)(Scalar time_slice); + + void + PowerSimulation(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + VTV* + GetEntity() + {Check(this); return Cast_Object(VTV*, Subsystem::GetEntity());} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Construction and Destruction + // + public: + typedef VTVPower__SubsystemResource SubsystemResource; + + VTVPower( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem + ); + ~VTVPower(); + + Logical + TestInstance() const; + }; + +#endif diff --git a/CODE/RP/RP/VTVSUB.CPP b/CODE/RP/RP/VTVSUB.CPP new file mode 100644 index 0000000..686f754 --- /dev/null +++ b/CODE/RP/RP/VTVSUB.CPP @@ -0,0 +1,174 @@ +//===========================================================================// +// File: subsystm.cc // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification of entity subsystem class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/24/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(VTVSUB_HPP) +# include +#endif + +#if !defined(VTV_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +#if !defined(VTVMPPR_HPP) +# include +#endif + +VTVSubsystem::SharedData + VTVSubsystem::DefaultData( + VTVSubsystem::ClassDerivations, + VTVSubsystem::MessageHandlers, + VTVSubsystem::AttributeIndex, + VTVSubsystem::StateCount + ); +Derivation + VTVSubsystem::ClassDerivations(Subsystem::ClassDerivations,"VTVSubsystem"); + +//############################################################################# +// Messaging Support +// +//const Receiver::HandlerEntry +// VTVSubsystem::MessageHandlerEntries[]= +//{ +//}; +// +//Receiver::MessageHandlerSet +// VTVSubsystem::MessageHandlers( +// ELEMENTS(VTVSubsystem::MessageHandlerEntries), +// VTVSubsystem::MessageHandlerEntries, +// Subsystem::MessageHandlers +// ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVSubsystem::VTVSubsystem( + VTV *entity, + int subsystem_ID, + SubsystemResource *model, + SharedData &shared_data, + // these two fields added 12-28-95 by cpb + void *control_destination, + Receiver::MessageID message_id +): + Subsystem(entity, subsystem_ID, model, shared_data) +{ + controlDestination = control_destination; + controlMessageID = message_id; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVSubsystem::~VTVSubsystem() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTVSubsystem::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +void + VTVSubsystem::EnterConfiguration( + ControlsButton *direct_target, + Receiver *receiver, + Receiver::MessageID active_message_id, + Receiver::MessageID config_message_id + ) +{ + Check(this); + + Check(application); + ControlsManager + *controls_mgr = application->GetControlsManager(); + Check(controls_mgr); + + //------------------------------------------- + // Tell controls mgr that we're configuring + //------------------------------------------- + controls_mgr->StartMappableButtonsConfigure( + direct_target, // direct mapping (if used) + receiver, // targeted receiver + receiver, // dependant + active_message_id, // activation message ID (if used) + (ModeMask) 0, // remove_mode_mask + (ModeMask) 0 // add_mode_mask + ); + + //----------------------------------------------------------- + // Create temporary mappings for configuration + //----------------------------------------------------------- + Check(GetEntity()); + + VTVControlsMapper + *mapper = (VTVControlsMapper*) GetEntity()->GetSubsystem( + VTV::ControlsMapperSubsystem + ); + + if (mapper != NULL) + { + Check(mapper); + + mapper->CreateTemporaryEventMappings( + receiver, + config_message_id + ); + } + Check_Fpu(); +} + +void + VTVSubsystem::ExitConfiguration() +{ + Check(application); + ControlsManager + *controls_mgr = application->GetControlsManager(); + Check(controls_mgr); + + //------------------------------------------------ + // Tell controls mgr we're through + //------------------------------------------------ + controls_mgr->StopMappableButtonsConfigure( + (ModeMask) 0, // remove_mode_mask + (ModeMask) 0 // add_mode_mask + ); + //----------------------------------------------------------- + // Remove temporary mappings for configuration + //----------------------------------------------------------- + Check(GetEntity()); + + VTVControlsMapper + *mapper = (VTVControlsMapper*) GetEntity()->GetSubsystem( + VTV::ControlsMapperSubsystem + ); + + if (mapper != NULL) + { + Check(mapper); + + mapper->RemoveTemporaryEventMappings(); + } + Check_Fpu(); +} + diff --git a/CODE/RP/RP/VTVSUB.HPP b/CODE/RP/RP/VTVSUB.HPP new file mode 100644 index 0000000..85e7e64 --- /dev/null +++ b/CODE/RP/RP/VTVSUB.HPP @@ -0,0 +1,102 @@ +//===========================================================================// +// File: subsystm.hh // +// Project: MUNGA Brick: Entity Manager // +// Contents: Interface specification of entity subsystem class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/24/95 JMA Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#if !defined(VTVSUB_HPP) +# define VTVSUB_HPP + +# if !defined(SUBSYSTM_HPP) +# include +# endif + +# if !defined(CONTROLS_HPP) +# include +# endif + + class VTV; + + //########################################################################## + //######################## Subsystem ################################# + //########################################################################## + + class VTVSubsystem: + public Subsystem + { + friend class VTV; + + //########################################################################## + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + //########################################################################## + // Messaging support + // + + // No messages handled here + + //########################################################################## + // Construction and Destruction Support + // + public: + ~VTVSubsystem(); + + Logical + TestInstance() const; + + protected: + VTVSubsystem( + VTV *entity, + int subsystem_id, + SubsystemResource *model, + SharedData &shared_data, + // these two fields added 12-28-95 by cpb + void *control_destination = NULL, + Receiver::MessageID message_id = (Receiver::MessageID) 0 + ); + + //########################################################################## + // Model support + // + public: + VTV* + GetEntity() + {return (VTV*)Subsystem::GetEntity();} + + //########################################################################## + // Mapping support + // + protected: + void + EnterConfiguration( + ControlsButton *direct_target, + Receiver *receiver, + Receiver::MessageID active_message_id, + Receiver::MessageID config_message_id + ), + ExitConfiguration(); + + // 'controlDestination' is a pointer to the "thing" that a button + // is mapped to (if 'direct-mapped'), and 'controlMessageID' indicates + // the message ID that the button is mapped to (if 'event-mapped'). + // These values must be set appropriately in order for gauges to be + // able to determine ownership of mapped buttons. + void + *controlDestination; // OBSOLETE? + + Receiver::MessageID // OBSOLETE? + controlMessageID; + }; + +#endif diff --git a/CODE/RP/RP/mssccprj.scc b/CODE/RP/RP/mssccprj.scc new file mode 100644 index 0000000..e25ffe7 --- /dev/null +++ b/CODE/RP/RP/mssccprj.scc @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[rp.mak] +SCC_Aux_Path = "M:\VWESS" +SCC_Project_Name = "$/Tesla_rp/RP", CKWAAAAA diff --git a/CODE/RP/RP/opt/opt.cfg b/CODE/RP/RP/opt/opt.cfg new file mode 100644 index 0000000..a06163c --- /dev/null +++ b/CODE/RP/RP/opt/opt.cfg @@ -0,0 +1,34 @@ +-DLBE4;DEBUG_LEVEL=0;DEBUG_STREAM=cout;MESSAGE_BUFFERING=False +-b +-r +-ff +-AT +-k- +-N- +-v- +-5 +-a4 +-V +-Jg +-x- +-RT- +-O2 +-Ot +-Oc +-Og +-O +-Ol +-Z +-Ob +-Oe +-Oi +-Om +-Op +-Ov +-w +-c +-Id:\tesla_rp\rp_l4;d:\tesla_rp\rp;d:\tesla_rp\munga_l4;d:\tesla_rp\munga_l4\libdpl;d:\tesla_rp\munga_l4\libdpl\dvs;d:\tesla_rp\munga_l4\libdpl\dpl;d:\tesla_rp\munga_l4\sos\bc4;d:\tesla_rp\munga_l4\netnub;d:\tesla_rp\munga;d:\bc5\include +-H +-H=rpopt.csm +-Hc +-nd:\tesla_rp\rp\opt diff --git a/CODE/RP/RP/rp.mak b/CODE/RP/RP/rp.mak new file mode 100644 index 0000000..d83f152 --- /dev/null +++ b/CODE/RP/RP/rp.mak @@ -0,0 +1,96 @@ +.autodepend +.cacheautodepend +.suffixes: .cpp + +!ifndef BTYPE +!error BTYPE macro not supplied +!endif + +!ifndef BPATH +!error BPATH macro not supplied +!endif + +!include make.cfg +!include $(BPATH) + +!ifndef RP_ROOT +!error RP_ROOT macro is not defined +!endif + +TARGET_DIR = $(RP_ROOT)\$(BTYPE) +TARGET_PATH = $(TARGET_DIR)\\ +.path.obj = $(TARGET_DIR) +.path.lib = $(LIBRARY_PATH) + +LIB_PREFIX = -+$(TARGET_DIR)\\ + +CFG_FILE = $(TARGET_DIR)\$(BTYPE).cfg +HEADER_FILE = rp$(BTYPE).csm + +#------------------------------------------------------------------------------ +# Library targets +# +all: $(CFG_FILE) $(TARGET_DIR)\rp.lib + +clean: + del $(TARGET_DIR)\*.obj + del $(TARGET_DIR)\*.lib + del $(TARGET_DIR)\*.bak + del $(TARGET_DIR)\*.cfg + +assemble: + @echo No assembly targets + +#------------------------------------------------------------------------------ +# Implicit rules +# +!include $(BTYPE).mak + +!ifndef STARTUP_OBJ +!error STARTUP_OBJ macro is not defined +!endif + +!ifndef STARTUP_LIBS +!error STARTUP_LIBS macro is not defined +!endif + +{$(INCLUDE_PATH)}.cpp{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(INCLUDE_PATH)}.c{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(RP_ROOT)}.asm{$(TARGET_DIR)}.obj: + tasm32 -ml $(TASM_OPTIONS) -i$(RP_ROOT) $<,$@ >>error.log + +#------------------------------------------------------------------------------ +# Red Planet library +# +RP_OBJS = \ + ?vtvsub.obj \ + ?vtv.obj \ + ?vtvmppr.obj \ + ?vtvpwr.obj \ + ?thruster.obj \ + ?booster.obj \ + ?chute.obj \ + ?weapsys.obj \ + ?rivet.obj \ + ?demopack.obj \ + ?rpplayer.obj \ + ?rpdirect.obj \ + ?crusher.obj \ + ?runner.obj \ + ?blocker.obj \ + ?scorzone.obj \ + ?rpreg.obj \ + ?rpmssn.obj \ + ?rpcnsl.obj \ + ?rptool.obj + +$(RP_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\rp.lib: $(RP_OBJS:?=) $(RP_ROOT)\rp.mak + tlib $@ $(LIB_OPTIONS) @&&| +$(RP_OBJS:?=$(LIB_PREFIX)) +| >>error.log diff --git a/CODE/RP/RP/vssver.scc b/CODE/RP/RP/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..bda2ba77c23645fd98f7f8ea9f17493ec46abb5a GIT binary patch literal 704 zcmW;IYe*AN7zSWhKNh+o=1OF>>1^hz%~?xxmvq_Y!gM9;#wJU!ASvhPJBOT0GOPl&5w^i@H^XKqdGL5Duq^}ce) zow1q;VZ8qIGn=u8r^ukg$9+y^48L~y5{od&gZ)*f_LqDaO)%hm*rV)gw{wzY0X*7v zIk_U(LoR@0A4OM%Z$0ESu-CSm8U6N@EQIHz&qr2^wd6urXu1`-;MI}W!ZQiEBE_`O z{vtS$6&C;KUq-nI*6QmFkyWMSb#N-1d%lG?wvg_(9v*58v91q%Aa8(u@#g8JrY^D= zo-mA9G`=Tf3C!pS2CRqnl8a$eFnpsn`v_SIy8|5l%f6H35;%~I%L>?b@ZakOU7 zVGel{?3c5?wiZbi(*Gxe1yii*hgXJDX>W$-uIa7aE5}pmzNK)Z=V$Qun`v?x9Gah< zYMH%A-U1(VMV$`}ZgM$ni*?=RFVUqICXXLYKpAvQ!pY0UC zQc|vh>)S=D*3@`1y?-m*kk?^Xe~yqV;ONd5{Y|}p$d&N@!pThI-qP7> zc^m9rF3 +# endif + +# if !defined(MUNGAL4_HPP) +# include +# endif + +#endif diff --git a/CODE/RP/RP_L4/RPL4APP.HPP b/CODE/RP/RP_L4/RPL4APP.HPP new file mode 100644 index 0000000..8d9ef10 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4APP.HPP @@ -0,0 +1,64 @@ +//===========================================================================// +// File: rp4lbe4.hh // +// Project: MUNGA Brick: Red Planet LBE Application // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPL4APP_HPP) +# define RPL4APP_HPP + +# if !defined(L4APP_HPP) +# include +# endif + + //########################################################################## + //###################### RP4L4Application ############################ + //########################################################################## + + class RPL4Application: + public L4Application + { + public: + RPL4Application( + ResourceFile *resource_file, + ClassID class_ID=L4ApplicationClassID, + SharedData &shared_data=DefaultData + ); + ~RPL4Application(); + + private: + Registry* + MakeRegistry(); + + VideoRenderer* + MakeVideoRenderer(); + + AudioRenderer* + MakeAudioRenderer(); + + GaugeRenderer* + MakeGaugeRenderer(); + + ModeManager* + MakeModeManager(); + + Mission* + MakeMission( + NotationFile *notation_file, + ResourceFile *resources + ); + + Entity* + MakeViewpointEntity(Entity__MakeMessage *); + }; + +#endif + diff --git a/CODE/RP/RP_L4/RPL4ARND.CPP b/CODE/RP/RP_L4/RPL4ARND.CPP new file mode 100644 index 0000000..5daf716 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4ARND.CPP @@ -0,0 +1,46 @@ +//===========================================================================// +// File: rpl4arnd.cc // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RPL4ARND_HPP) +# include +#endif + +// +//############################################################################# +// RPL4AudioRenderer +//############################################################################# +// +RPL4AudioRenderer::RPL4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode +): + L4AudioRenderer( + render_rate, + mission_review_mode + ) +{ +} + +// +//############################################################################# +// ~RPL4AudioRenderer +//############################################################################# +// +RPL4AudioRenderer::~RPL4AudioRenderer() +{ +} + diff --git a/CODE/RP/RP_L4/RPL4ARND.HPP b/CODE/RP/RP_L4/RPL4ARND.HPP new file mode 100644 index 0000000..41c9534 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4ARND.HPP @@ -0,0 +1,41 @@ +//===========================================================================// +// File: rpl4arnd.hh // +// Project: MUNGA Brick: Audio Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/30/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPL4ARND_HPP) +# define RPL4ARND_HPP + +# if !defined(L4AUDRND_HPP) +# include +# endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~ RPL4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class RPL4AudioRenderer: + public L4AudioRenderer + { + public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + RPL4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode + ); + ~RPL4AudioRenderer(); + }; + +#endif + diff --git a/CODE/RP/RP_L4/RPL4GRND.HPP b/CODE/RP/RP_L4/RPL4GRND.HPP new file mode 100644 index 0000000..dd54cd1 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4GRND.HPP @@ -0,0 +1,62 @@ +//===========================================================================// +// File: rpl4grnd.hh // +// Project: MUNGA Brick: Gauge Renderer Manager // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/13/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPL4GRND_HPP) +# define RPL4GRND_HPP + +# if !defined(L4GREND_HPP) +# include +# endif + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ RPL4GaugeRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class RPL4GaugeRenderer: + public L4GaugeRenderer + { + public: + + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + RPL4GaugeRenderer(); + ~RPL4GaugeRenderer(); + + Logical + TestInstance() const; + + void + NotifyOfNewInterestingEntity(Entity *entity); + void + NotifyOfBecomingUninterestingEntity(Entity *entity); + // + //-------------------------------------------------------------------- + // LoadMissionImplementation + // ShutdownImplementation + // SuspendImplementation + // ResumeImplementation + // + // These are virtual functions defined by the Renderer class. + // Derived classes must call these methods. + //-------------------------------------------------------------------- + // + void + LoadMissionImplementation(Mission *mission); + void + ShutdownImplementation(); + }; + +#endif + diff --git a/CODE/RP/RP_L4/RPL4MODE.CPP b/CODE/RP/RP_L4/RPL4MODE.CPP new file mode 100644 index 0000000..2c257cc --- /dev/null +++ b/CODE/RP/RP_L4/RPL4MODE.CPP @@ -0,0 +1,84 @@ +//==========================================================================// +// File: RPL4MODE.CPP // +// Project: MUNGA Brick: Controls Manager // +// Contents: Interface specification for BT LBE4 Controls // +//--------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ----------------------------------------------------------// +// 03/08/96 CPB Built from BTL4MODE.CPP // +//--------------------------------------------------------------------------// +// Copyright (C) 1994-1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//==========================================================================// + +#include +#pragma hdrstop + +#if !defined(RPL4MODE_HPP) +# include +#endif + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +struct ModeLookup +{ + const char *name; + ModeMask modeMask; +}; + +static ModeLookup + mode_lookup[] = + { + {"ModeNonConfig", RPL4ModeManager::ModeNonConfig}, + {"ModeConfigReady", RPL4ModeManager::ModeConfigReady}, + {"ModeConfigOn", RPL4ModeManager::ModeConfigOn}, + {"ModePreset1", RPL4ModeManager::ModePreset1}, + {"ModePreset2", RPL4ModeManager::ModePreset2}, + {"ModePreset3", RPL4ModeManager::ModePreset3}, + {"ModePreset4", RPL4ModeManager::ModePreset4}, + {"ModePreset5", RPL4ModeManager::ModePreset5}, + {"ModePreset6", RPL4ModeManager::ModePreset6}, + {"ModeBasic", RPL4ModeManager::ModeBasic}, + {"ModeStandard", RPL4ModeManager::ModeStandard}, + {"ModeIntercom", RPL4ModeManager::ModeIntercom}, + {"ModeConfiguring", RPL4ModeManager::ModeConfiguring}, + { NULL, (ModeMask)0} + }; + +Logical + RPL4ModeManager::ModeStringLookup( + const char *name, + ModeMask *returned_value + ) +{ + Check(this); + Check_Pointer(name); + Check_Pointer(returned_value); + //---------------------------------------- + // Search table for match + //---------------------------------------- + ModeLookup + *lookup; + + for(lookup=mode_lookup; lookup->name!=NULL; ++lookup) + { + if (stricmp(name, lookup->name) == 0) + { + *returned_value = lookup->modeMask; + Check_Fpu(); + return True; + } + } + //---------------------------------------- + // Not found here, check next level down. + //---------------------------------------- + Check_Fpu(); + return ModeManager::ModeStringLookup(name, returned_value); +} + + diff --git a/CODE/RP/RP_L4/RPL4MODE.HPP b/CODE/RP/RP_L4/RPL4MODE.HPP new file mode 100644 index 0000000..1ce9b39 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4MODE.HPP @@ -0,0 +1,98 @@ +//===========================================================================// +// File: rpl4mode.hpp // +// Project: Battletech // +// Contents: RPL4 controls // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/08/96 CPB Created from BRL4MODE.HPP // +//---------------------------------------------------------------------------// +// Copyright (C) 1996, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPL4MODE_HPP) +# define RPL4MODE_HPP + +# if !defined(MODE_HPP) +# include +# endif + + + //######################################################################### + //########################## RPL4ControlsManager ########################## + //######################################################################### + class RPL4ModeManager: + public ModeManager + { + public: + enum + { + }; + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- + public: + RPL4ModeManager(ModeMask initial_mask): + ModeManager(initial_mask) + {} + + //------------------------------------------------------------------- + // Mode control + //------------------------------------------------------------------- + enum + { + ModeNonConfigBit = ModeManager::nextModeBit, + ModeConfigReadyBit, + ModeConfigOnBit, + ModePreset1Bit, + ModePreset2Bit, + ModePreset3Bit, + ModePreset4Bit, + ModePreset5Bit, + ModePreset6Bit, + + ModeBasicBit, + ModeStandardBit, + + ModeIntercomBit + }; + enum + { + ModePreset1 = 1L< +# endif + + //########################################################################## + //########################### RPL4Mission ############################ + //########################################################################## + + class RPL4Mission: + public RPMission + { + public: + RPL4Mission( + NotationFile *notation_file, + ResourceFile *resources + ); + ~RPL4Mission(); + + Logical + TestInstance() const; + + void + SetPlayerData(NotationFile *notation_file); + }; + +#endif diff --git a/CODE/RP/RP_L4/RPL4PB.HPP b/CODE/RP/RP_L4/RPL4PB.HPP new file mode 100644 index 0000000..e2814c8 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4PB.HPP @@ -0,0 +1,116 @@ +//===========================================================================// +// File: rp4lbe4.hh // +// Project: MUNGA Brick: Red Planet LBE Application // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPL4PB_HPP) +# define RPL4PB_HPP + +# if !defined(RPL4APP_HPP) +# include +# endif + +# if !defined(L4SPLR_HPP) +# include +# endif + + //########################################################################## + //####################### RPSpoolerTask ############################## + //########################################################################## + + class RPSpoolerTask: + public SpoolerTask + { + public: + RPSpoolerTask(); + ~RPSpoolerTask(); + + void + DispatchPacket(NetworkPacket *packet); + long + GetTimeBias(); + }; + + //########################################################################## + //#################### RPPlaybackApplication ########################## + //########################################################################## + + class RPL4PlaybackApplication: + public RPL4Application + { + public: + RPL4PlaybackApplication( + ResourceFile *resource, + SpoolFile *spool_file = NULL + ); + ~RPL4PlaybackApplication(); + + Logical + TestInstance() const; + + void + SetSpoolFile(SpoolFile *spool_file) + {spoolFile = spool_file;} + + MissionReviewApplicationManager* + GetApplicationManager() + { + return + (MissionReviewApplicationManager*) + Application::GetApplicationManager(); + } + + long + GetTimeBias() + {return timeBias;} + + void + DispatchPacket(NetworkPacket *packet); + + protected: + NetworkManager* + MakeNetworkManager(); + + long + timeBias; + + void + Initialize(); + void + LoadBackgroundTasks(); + Logical + ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ); + void + ExecuteBackgroundTask(); + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data Support + // + public: + static Derivation ClassDerivations; + static SharedData DefaultData; + + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + }; + +#endif diff --git a/CODE/RP/RP_L4/RPL4TOOL.CPP b/CODE/RP/RP_L4/RPL4TOOL.CPP new file mode 100644 index 0000000..b31a7f9 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4TOOL.CPP @@ -0,0 +1,158 @@ +//===========================================================================// +// File: rp4lbe4.cc // +// Project: MUNGA Brick: Red Planet LBE Application // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(RPTOOL_HPP) +# include +#endif + +#if !defined(RPL4MODE_HPP) +# include +#endif + +#if !defined(L4TOOL_HPP) +# include +#endif + +#if !defined(RPL4VER_HPP) +# include +#endif + + +class RPL4Tool: +public L4Tool +{ +public: + RPL4Tool(); + ~RPL4Tool(); + + Logical + ConvertStringToModeMask( + const char *string, + ModeMask *returned_value_ptr + ); + +protected: + RPL4ModeManager + *modeManager; +}; + +//---------------------------------------------------------------------- +RPL4Tool::RPL4Tool() : + L4Tool() +{ + Check_Pointer(this); + + modeManager = new RPL4ModeManager(RPL4ModeManager::ModeInitial); + Register_Object(modeManager); + +// gaugeAlarmManager = new RPL4GaugeAlarmManager(); +// Register_Object(gaugeAlarmManager); + Check_Fpu(); +} + +//---------------------------------------------------------------------- +RPL4Tool::~RPL4Tool() +{ +// Check(this); +// Unregister_Object(gaugeAlarmManager); +// delete gaugeAlarmManager; +// gaugeAlarmManager = NULL; + + Unregister_Object(modeManager); + delete modeManager; + modeManager = NULL; + Check_Fpu(); +} + +//---------------------------------------------------------------------- +Logical + RPL4Tool::ConvertStringToModeMask( + const char *name, + ModeMask *returned_value + ) +{ +// Check(this); + + Check_Pointer(name); + Check_Pointer(returned_value); + Check(modeManager); + + Check_Fpu(); + return modeManager->ModeStringLookup(name, returned_value); +} + +//########################################################################## +//################## RP4L4Application Globals ######################## +//########################################################################## + +extern const char* const ProgName; +const char* const ProgName = "rpl4tool"; + +// +//############################################################################# +// main +//############################################################################# +// +int + main(int argc, char *argv[]) +{ + int status; + if (argc < 3) + { +Usage: + DEBUG_STREAM << "Building Usage: rpl4tool -b rpl4.bld [res2.bld]\n" + << " Listing Usage: rpl4tool -l rpl4.res [res2.res ...]\n"; + status = 1; + } + else + { + RPL4Tool + rpl4_tool; + RPTool + rp_l4_tool(&rpl4_tool); + L4AudioCreateSymbols + create_symbols; + + if (!strcmp(argv[1], "-b")) + { + status = + rp_l4_tool.BuildResources( + argc-1, + &argv[1], + create_symbols, + MINOR_DATA_VERSION + ); + } + else if (!strcmp(argv[1], "-l")) + { + status = + rp_l4_tool.ListResources( + argc-1, + &argv[1] + ); + } + else + { + DEBUG_STREAM << "Error: Unknown tool switch!\n"; + goto Usage; + } + } + + Stop_Registering(); + return status; +} + diff --git a/CODE/RP/RP_L4/RPL4VER.HPP b/CODE/RP/RP_L4/RPL4VER.HPP new file mode 100644 index 0000000..60ce3ff --- /dev/null +++ b/CODE/RP/RP_L4/RPL4VER.HPP @@ -0,0 +1,11 @@ +#if !defined(RPL4VER_HPP) +# define RPL4VER_HPP + +# define MAJOR_DATA_VERSION 3 +# define RELEASE_VERSION 0 +# define MINOR_DATA_VERSION 2 + +#endif + + + diff --git a/CODE/RP/RP_L4/RPL4VID.HPP b/CODE/RP/RP_L4/RPL4VID.HPP new file mode 100644 index 0000000..dc88fd6 --- /dev/null +++ b/CODE/RP/RP_L4/RPL4VID.HPP @@ -0,0 +1,83 @@ +//===========================================================================// +// File: rpl4vid.hh // +// Project: MUNGA Brick: Video Renderer Manager // +// Contents: Wrapper class for including rp scripts into video renderer // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/12/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#if !defined(RPL4VID_HPP) +# define RPL4VID_HPP + +# if !defined(L4VIDEO_HPP) +# include +# endif + +# include +# include + +//########################################################################## +//########################################################################## + + class RPL4VideoRenderer: + public DPLRenderer + { + public: + RPL4VideoRenderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration + ); + ~RPL4VideoRenderer(); + char + SetupMaterialSubstitutionList( + Entity* entity, + ViewFrom view_type); // The entity we will be substituting for. + void + TearDownMaterialSubstitutionList(); + + protected: + int + vtvsExpected, + vtvCount; + + void + LoadMissionImplementation(Mission *mission); + + void + MakeEntityRenderables( + Entity *this_entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom type); // Type of reference (inside/outside...etc.) + + dpl_DCS* + ReadSKLFile( + Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom type, // type of reference to create + char skeleton_type // TEMPORARY!!!! to handle color substitutions + ); + + void + RecurseSKLFile( + Entity *entity, + dpl_DCS *parentDCS, + NotationFile *mech_skeleton, + const char *page_name, + int recursion_depth, + ViewFrom type, // type of reference to create !!! should be enum + int *joint_counter, + dpl_LOAD_MODE cache_mode + ); + + }; + +#endif diff --git a/CODE/RP/RP_L4/mssccprj.scc b/CODE/RP/RP_L4/mssccprj.scc new file mode 100644 index 0000000..7418774 --- /dev/null +++ b/CODE/RP/RP_L4/mssccprj.scc @@ -0,0 +1,5 @@ +SCC = This is a Source Code Control file + +[rpL4.mak] +SCC_Aux_Path = "M:\VWESS" +SCC_Project_Name = "$/Tesla_rp/RP_L4", QNWAAAAA diff --git a/CODE/RP/RP_L4/opt/opt.cfg b/CODE/RP/RP_L4/opt/opt.cfg new file mode 100644 index 0000000..91784cc --- /dev/null +++ b/CODE/RP/RP_L4/opt/opt.cfg @@ -0,0 +1,34 @@ +-DLBE4;DEBUG_LEVEL=0;DEBUG_STREAM=cout;MESSAGE_BUFFERING=False +-b +-r +-ff +-AT +-k- +-N- +-v- +-5 +-a4 +-V +-Jg +-x- +-RT- +-O2 +-Ot +-Oc +-Og +-O +-Ol +-Z +-Ob +-Oe +-Oi +-Om +-Op +-Ov +-w +-c +-Id:\tesla_rp\rp_l4;d:\tesla_rp\rp;d:\tesla_rp\munga_l4;d:\tesla_rp\munga_l4\libdpl;d:\tesla_rp\munga_l4\libdpl\dvs;d:\tesla_rp\munga_l4\libdpl\dpl;d:\tesla_rp\munga_l4\sos\bc4;d:\tesla_rp\munga_l4\netnub;d:\tesla_rp\munga;d:\bc5\include +-H +-H=rpl4opt.csm +-Hc +-nd:\tesla_rp\rp_l4\opt diff --git a/CODE/RP/RP_L4/rpL4.mak b/CODE/RP/RP_L4/rpL4.mak new file mode 100644 index 0000000..3c93a09 --- /dev/null +++ b/CODE/RP/RP_L4/rpL4.mak @@ -0,0 +1,134 @@ +.autodepend +.cacheautodepend +.suffixes: .cpp + +!ifndef BTYPE +!error BTYPE macro not supplied +!endif + +!ifndef BPATH +!error BPATH macro not supplied +!endif + +!include make.cfg +!include $(BPATH) + +!ifndef RPL4_ROOT +!error RPL4_ROOT macro is not defined +!endif + +TARGET_DIR = $(RPL4_ROOT)\$(BTYPE) +TARGET_PATH = $(TARGET_DIR)\\ +.path.obj = $(TARGET_DIR) +.path.lib = $(LIBRARY_PATH) + +LIB_PREFIX = -+$(TARGET_DIR)\\ + +CFG_FILE = $(TARGET_DIR)\$(BTYPE).cfg +HEADER_FILE = rpl4$(BTYPE).csm + +#------------------------------------------------------------------------------ +# Library targets +# +all: $(CFG_FILE) $(TARGET_DIR)\rpl4$(BTYPE).exe $(TARGET_DIR)\rpl4tool.exe + +clean: + del $(TARGET_DIR)\*.obj + del $(TARGET_DIR)\*.lib + del $(TARGET_DIR)\*.exe + del $(TARGET_DIR)\*.bak + del $(TARGET_DIR)\*.cfg + +assemble: + @echo No assembly targets + +#------------------------------------------------------------------------------ +# Implicit rules +# +!include $(BTYPE).mak + +!ifndef STARTUP_OBJ +!error STARTUP_OBJ macro is not defined +!endif + +!ifndef STARTUP_LIBS +!error STARTUP_LIBS macro is not defined +!endif + +{$(INCLUDE_PATH)}.cpp{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(INCLUDE_PATH)}.c{$(TARGET_DIR)}.obj: + $(BCC) @$(CFG_FILE) $< >>error.log + +{$(RPL4_ROOT)}.asm{$(TARGET_DIR)}.obj: + tasm32 -ml $(TASM_OPTIONS) -i$(RPL4_ROOT) $<,$@ >>error.log + +#------------------------------------------------------------------------------ +# Game +# +$(TARGET_DIR)\rpl4$(BTYPE).exe: \ + $(RPL4_ROOT)\rpl4.mak l4stub.lib stub.lib $(BTYPE).mak munga.lib\ + mungal4.lib rp.lib $(TARGET_DIR)\rpl4.lib $(TARGET_DIR)\rpl4.obj\ + $(DPL_ROOT)\libdpl.lib + tlink32 @&&| +$(LINK_OPTIONS) + +$(STARTUP_OBJ)+ +$(TARGET_DIR)\rpl4.obj +$<,$* +l4stub.lib+ +stub.lib+ +munga.lib+ +mungal4.lib+ +$(DPL_ROOT)\libdpl.lib+ +rp.lib+ +$(TARGET_DIR)\rpl4.lib+ +$(STARTUP_LIBS) +| >>error.log + +rpl4.obj: $(CFG_FILE) + +#------------------------------------------------------------------------------ +# Tools +# +$(TARGET_DIR)\rpl4tool.exe: \ + $(RPL4_ROOT)\rpl4.mak $(TARGET_DIR)\rpl4tool.obj l4stub.lib stub.lib\ + $(BTYPE).mak munga.lib mungal4.lib rp.lib $(TARGET_DIR)\rpl4.lib\ + $(DPL_ROOT)\libdpl.lib + tlink32 @&&| +$(LINK_OPTIONS) + +$(STARTUP_OBJ)+ +$(TARGET_DIR)\rpl4tool.obj +$<,$* +l4stub.lib+ +stub.lib+ +munga.lib+ +mungal4.lib+ +$(DPL_ROOT)\libdpl.lib+ +rp.lib+ +$(TARGET_DIR)\rpl4.lib+ +$(STARTUP_LIBS) +| >>error.log + +rpl4tool.obj: $(CFG_FILE) + +#------------------------------------------------------------------------------ +# Red Planet library +# +RPL4_OBJS = \ + ?rpl4mode.obj \ + ?rpl4gaug.obj \ + ?rpl4grnd.obj \ + ?rpl4vid.obj \ + ?rpl4mppr.obj \ + ?rpl4arnd.obj \ + ?rpl4mssn.obj \ + ?rpl4app.obj \ + ?rpl4pb.obj + +$(RPL4_OBJS:?=): $(CFG_FILE) + +$(TARGET_DIR)\rpl4.lib: $(RPL4_OBJS:?=) $(RPL4_ROOT)\rpl4.mak + tlib $@ $(LIB_OPTIONS) @&&| +$(RPL4_OBJS:?=$(LIB_PREFIX)) +| >>error.log diff --git a/CODE/RP/RP_L4/vssver.scc b/CODE/RP/RP_L4/vssver.scc new file mode 100644 index 0000000000000000000000000000000000000000..265a8c4c78179b8b47584677d49a6f32ce719a47 GIT binary patch literal 400 zcmXpJVq`d2=P%iL-obO(RqsctpMq-6gvKnavSt8-Y9KvNEBt|C|F739 zh2;0lxelSx!quX9gu&l@`U^K72Co5dLX|wu;G|-lq;Cu0OZ&9NrpDY zrhxg4Kt9u#YxV908DM@BkUy>Bj`!7KelWio$p14rgC}y9I+))ApHQi&rX! zo!76`}3nd|-Y*kpKEixTd?SB$z(|$anPT&QIhv2J|84Y1jcjuR z%ijR<9rx%}-(436=HCSJHI%%yA0J8r^KSw9J#R1XO@CVj=HCYL?}ss%^(Qlf`FDW) z=}%T~aGuWr=HCVKvlY*1Gj5gv^X~!qpC>Fg5$=)(^X~)sFZ1)h*lQoT4+@V5Kz`9~ Lotmk&-C#Zdu{Cn# literal 0 HcmV?d00001 diff --git a/CONTENT/BT/32STUB.EXE b/CONTENT/BT/32STUB.EXE new file mode 100644 index 0000000000000000000000000000000000000000..874767286c9c2b5ad2b1d0cb7be9a634981f4cf8 GIT binary patch literal 2160 zcmeZ`Dqvt`U|>)H;{X5M85o!t7-E3f4#;O@_#Kc{1Y`hNqhNT3fU!|06p87@AobnOGT{C>R?RmE`Icmy{+cq~#YW1h^`sW#*(7>wyEr4@kxU zaSkMSco`UsjeBJMrZY#e>3p6R5I=gVvu9sZ3mR|KC8&zoWa-!G)1kCO^3nw z|DT=z{~I6pv`($TmZ9`V^Ks^VF$~?;)Vf$ZSlr!gVoI61uh}q^zTY3j(ESN2$WZ!i zR}6}YVwfhXHQEL^mh!7L)-r{7l(MTe)Uw!?a6#>P^g5#XI19+i5`Un5?qHTH*iswo z5)K=N5}@U;-#66!k162-lKLeq$5>+A!hxDZWo!h_V5vn# z`9)R=&WU;ICBST!m!hB|7ZAiJzpI0J2LtC>#i$7RxpTq-g7yIo72!r``qf$6N` z>rYV;adYRqHqcY>EK$fUEiO?=N>#|uQz*$uRVYX-$xtZCS12k4@iU7R3X1a6ixPA7 zc)6g4pGO$J;lExZub@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8_F jzak?8!vul)MiT)B4aNFq0YwHImHH_RDhv#$6i^cYKX(=$ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/ABNCMP.SCP b/CONTENT/BT/AUDIO/ABNCMP.SCP new file mode 100644 index 0000000..18a89cc --- /dev/null +++ b/CONTENT/BT/AUDIO/ABNCMP.SCP @@ -0,0 +1,103 @@ +# +################################################################### +# AmmoBin Audio Script +################################################################### +# + +# +################################################################### +# AmmoBinEjecting component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=EjectStart01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=AmmoBinEjectingVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=AmmoBinEjectingComponent + +# +################################################################### +# AmmoBinEjected component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=EjectButton01 +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=AmmoBinEjectedVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=AmmoBinEjectedComponent + +# +################################################################### +# AmmoBinDumped component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=EjectEnd01 +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=AmmoBinDumpedVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=AmmoBinDumpedComponent + +# +################################################################### +# AmmoBinFireWarning component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=Warnings01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=WarningVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=AmmoBinFireWarningComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=AmmoBinFireWarningComponent +tempo=160 +midi_file=audio\abfwrn01.mid +is_looped=False +dump_value=False +name=AmmoBinFireWarningSequence + +[AudioIdleWatcher] +audio_component=AmmoBinFireWarningSequence + diff --git a/CONTENT/BT/AUDIO/ABNTRG.SCP b/CONTENT/BT/AUDIO/ABNTRG.SCP new file mode 100644 index 0000000..b95a3ef --- /dev/null +++ b/CONTENT/BT/AUDIO/ABNTRG.SCP @@ -0,0 +1,96 @@ +# +################################################################### +# Projectile Internal Audio Script +################################################################### +# + +# +################################################################### +# Includes +################################################################### +# +[include] +file=audio\dsttrg.scp + +# +################################################################### +# AmmoBinEjecting component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=AmmoState +audio_component=AmmoBinEjectingComponent +trigger_state=AmmoBin::Ejecting +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=AmmoState +audio_component=AmmoBinEjectingComponent +trigger_state=AmmoBin::Ejecting +inverse_trigger=True +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# AmmoBinEjected component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=AmmoState +audio_component=AmmoBinEjectedComponent +trigger_state=AmmoBin::Ejected +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# AmmoBinDumped component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=AmmoState +audio_component=AmmoBinDumpedComponent +trigger_state=AmmoBin::AmmoDumped +inverse_trigger=False +control_ID=StartAudioControlID +control_value=3.0 +dump_value=False + +# +################################################################### +# AmmoBinFireWarning component +################################################################### +# + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=FireCountdownStarted +audio_component=AmmoBinFireWarningSequence +attribute_match_value=True +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=FireCountdownStarted +audio_component=AmmoBinFireWarningSequence +attribute_match_value=False +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/ACNCMP.SCP b/CONTENT/BT/AUDIO/ACNCMP.SCP new file mode 100644 index 0000000..27db5e8 --- /dev/null +++ b/CONTENT/BT/AUDIO/ACNCMP.SCP @@ -0,0 +1,34 @@ +# +################################################################### +# Mech AutoCannon Audio Script +################################################################### +# + +[macro] +ProjectileFireResource=AutoCannonAction01 +ProjectileFireComponent=AutoCannonFireComponent +# +ProjectileLaunchResource=AutoCannonFire01 +ProjectileLaunchComponent=AutoCannonLaunchComponent +# +ProjectileLoadingResource=AutoCannonLoading01 +ProjectileLoadingComponent=AutoCannonLoadingComponent +# +ProjectileLoadedResource=AutoCannonLoaded01 +ProjectileLoadedComponent=AutoCannonLoadedComponent +ProjectileLoadedSequence=AutoCannonLoadedSequence +# +ProjectileTriggerDuringLoadResource=TriggerDuringLoad01 +ProjectileTriggerDuringLoadComponent=AutoCannonTriggerDuringLoadComponent +# +ProjectileMisfireResource=AutoCannonMisfire01 +ProjectileMisfireComponent=AutoCannonMisfireComponent +ProjectileMisfireSequence=AutoCannonMisfireSequence +# +ProjectileJamResource=AutoCannonJam01 +ProjectileJamComponent=AutoCannonJamComponent +ProjectileJamSequence=AutoCannonJamSequence + +[include] +file=audio\prjcmp.scp + diff --git a/CONTENT/BT/AUDIO/ACNCMPE.SCP b/CONTENT/BT/AUDIO/ACNCMPE.SCP new file mode 100644 index 0000000..d0264fc --- /dev/null +++ b/CONTENT/BT/AUDIO/ACNCMPE.SCP @@ -0,0 +1,13 @@ +# +################################################################### +# AutoCannon External Audio Script +################################################################### +# + +[macro] +ProjectileLaunchResource=AutoCannonFireExt01 +ProjectileLaunchVolume=AutoCannonExtLaunchVolume +ProjectileLaunchComponent=AutoCannonExtLaunchComponent + +[include] +file=audio\prjcmpe.scp \ No newline at end of file diff --git a/CONTENT/BT/AUDIO/ACNTRG.SCP b/CONTENT/BT/AUDIO/ACNTRG.SCP new file mode 100644 index 0000000..98186fd --- /dev/null +++ b/CONTENT/BT/AUDIO/ACNTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Mech AutoCannon Internal Audio Script +################################################################### +# + +[include] +file=audio\prjtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/ACNTRGE.SCP b/CONTENT/BT/AUDIO/ACNTRGE.SCP new file mode 100644 index 0000000..5951aa7 --- /dev/null +++ b/CONTENT/BT/AUDIO/ACNTRGE.SCP @@ -0,0 +1,8 @@ +# +################################################################### +# AutoCannon External Audio Script +################################################################### +# + +[include] +file=audio\prjtrge.scp diff --git a/CONTENT/BT/AUDIO/ALMINT.SCP b/CONTENT/BT/AUDIO/ALMINT.SCP new file mode 100644 index 0000000..55a0113 --- /dev/null +++ b/CONTENT/BT/AUDIO/ALMINT.SCP @@ -0,0 +1,78 @@ +# +################################################################### +# Mech Alarm Internal Audio Script +################################################################### +# + +# +################################################################### +# IncomingAlarm component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=IncomingAlarm01 +position=RearDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=IncomingAlarmVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=IncomingAlarmComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=IncomingAlarmComponent +tempo=100 +midi_file=audio\incarm01.mid +is_looped=True +dump_value=False +name=IncomingAlarmSequence + +[AudioIdleWatcher] +audio_component=IncomingAlarmSequence + +#------------------------------------------------------------------ + +# +# distance to missile -> tempo +# + +[AudioScalarScale] +subsystem=Entity +attribute=DistanceToMissile +audio_component=IncomingAlarmSequence +attribute_value_boundary1=100.0 +attribute_value_boundary2=800.0 +control_ID=TempoAudioControlID +control_value_boundary1=600 +control_value_boundary2=10 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[AudioLogicalTrigger] +subsystem=Entity +attribute=IncomingLock +audio_component=IncomingAlarmSequence +attribute_match_value=True +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioLogicalTrigger] +subsystem=Entity +attribute=IncomingLock +audio_component=IncomingAlarmSequence +attribute_match_value=False +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/AUDIO.INI b/CONTENT/BT/AUDIO/AUDIO.INI new file mode 100644 index 0000000..b5bcc45 --- /dev/null +++ b/CONTENT/BT/AUDIO/AUDIO.INI @@ -0,0 +1,53 @@ +[AudioRenderer] + +# +# Radius of clipping sphere +# +clipping_radius=450.0 + +# +# Distance between ears +# +distance_between_ears=2.0 + +# +# Control amplitude rolloff +# +amplitude_rolloff=2.0 +amplitude_rolloff_knee=60.0 +amplitude_rolloff_distance_scale=0.003 + +# +# Control high frequency rolloff +# +high_frequency_rolloff=2.0 +high_frequency_rolloff_knee=60.0 +high_frequency_rolloff_distance_scale=0.0035 + +# +# Control doppler +# +doppler_range=600.0 +speed_of_sound=250.0 + +# +# Control source compression +# +compression_scale=0.92 +compression_exponent=8.5 + +# +# ITD difference constant +# +itd_difference=0.0015 + +# +# Global reverb scale +# +global_reverb_scale=0.3 + +[AudioResources] +front_audio_resource=audio\audio1.res +front_audio_resource=audio\audio2.res +rear_audio_resource=audio\audio1.res +rear_audio_resource=audio\audio2.res diff --git a/CONTENT/BT/AUDIO/AUDIOMR.INI b/CONTENT/BT/AUDIO/AUDIOMR.INI new file mode 100644 index 0000000..a7afe88 --- /dev/null +++ b/CONTENT/BT/AUDIO/AUDIOMR.INI @@ -0,0 +1,53 @@ +[AudioRenderer] + +# +# Radius of clipping sphere +# +clipping_radius=700.0 + +# +# Distance between ears +# +distance_between_ears=2.0 + +# +# Control amplitude rolloff +# +amplitude_rolloff=2.0 +amplitude_rolloff_knee=60.0 +amplitude_rolloff_distance_scale=0.002 + +# +# Control high frequency rolloff +# +high_frequency_rolloff=2.0 +high_frequency_rolloff_knee=60.0 +high_frequency_rolloff_distance_scale=0.003 + +# +# Control doppler +# +doppler_range=600.0 +speed_of_sound=250.0 + +# +# Control source compression +# +compression_scale=0.1 +compression_exponent=9.0 + +# +# ITD difference constant +# +itd_difference=0.0015 + +# +# Global reverb scale +# +global_reverb_scale=0.3 + +[AudioResources] +front_audio_resource=audio\audio1.res +front_audio_resource=audio\audio2.res +rear_audio_resource=audio\audio1.res +rear_audio_resource=audio\audio2.res diff --git a/CONTENT/BT/AUDIO/AVA1EXT.SCP b/CONTENT/BT/AUDIO/AVA1EXT.SCP new file mode 100644 index 0000000..ec99344 --- /dev/null +++ b/CONTENT/BT/AUDIO/AVA1EXT.SCP @@ -0,0 +1,43 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC100 component +# +[include] +file=audio\acncmpe.scp + +# AFC100 watcher +[macro] +MechSubsystem=AFC100 +[include] +file=audio\acntrge.scp + +# +# PPC component +# +[include] +file=audio\glrcmpe.scp + +# PPC watcher +[macro] +MechSubsystem=PPC +[include] +file=audio\glrtrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/AVA1INT.SCP b/CONTENT/BT/AUDIO/AVA1INT.SCP new file mode 100644 index 0000000..6511451 --- /dev/null +++ b/CONTENT/BT/AUDIO/AVA1INT.SCP @@ -0,0 +1,97 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC100 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC100 watcher +[macro] +MechSubsystem=AmmoBinAFC100 +[include] +file=audio\abntrg.scp + +# +# AFC100 component +# +[include] +file=audio\laccmp.scp + +# AFC100 watcher +[macro] +MechSubsystem=AFC100 +[include] +file=audio\lactrg.scp + +# +# PPC component +# +[include] +file=audio\ppccmp.scp + +# PPC watcher +[macro] +MechSubsystem=PPC +[include] +file=audio\ppctrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# AmmoBinLRM5 watcher +[macro] +MechSubsystem=AmmoBinLRM5 +[include] +file=audio\abntrg.scp + +# +# LRM5 component +# +[include] +file=audio\lrmcmp.scp + +# LRM5 watcher +[macro] +MechSubsystem=LRM5 +[include] +file=audio\lrmtrg.scp + +# AmmoBinSRM2 watcher +[macro] +MechSubsystem=AmmoBinSRM2 +[include] +file=audio\abntrg.scp + +# +# SRM2 component +# +[include] +file=audio\srmcmp.scp + +# SRM2 watcher +[macro] +MechSubsystem=SRM2 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/AVA2.SCP b/CONTENT/BT/AUDIO/AVA2.SCP new file mode 100644 index 0000000..2282034 --- /dev/null +++ b/CONTENT/BT/AUDIO/AVA2.SCP @@ -0,0 +1,55 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC5_1 component +# +[include] +file=audio\acncmpe.scp + +# AFC5_1 watcher +[macro] +MechSubsystem=AFC5_1 +[include] +file=audio\acntrge.scp + +# AFC5_2 watcher +[macro] +MechSubsystem=AFC5_2 +[include] +file=audio\acntrge.scp + +# AFC5_3 watcher +[macro] +MechSubsystem=AFC5_3 +[include] +file=audio\acntrge.scp + +# AFC5_4 watcher +[macro] +MechSubsystem=AFC5_4 +[include] +file=audio\acntrge.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/AVAEXT.SCP b/CONTENT/BT/AUDIO/AVAEXT.SCP new file mode 100644 index 0000000..e1aaba3 --- /dev/null +++ b/CONTENT/BT/AUDIO/AVAEXT.SCP @@ -0,0 +1,61 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC50 component +# +[include] +file=audio\acncmpe.scp + +# AFC50 watcher +[macro] +MechSubsystem=AFC50 +[include] +file=audio\acntrge.scp + +# +# ERLLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# ERLLaser_1 watcher +[macro] +MechSubsystem=ERLLaser_1 +[include] +file=audio\glrtrge.scp + +# ERLLaser_2 watcher +[macro] +MechSubsystem=ERLLaser_2 +[include] +file=audio\glrtrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# ERMLaser_3 watcher +[macro] +MechSubsystem=ERMLaser_3 +[include] +file=audio\glrtrge.scp + +# ERMLaser_4 watcher +[macro] +MechSubsystem=ERMLaser_4 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/AVAINT.SCP b/CONTENT/BT/AUDIO/AVAINT.SCP new file mode 100644 index 0000000..82dae63 --- /dev/null +++ b/CONTENT/BT/AUDIO/AVAINT.SCP @@ -0,0 +1,109 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC50 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC50 watcher +[macro] +MechSubsystem=AmmoBinAFC50 +[include] +file=audio\abntrg.scp + +# +# AFC50 component +# +[include] +file=audio\maccmp.scp + +# AFC50 watcher +[macro] +MechSubsystem=AFC50 +[include] +file=audio\mactrg.scp + +# +# ERLLaser_1 component +# +[include] +file=audio\erlcmp.scp + +# ERLLaser_1 watcher +[macro] +MechSubsystem=ERLLaser_1 +[include] +file=audio\erltrg.scp + +# ERLLaser_2 watcher +[macro] +MechSubsystem=ERLLaser_2 +[include] +file=audio\erltrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# ERMLaser_3 watcher +[macro] +MechSubsystem=ERMLaser_3 +[include] +file=audio\ermtrg.scp + +# ERMLaser_4 watcher +[macro] +MechSubsystem=ERMLaser_4 +[include] +file=audio\ermtrg.scp + +# AmmoBinLRM10_1 watcher +[macro] +MechSubsystem=AmmoBinLRM10_1 +[include] +file=audio\abntrg.scp + +# +# LRM10_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM10_1 watcher +[macro] +MechSubsystem=LRM10_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM10_2 watcher +[macro] +MechSubsystem=AmmoBinLRM10_2 +[include] +file=audio\abntrg.scp + +# LRM10_2 watcher +[macro] +MechSubsystem=LRM10_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/BATEXT.SCP b/CONTENT/BT/AUDIO/BATEXT.SCP new file mode 100644 index 0000000..f76f79a --- /dev/null +++ b/CONTENT/BT/AUDIO/BATEXT.SCP @@ -0,0 +1,25 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\glrtrge.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/BATINT.SCP b/CONTENT/BT/AUDIO/BATINT.SCP new file mode 100644 index 0000000..aa2a9e4 --- /dev/null +++ b/CONTENT/BT/AUDIO/BATINT.SCP @@ -0,0 +1,85 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC_1 component +# +[include] +file=audio\ppccmp.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\ppctrg.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\ppctrg.scp + +# +# AmmoBinLRM15_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinLRM15_1 watcher +[macro] +MechSubsystem=AmmoBinLRM15_1 +[include] +file=audio\abntrg.scp + +# +# LRM15_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM15_1 watcher +[macro] +MechSubsystem=LRM15_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM15_2 watcher +[macro] +MechSubsystem=AmmoBinLRM15_2 +[include] +file=audio\abntrg.scp + +# LRM15_2 watcher +[macro] +MechSubsystem=LRM15_2 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM15_3 watcher +[macro] +MechSubsystem=AmmoBinLRM15_3 +[include] +file=audio\abntrg.scp + +# LRM15_3 watcher +[macro] +MechSubsystem=LRM15_3 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM15_4 watcher +[macro] +MechSubsystem=AmmoBinLRM15_4 +[include] +file=audio\abntrg.scp + +# LRM15_4 watcher +[macro] +MechSubsystem=LRM15_4 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/BBNEXP.SCP b/CONTENT/BT/AUDIO/BBNEXP.SCP new file mode 100644 index 0000000..cfbc1c7 --- /dev/null +++ b/CONTENT/BT/AUDIO/BBNEXP.SCP @@ -0,0 +1,118 @@ +# +################################################################### +# Big Burning Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# BigExplosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=AuxExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=BigExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=BigExplosionComponent + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=BigExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-200 +max_value=200 +name=BigExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=BigExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.7 +max_value=1.0 +name=BigExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=BigExplosionPitchSampleAndHold +audio_component=BigExplosionBrightnessSampleAndHold +audio_component=BigExplosionComponent +name=BigExplosionSplitter + +[AudioControlSequence] +audio_component=BigExplosionSplitter +tempo=160 +midi_file=audio\bigexp01.mid +is_looped=False +dump_value=False +name=BigExplosionSequence + +[AudioIdleWatcher] +audio_component=BigExplosionSequence + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=BigExplosionSequence +control_ID=StartAudioControlID +control_value=0.0 + +# +################################################################### +# SmallFire component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=SmallFireLoop01 +priority=0 +mix_presence=3 +volume_mix_level=SmallFireVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=SmallFireComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=SmallFireComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/BHK1EXT.SCP b/CONTENT/BT/AUDIO/BHK1EXT.SCP new file mode 100644 index 0000000..b1f6056 --- /dev/null +++ b/CONTENT/BT/AUDIO/BHK1EXT.SCP @@ -0,0 +1,43 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\glrtrge.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\glrtrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# ERMLaser_3 watcher +[macro] +MechSubsystem=ERMLaser_3 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/BHK1INT.SCP b/CONTENT/BT/AUDIO/BHK1INT.SCP new file mode 100644 index 0000000..3b4888b --- /dev/null +++ b/CONTENT/BT/AUDIO/BHK1INT.SCP @@ -0,0 +1,85 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC_1 component +# +[include] +file=audio\ppccmp.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\ppctrg.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\ppctrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# ERMLaser_3 watcher +[macro] +MechSubsystem=ERMLaser_3 +[include] +file=audio\ermtrg.scp + +# +# AmmoBinSRM6_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinSRM6_1 watcher +[macro] +MechSubsystem=AmmoBinSRM6_1 +[include] +file=audio\abntrg.scp + +# +# SRM6_1 component +# +[include] +file=audio\srmcmp.scp + +# SRM6_1 watcher +[macro] +MechSubsystem=SRM6_1 +[include] +file=audio\srmtrg.scp + +# AmmoBinSRM6_2 watcher +[macro] +MechSubsystem=AmmoBinSRM6_2 +[include] +file=audio\abntrg.scp + +# SRM6_2 watcher +[macro] +MechSubsystem=SRM6_2 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/BIGEXP.SCP b/CONTENT/BT/AUDIO/BIGEXP.SCP new file mode 100644 index 0000000..36e90b6 --- /dev/null +++ b/CONTENT/BT/AUDIO/BIGEXP.SCP @@ -0,0 +1,91 @@ +# +################################################################### +# Big Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# BigExplosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=AuxExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=BigExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=BigExplosionComponent + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=BigExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-200 +max_value=200 +name=BigExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=BigExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.7 +max_value=1.0 +name=BigExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=BigExplosionPitchSampleAndHold +audio_component=BigExplosionBrightnessSampleAndHold +audio_component=BigExplosionComponent +name=BigExplosionSplitter + +[AudioControlSequence] +audio_component=BigExplosionSplitter +tempo=160 +midi_file=audio\bigexp01.mid +is_looped=False +dump_value=False +name=BigExplosionSequence + +[AudioIdleWatcher] +audio_component=BigExplosionSequence + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=BigExplosionSequence +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/BIGEXP01.MID b/CONTENT/BT/AUDIO/BIGEXP01.MID new file mode 100644 index 0000000000000000000000000000000000000000..0f41bde4515b1048fe1acfa4dfa9b4b8ca281a09 GIT binary patch literal 91 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8O| mzak?8!vxFv3QGnC*ZKfg1_r(QMg=_v28sH12??MUeFgxApcI4v literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/BLKEXT.SCP b/CONTENT/BT/AUDIO/BLKEXT.SCP new file mode 100644 index 0000000..49cf53d --- /dev/null +++ b/CONTENT/BT/AUDIO/BLKEXT.SCP @@ -0,0 +1,61 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# ERLLaser component +# +[include] +file=audio\glrcmpe.scp + +# ERLLaser watcher +[macro] +MechSubsystem=ERLLaser +[include] +file=audio\glrtrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# ERMLaser_3 watcher +[macro] +MechSubsystem=ERMLaser_3 +[include] +file=audio\glrtrge.scp + +# ERMLaser_4 watcher +[macro] +MechSubsystem=ERMLaser_4 +[include] +file=audio\glrtrge.scp + +# ERMLaser_5 watcher +[macro] +MechSubsystem=ERMLaser_5 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/BLKINT.SCP b/CONTENT/BT/AUDIO/BLKINT.SCP new file mode 100644 index 0000000..50c6329 --- /dev/null +++ b/CONTENT/BT/AUDIO/BLKINT.SCP @@ -0,0 +1,109 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# ERLLaser component +# +[include] +file=audio\erlcmp.scp + +# ERLLaser watcher +[macro] +MechSubsystem=ERLLaser +[include] +file=audio\erltrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# ERMLaser_3 watcher +[macro] +MechSubsystem=ERMLaser_3 +[include] +file=audio\ermtrg.scp + +# ERMLaser_4 watcher +[macro] +MechSubsystem=ERMLaser_4 +[include] +file=audio\ermtrg.scp + +# ERMLaser_5 watcher +[macro] +MechSubsystem=ERMLaser_5 +[include] +file=audio\ermtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# +# AmmoBinSRM6_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinSRM6_1 watcher +[macro] +MechSubsystem=AmmoBinSRM6_1 +[include] +file=audio\abntrg.scp + +# +# SRM6_1 component +# +[include] +file=audio\srmcmp.scp + +# SRM6_1 watcher +[macro] +MechSubsystem=SRM6_1 +[include] +file=audio\srmtrg.scp + +# AmmoBinSRM6_2 watcher +[macro] +MechSubsystem=AmmoBinSRM6_2 +[include] +file=audio\abntrg.scp + +# SRM6_2 watcher +[macro] +MechSubsystem=SRM6_2 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/BRNEXT.SCP b/CONTENT/BT/AUDIO/BRNEXT.SCP new file mode 100644 index 0000000..42eb52e --- /dev/null +++ b/CONTENT/BT/AUDIO/BRNEXT.SCP @@ -0,0 +1,105 @@ +# +################################################################### +# Mech External Burning Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.75 +name=ExplosionLocation + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.5 +name=FireLocation + +# +################################################################### +# Mech Explosion external component +################################################################### +# + +[Dynamic3DPatchSource] +location=ExplosionLocation +resource=MechExplosion01 +priority=0 +mix_presence=2 +volume_mix_level=MechExplosionExternalVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=MechExplosionExternalComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=MechExplosionExternalComponent +tempo=100 +midi_file=audio\mchexp07.mid +is_looped=False +dump_value=False +name=MechExplosionExternalSequence + +[AudioIdleWatcher] +audio_component=MechExplosionExternalSequence + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=MechExplosionExternalSequence +control_ID=StartAudioControlID +control_value=0.0 + +# +################################################################### +# MechFire external component +################################################################### +# + +[Dynamic3DPatchSource] +location=FireLocation +resource=MechFireLoop01 +priority=0 +mix_presence=3 +volume_mix_level=MechFireExternalVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=MechFireExternalComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=MechFireExternalComponent +tempo=160 +midi_file=audio\mchfre01.mid +is_looped=False +dump_value=False +name=MechFireExternalSequence + +[AudioIdleWatcher] +audio_component=MechFireExternalSequence + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=MechFireExternalSequence +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/BRNINT.SCP b/CONTENT/BT/AUDIO/BRNINT.SCP new file mode 100644 index 0000000..0e09cbe --- /dev/null +++ b/CONTENT/BT/AUDIO/BRNINT.SCP @@ -0,0 +1,117 @@ +# +################################################################### +# Mech Internal Burning Audio Script +################################################################### +# + +# +################################################################### +# Death component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=Death01 +position=FrontDirectPatchPosition +priority=4 +mix_presence=1 +volume_mix_level=DeathVolume +pitch_mix_offset=0.0 +brightness_mix_level=0.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=5.0 +name=DeathComponent01 + +[DirectPatchSource] +location=OriginLocation +resource=Death01 +position=RearDirectPatchPosition +priority=4 +mix_presence=1 +volume_mix_level=DeathVolume +pitch_mix_offset=0.0 +brightness_mix_level=0.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=5.0 +name=DeathComponent02 + +[DirectPatchSource] +location=OriginLocation +resource=Death01 +position=RearDirectPatchPosition +priority=4 +mix_presence=1 +volume_mix_level=DeathVolume +pitch_mix_offset=0.0 +brightness_mix_level=0.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=5.0 +name=DeathComponent03 + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=DeathComponent01 +tempo=100 +midi_file=audio\mchexpi1.mid +is_looped=False +dump_value=False +name=DeathComponent01Sequence + +[AudioControlSequence] +audio_component=DeathComponent02 +tempo=100 +midi_file=audio\mchexpi2.mid +is_looped=False +dump_value=False +name=DeathComponent02Sequence + +[AudioControlSequence] +audio_component=DeathComponent03 +tempo=100 +midi_file=audio\mchexpi3.mid +is_looped=False +dump_value=False +name=DeathComponent03Sequence + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=DeathComponent01Sequence +audio_component=DeathComponent02Sequence +audio_component=DeathComponent03Sequence +name=DeathSplitter + +[AudioIdleWatcher] +audio_component=DeathSplitter + +#------------------------------------------------------------------ + +[AudioStateTrigger] +subsystem=Entity +attribute=SimulationState +audio_component=DeathSplitter +trigger_state=Mech::BurningState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioStateTrigger] +subsystem=Entity +attribute=SimulationState +audio_component=DeathSplitter +trigger_state=Mech::BurningState +inverse_trigger=True +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + + diff --git a/CONTENT/BT/AUDIO/BUTCMP.SCP b/CONTENT/BT/AUDIO/BUTCMP.SCP new file mode 100644 index 0000000..dc33afd --- /dev/null +++ b/CONTENT/BT/AUDIO/BUTCMP.SCP @@ -0,0 +1,103 @@ +# +################################################################### +# Mech Subsystem Buttons Audio Script +################################################################### +# + +# +################################################################### +# SelectGenerator component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=GeneratorSelect01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=SelectGeneratorVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=SelectGeneratorComponent + +# +################################################################### +# GeneratorMode component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=DefaultButton01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=GeneratorModeVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=GeneratorModeComponent + +# +################################################################### +# ToggleCooling component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=DefaultButton01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=ToggleCoolingVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=ToggleCoolingComponent + +# +################################################################### +# ConfigureMappables component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProgramButton01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=ConfigureMappablesVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=ConfigureMappablesComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=ConfigureMappablesComponent +tempo=160 +midi_file=audio\prgbut01.mid +is_looped=True +dump_value=False +name=ConfigureMappablesSequence + +[AudioIdleWatcher] +audio_component=ConfigureMappablesSequence + diff --git a/CONTENT/BT/AUDIO/BUTTRG.SCP b/CONTENT/BT/AUDIO/BUTTRG.SCP new file mode 100644 index 0000000..69eda7f --- /dev/null +++ b/CONTENT/BT/AUDIO/BUTTRG.SCP @@ -0,0 +1,90 @@ +# +################################################################### +# Mech Subsystem Buttons Audio Script +################################################################### +# + +# +################################################################### +# SelectGenerator component +################################################################### +# + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=PoweredSubsystem::SelectGeneratorAMessageID +audio_component=SelectGeneratorComponent +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=PoweredSubsystem::SelectGeneratorBMessageID +audio_component=SelectGeneratorComponent +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=PoweredSubsystem::SelectGeneratorCMessageID +audio_component=SelectGeneratorComponent +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=PoweredSubsystem::SelectGeneratorDMessageID +audio_component=SelectGeneratorComponent +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# GeneratorMode component +################################################################### +# + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=PoweredSubsystem::ToggleGeneratorModeMessageID +audio_component=GeneratorModeComponent +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# ToggleCooling component +################################################################### +# + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=HeatableSubsystem::ToggleCoolingMessageID +audio_component=ToggleCoolingComponent +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# ConfigureMappables component +################################################################### +# + +[AudioIntegerTrigger] +subsystem=MechSubsystem +attribute=ConfigureActivePress +audio_component=ConfigureMappablesSequence +attribute_value_threshold=-1 +control_ID_on=StartAudioControlID +control_ID_off=StopAudioControlID +control_value_on=0.0 +control_value_off=0.0 +inverse_trigger=False +dump_value=False + diff --git a/CONTENT/BT/AUDIO/CALEXT.SCP b/CONTENT/BT/AUDIO/CALEXT.SCP new file mode 100644 index 0000000..a4b7f3f --- /dev/null +++ b/CONTENT/BT/AUDIO/CALEXT.SCP @@ -0,0 +1,49 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\glrtrge.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\glrtrge.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/CALINT.SCP b/CONTENT/BT/AUDIO/CALINT.SCP new file mode 100644 index 0000000..922879c --- /dev/null +++ b/CONTENT/BT/AUDIO/CALINT.SCP @@ -0,0 +1,91 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC_1 component +# +[include] +file=audio\ppccmp.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\ppctrg.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\ppctrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\erstrg.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\erstrg.scp + +# +# AmmoBinLRM15_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinLRM15_1 watcher +[macro] +MechSubsystem=AmmoBinLRM15_1 +[include] +file=audio\abntrg.scp + +# +# LRM15_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM15_1 watcher +[macro] +MechSubsystem=LRM15_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM15_2 watcher +[macro] +MechSubsystem=AmmoBinLRM15_2 +[include] +file=audio\abntrg.scp + +# LRM15_2 watcher +[macro] +MechSubsystem=LRM15_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/CLKWRN01.MID b/CONTENT/BT/AUDIO/CLKWRN01.MID new file mode 100644 index 0000000000000000000000000000000000000000..c044502166f268ca93f7989f87cb8fdf08ea31b9 GIT binary patch literal 100 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8_F jzak?8!vul)MiT)B4dMDG2Vn*c@%kwY;tUL^6i^cYI_MS8 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/CLTCMP.SCP b/CONTENT/BT/AUDIO/CLTCMP.SCP new file mode 100644 index 0000000..f045653 --- /dev/null +++ b/CONTENT/BT/AUDIO/CLTCMP.SCP @@ -0,0 +1,74 @@ +# +################################################################### +# Coolant System Audio Script +################################################################### +# + +# +################################################################### +# CoolantLeakWarning component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=Warnings01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=WarningVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=CoolantLeakWarningComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=CoolantLeakWarningComponent +tempo=160 +midi_file=audio\clkwrn01.mid +is_looped=True +dump_value=False +name=CoolantLeakWarningSequence + +[AudioIdleWatcher] +audio_component=CoolantLeakWarningSequence + +# +################################################################### +# CoolantLeak component +################################################################### +# + +[!DirectPatchSource] +location=OriginLocation +resource=CoolantLeak01 +position=RearDirectPatchPosition +priority=0 +mix_presence=0 +volume_mix_level=CoolantLeakVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=CoolantLeakComponent + +#------------------------------------------------------------------ + +# +# amplitude smoother -> amplitude +# + +[!AudioControlSmoother] +audio_component=CoolantLeakComponent +number_of_samples=4 +control_ID=VolumeAudioControlID +name=CoolantLeakAmplitudeSmoother + + diff --git a/CONTENT/BT/AUDIO/CLTTRG.SCP b/CONTENT/BT/AUDIO/CLTTRG.SCP new file mode 100644 index 0000000..d6ac9f0 --- /dev/null +++ b/CONTENT/BT/AUDIO/CLTTRG.SCP @@ -0,0 +1,63 @@ +# +################################################################### +# Coolant System Buttons Audio Script +################################################################### +# + +# +################################################################### +# CoolantLeakWarning component +################################################################### +# + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=ReportLeak +audio_component=CoolantLeakWarningSequence +attribute_match_value=True +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=ReportLeak +audio_component=CoolantLeakWarningSequence +attribute_match_value=False +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# CoolantLeak component +################################################################### +# + +[!AudioScalarScale] +subsystem=MechSubsystem +attribute=CoolantMassLeakRate +audio_component=CoolantLeakAmplitudeSmoother +attribute_value_boundary1=0.0 +attribute_value_boundary2=0.1 +control_ID=TempoAudioControlID +control_value_boundary1=0.0 +control_value_boundary2=1.0 +exponent=0.5 +dump_value=False + +#------------------------------------------------------------------ + +[!AudioScalarTrigger] +subsystem=MechSubsystem +attribute=CoolantMassLeakRate +audio_component=CoolantLeakComponent +attribute_value_threshold=0.01 +control_ID_on=StartAudioControlID +control_ID_off=StopAudioControlID +control_value_on=0.0 +control_value_off=0.0 +inverse_trigger=False +dump_value=False + + diff --git a/CONTENT/BT/AUDIO/CNDCMP.SCP b/CONTENT/BT/AUDIO/CNDCMP.SCP new file mode 100644 index 0000000..f3730c4 --- /dev/null +++ b/CONTENT/BT/AUDIO/CNDCMP.SCP @@ -0,0 +1,49 @@ +# +################################################################### +# Condenser Audio Script +################################################################### +# + +# +################################################################### +# CoolantPressureIncrease component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=CoolantPressureIncrease03 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=CoolantPressureVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=CoolantPressureIncreaseComponent + +# +################################################################### +# CoolantPressureDecrease component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=CoolantPressureDecrease03 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=CoolantPressureVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=CoolantPressureDecreaseComponent + + diff --git a/CONTENT/BT/AUDIO/CNDTRG.SCP b/CONTENT/BT/AUDIO/CNDTRG.SCP new file mode 100644 index 0000000..490de8a --- /dev/null +++ b/CONTENT/BT/AUDIO/CNDTRG.SCP @@ -0,0 +1,46 @@ +# +################################################################### +# Condenser Audio Script +################################################################### +# + +# +################################################################### +# Includes +################################################################### +# +[include] +file=audio\clttrg.scp + +# +################################################################### +# CoolantPressureIncrease component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=CondenserState +audio_component=CoolantPressureIncreaseComponent +trigger_state=Condenser::OpeningCondenserState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=4.0 +dump_value=False + +# +################################################################### +# CoolantPressureDecrease component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=CondenserState +audio_component=CoolantPressureDecreaseComponent +trigger_state=Condenser::ClosingCondenserState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=4.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/COLEXT.SCP b/CONTENT/BT/AUDIO/COLEXT.SCP new file mode 100644 index 0000000..f3ab54d --- /dev/null +++ b/CONTENT/BT/AUDIO/COLEXT.SCP @@ -0,0 +1,102 @@ +# +################################################################### +# Mech Internal Collision Audio Script +################################################################### +# + +[macro] +CollisionTopSpeed=25 + +# +################################################################### +# Collision component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=CollisionExt01 +priority=0 +mix_presence=0 +volume_mix_level=CollisionExternalVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=CollisionExternalComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=CollisionExternalComponent +audio_resource_index=CollisionExtIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=CollisionExternalResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=CollisionExternalResourceSelect +control_ID=100 +sample_duration=0.0 +name=CollisionExternalSampleAndHold + +#------------------------------------------------------------------ + +# +# collision speed -> attack volume +# + +[AudioScalarScale] +subsystem=Entity +attribute=CollisionSpeed +audio_component=CollisionExternalComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=CollisionTopSpeed +control_ID=AttackVolumeAudioControlID +control_value_boundary1=0.9 +control_value_boundary2=1.0 +exponent=0.5 +dump_value=False + +#------------------------------------------------------------------ + +# +# collision speed -> filter +# + +[AudioScalarScale] +subsystem=Entity +attribute=CollisionSpeed +audio_component=CollisionExternalComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=CollisionTopSpeed +control_ID=BrightnessAudioControlID +control_value_boundary1=0.8 +control_value_boundary2=1.0 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[AudioStateTrigger] +subsystem=Entity +attribute=CollisionState +audio_component=CollisionExternalComponent +trigger_state=Mech::InitialHitState +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=3.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/COLINT.SCP b/CONTENT/BT/AUDIO/COLINT.SCP new file mode 100644 index 0000000..6eabea9 --- /dev/null +++ b/CONTENT/BT/AUDIO/COLINT.SCP @@ -0,0 +1,135 @@ +# +################################################################### +# Mech Collision Internal Collision Audio Script +################################################################### +# + +[macro] +CollisionTopSpeed=25 +CollisionTopAngularSpeed=0.8 + +# +################################################################### +# Collision component +################################################################### +# + +[Static3DPatchSource] +location=OriginLocation +resource=Collision01 +priority=2 +mix_presence=3 +volume_mix_level=CollisionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=CollisionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=CollisionComponent +audio_resource_index=CollisionIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=CollisionResourceSelect + +# +# angular speed -> resource select +# + +[AudioMotionScale] +subsystem=Entity +attribute=LocalVelocity +motion_type=AngularMotionType +motion_value=LengthMotionValue +audio_component=CollisionResourceSelect +attribute_value_boundary1=0.0 +attribute_value_boundary2=CollisionTopAngularSpeed +control_ID=100 +control_value_boundary1=0.0 +control_value_boundary2=1.0 +exponent=0.5 +dump_value=False + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=CollisionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=100 +name=CollisionPitchSampleAndHold + +#------------------------------------------------------------------ + +# +# collision speed -> attack volume +# + +[AudioScalarScale] +subsystem=Entity +attribute=CollisionSpeed +audio_component=CollisionComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=CollisionTopSpeed +control_ID=AttackVolumeAudioControlID +control_value_boundary1=0.9 +control_value_boundary2=1.0 +exponent=0.5 +dump_value=False + +#------------------------------------------------------------------ + +# +# collision speed -> filter +# + +[AudioScalarScale] +subsystem=Entity +attribute=CollisionSpeed +audio_component=CollisionComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=CollisionTopSpeed +control_ID=BrightnessAudioControlID +control_value_boundary1=0.7 +control_value_boundary2=1.0 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[AudioStateTrigger] +subsystem=Entity +attribute=CollisionState +audio_component=CollisionPitchSampleAndHold +trigger_state=Mech::InitialHitState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[L4AudioCollisionTrigger] +subsystem=Entity +attribute=CollisionState +normal_attribute=CollisionNormal +audio_component=CollisionComponent +trigger_state=Mech::InitialHitState +control_ID=StartAudioControlID +control_value=3.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/CRNEXP.SCP b/CONTENT/BT/AUDIO/CRNEXP.SCP new file mode 100644 index 0000000..d92479b --- /dev/null +++ b/CONTENT/BT/AUDIO/CRNEXP.SCP @@ -0,0 +1,84 @@ +# +################################################################### +# Crunch Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.25 +name=OriginLocation + +# +################################################################### +# Crunch component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=Crunch01 +priority=0 +mix_presence=3 +volume_mix_level=CrunchExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=CrunchComponent + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=CrunchComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-200 +max_value=200 +name=CrunchPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=CrunchComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.7 +max_value=1.0 +name=CrunchBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=CrunchPitchSampleAndHold +audio_component=CrunchBrightnessSampleAndHold +name=CrunchSplitter + +[AudioControlSend] +audio_component=CrunchSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=CrunchComponent +control_ID=StartAudioControlID +control_value=3.0 + + diff --git a/CONTENT/BT/AUDIO/CTMIX.CFG b/CONTENT/BT/AUDIO/CTMIX.CFG new file mode 100644 index 0000000..90b2515 --- /dev/null +++ b/CONTENT/BT/AUDIO/CTMIX.CFG @@ -0,0 +1,15 @@ +/MA:229;0 +/VO:0;0 +/MI:229;0 +/CD:0;0 +/LI:0;0 +/MIC:0 +/SP:0 +/TR:114;0 +/BA:114;0 +/IPL:MIC- CDR- CDL- LIR- LIL- MIR- MIL- +/IPR:MIC- CDR- CDL- LIR- LIL- MIR- MIL- +/OPS:MIC- CDR- CDL- LIR- LIL- +/AGC:- +/IPG:1,1 +/OPG:1,1 diff --git a/CONTENT/BT/AUDIO/DGAEXP.SCP b/CONTENT/BT/AUDIO/DGAEXP.SCP new file mode 100644 index 0000000..c3ded99 --- /dev/null +++ b/CONTENT/BT/AUDIO/DGAEXP.SCP @@ -0,0 +1,47 @@ +# +################################################################### +# DamageBurn A Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.33 +name=OriginLocation + +# +################################################################### +# DamageBurn component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=Damage01 +priority=0 +mix_presence=0 +volume_mix_level=DamageBurnAVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=DamageBurnComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=DamageBurnComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/DGBEXP.SCP b/CONTENT/BT/AUDIO/DGBEXP.SCP new file mode 100644 index 0000000..574ccf1 --- /dev/null +++ b/CONTENT/BT/AUDIO/DGBEXP.SCP @@ -0,0 +1,47 @@ +# +################################################################### +# DamageBurn B Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.33 +name=OriginLocation + +# +################################################################### +# DamageBurn component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=Damage02 +priority=0 +mix_presence=0 +volume_mix_level=DamageBurnBVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=DamageBurnComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=DamageBurnComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/DGCEXP.SCP b/CONTENT/BT/AUDIO/DGCEXP.SCP new file mode 100644 index 0000000..7c8a750 --- /dev/null +++ b/CONTENT/BT/AUDIO/DGCEXP.SCP @@ -0,0 +1,48 @@ +# +################################################################### +# DamageBurn C Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.33 +name=OriginLocation + +# +################################################################### +# DamageBurn component +################################################################### +# + +[Static3DPatchSource] +location=OriginLocation +resource=Damage03 +priority=1 +mix_presence=0 +volume_mix_level=DamageBurnCVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +use_internal=False +name=DamageBurnComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=DamageBurnComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/DSTCMP.SCP b/CONTENT/BT/AUDIO/DSTCMP.SCP new file mode 100644 index 0000000..2794d5d --- /dev/null +++ b/CONTENT/BT/AUDIO/DSTCMP.SCP @@ -0,0 +1,38 @@ +# +################################################################### +# Destroyed Internal Audio Script +################################################################### +# + +# +################################################################### +# SubsystemDestroyed component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=DestroyedInt06 +position=RearDirectPatchPosition +priority=0 +mix_presence=3 +volume_mix_level=SubsystemDestroyedVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=SubsystemDestroyedComponent + +[AudioControlSequence] +audio_component=SubsystemDestroyedComponent +tempo=160 +midi_file=audio\dstrd02.mid +is_looped=False +dump_value=False +name=SubsystemDestroyedSequence + +[AudioIdleWatcher] +audio_component=SubsystemDestroyedSequence + diff --git a/CONTENT/BT/AUDIO/DSTRD01.MID b/CONTENT/BT/AUDIO/DSTRD01.MID new file mode 100644 index 0000000000000000000000000000000000000000..b18194aa2303dffc78d2d2bc377fbe3f5eb3f643 GIT binary patch literal 96 zcmeYb$w*;fU|?flWMF2f@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+s(_Q> dzak@094;UM5tyKo(&FNl(!`>|P~ira2LSVB79{`x literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/DSTRD02.MID b/CONTENT/BT/AUDIO/DSTRD02.MID new file mode 100644 index 0000000000000000000000000000000000000000..3bb9786b11443326b76e1939279c3dc6b40b177f GIT binary patch literal 79 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8F_ azak?8!vvL-HV+jB2Dg-^8aJRaeFgxaF%nb& literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/DSTTRG.SCP b/CONTENT/BT/AUDIO/DSTTRG.SCP new file mode 100644 index 0000000..3666a82 --- /dev/null +++ b/CONTENT/BT/AUDIO/DSTTRG.SCP @@ -0,0 +1,22 @@ +# +################################################################### +# Destroyed Internal Audio Script +################################################################### +# + +# +################################################################### +# Destroyed component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=SimulationState +audio_component=SubsystemDestroyedSequence +trigger_state=MechSubsystem::Destroyed +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/EPCCMP.SCP b/CONTENT/BT/AUDIO/EPCCMP.SCP new file mode 100644 index 0000000..c661ea9 --- /dev/null +++ b/CONTENT/BT/AUDIO/EPCCMP.SCP @@ -0,0 +1,57 @@ +# +################################################################### +# ER PPC Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserAFire01 +LaserFirePitchOffset=-200 +LaserFireComponent=PPCFireComponent +LaserFireIndex=LaserAFireIndex +LaserFireResourceSelect=PPCFireResourceSelect +LaserFireSampleAndHold=PPCFireSampleAndHold +# +LaserSustainResource=LaserASustain01 +LaserSustainComponent=PPCSustainComponent +LaserSustainIndex=LaserASustainIndex +LaserSustainResourceSelect=PPCSustainResourceSelect +LaserSustainSampleAndHold=PPCSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=PPCReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=PPCReleaseResourceSelect +LaserReleaseSampleAndHold=PPCReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=PPCChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=PPCChargeResourceSelect +LaserChargeSampleAndHold=PPCChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=SmallLaserLoadedComponent +LaserLoadedSequence=SmallLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=PPCTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=PPCMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=PPCSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + +#------------------------------------------------------------------ + +[macro] +CoolantLeakComponent=PPCCoolantLeakComponent +CoolantLeakAmplitudeSmoother=PPCCoolantLeakAmplitudeSmoother + +[include] +file=audio\cltcmp.scp + diff --git a/CONTENT/BT/AUDIO/EPPCMP.SCP b/CONTENT/BT/AUDIO/EPPCMP.SCP new file mode 100644 index 0000000..a5a5782 --- /dev/null +++ b/CONTENT/BT/AUDIO/EPPCMP.SCP @@ -0,0 +1,48 @@ +# +################################################################### +# ER PPC Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserAFire01 +LaserFirePitchOffset=-200 +LaserFireComponent=PPCFireComponent +LaserFireIndex=LaserAFireIndex +LaserFireResourceSelect=PPCFireResourceSelect +LaserFireSampleAndHold=PPCFireSampleAndHold +# +LaserSustainResource=LaserASustain01 +LaserSustainComponent=PPCSustainComponent +LaserSustainIndex=LaserASustainIndex +LaserSustainResourceSelect=PPCSustainResourceSelect +LaserSustainSampleAndHold=PPCSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=PPCReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=PPCReleaseResourceSelect +LaserReleaseSampleAndHold=PPCReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=PPCChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=PPCChargeResourceSelect +LaserChargeSampleAndHold=PPCChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=PPCLoadedComponent +LaserLoadedSequence=PPCLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=PPCTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=PPCMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=PPCSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + diff --git a/CONTENT/BT/AUDIO/EPPCMPE.SCP b/CONTENT/BT/AUDIO/EPPCMPE.SCP new file mode 100644 index 0000000..c2d8c10 --- /dev/null +++ b/CONTENT/BT/AUDIO/EPPCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# ER PPC External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserASustain01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=-100 +LaserSustainComponent=ERPPCExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/EPPTRG.SCP b/CONTENT/BT/AUDIO/EPPTRG.SCP new file mode 100644 index 0000000..042ba9c --- /dev/null +++ b/CONTENT/BT/AUDIO/EPPTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# PPC Internal Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/EPPTRGE.SCP b/CONTENT/BT/AUDIO/EPPTRGE.SCP new file mode 100644 index 0000000..86e97c1 --- /dev/null +++ b/CONTENT/BT/AUDIO/EPPTRGE.SCP @@ -0,0 +1,9 @@ +# +################################################################### +# PPC External Audio Script +################################################################### +# + +[include] +file=audio\lsrtrge.scp + diff --git a/CONTENT/BT/AUDIO/ERLCMP.SCP b/CONTENT/BT/AUDIO/ERLCMP.SCP new file mode 100644 index 0000000..91db4fb --- /dev/null +++ b/CONTENT/BT/AUDIO/ERLCMP.SCP @@ -0,0 +1,48 @@ +# +################################################################### +# Extended Range Large Laser Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserCFire01 +LaserFirePitchOffset=-200 +LaserFireComponent=ERLLaserFireComponent +LaserFireIndex=LaserCFireIndex +LaserFireResourceSelect=ERLLaserFireResourceSelect +LaserFireSampleAndHold=ERLLaserFireSampleAndHold +# +LaserSustainResource=LaserCSustain01 +LaserSustainComponent=ERLLaserSustainComponent +LaserSustainIndex=LaserCSustainIndex +LaserSustainResourceSelect=ERLLaserSustainResourceSelect +LaserSustainSampleAndHold=ERLLaserSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=ERLLaserReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=ERLLaserReleaseResourceSelect +LaserReleaseSampleAndHold=ERLLaserReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=ERLLaserChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=ERLLaserChargeResourceSelect +LaserChargeSampleAndHold=ERLLaserChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=ERLLaserLoadedComponent +LaserLoadedSequence=ERLLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=ERLLaserTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=ERLLaserMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=ERLLaserSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + diff --git a/CONTENT/BT/AUDIO/ERLCMPE.SCP b/CONTENT/BT/AUDIO/ERLCMPE.SCP new file mode 100644 index 0000000..1765e35 --- /dev/null +++ b/CONTENT/BT/AUDIO/ERLCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# ER Large Laser External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserCSustainExt01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=-200 +LaserSustainComponent=ERLLaserExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/ERLTRG.SCP b/CONTENT/BT/AUDIO/ERLTRG.SCP new file mode 100644 index 0000000..251ed5b --- /dev/null +++ b/CONTENT/BT/AUDIO/ERLTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# ER Large Laser Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/ERLTRGE.SCP b/CONTENT/BT/AUDIO/ERLTRGE.SCP new file mode 100644 index 0000000..ab9013c --- /dev/null +++ b/CONTENT/BT/AUDIO/ERLTRGE.SCP @@ -0,0 +1,8 @@ +# +################################################################### +# ER Laser External Triggers +################################################################### +# + +[include] +file=audio\lsrtrge.scp diff --git a/CONTENT/BT/AUDIO/ERMCMP.SCP b/CONTENT/BT/AUDIO/ERMCMP.SCP new file mode 100644 index 0000000..524270d --- /dev/null +++ b/CONTENT/BT/AUDIO/ERMCMP.SCP @@ -0,0 +1,49 @@ +# +################################################################### +# Extended Range Medium Laser Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserCFire01 +LaserFirePitchOffset=0 +LaserFireComponent=ERMLaserFireComponent +LaserFireIndex=LaserCFireIndex +LaserFireResourceSelect=ERMLaserFireResourceSelect +LaserFireSampleAndHold=ERMLaserFireSampleAndHold +# +LaserSustainResource=LaserCSustain01 +LaserSustainComponent=ERMLaserSustainComponent +LaserSustainIndex=LaserCSustainIndex +LaserSustainResourceSelect=ERMLaserSustainResourceSelect +LaserSustainSampleAndHold=ERMLaserSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=ERMLaserReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=ERMLaserReleaseResourceSelect +LaserReleaseSampleAndHold=ERMLaserReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=ERMLaserChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=ERMLaserChargeResourceSelect +LaserChargeSampleAndHold=ERMLaserChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=ERMLaserLoadedComponent +LaserLoadedSequence=ERMLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=ERMLaserTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=ERMLaserMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=ERMLaserSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + + diff --git a/CONTENT/BT/AUDIO/ERMCMPE.SCP b/CONTENT/BT/AUDIO/ERMCMPE.SCP new file mode 100644 index 0000000..07971b6 --- /dev/null +++ b/CONTENT/BT/AUDIO/ERMCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# ER Medium Laser External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserCSustainExt01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=0 +LaserSustainComponent=ERMLaserExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/ERMTRG.SCP b/CONTENT/BT/AUDIO/ERMTRG.SCP new file mode 100644 index 0000000..9b2edc6 --- /dev/null +++ b/CONTENT/BT/AUDIO/ERMTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# ER Medium Laser Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/ERMTRGE.SCP b/CONTENT/BT/AUDIO/ERMTRGE.SCP new file mode 100644 index 0000000..ab9013c --- /dev/null +++ b/CONTENT/BT/AUDIO/ERMTRGE.SCP @@ -0,0 +1,8 @@ +# +################################################################### +# ER Laser External Triggers +################################################################### +# + +[include] +file=audio\lsrtrge.scp diff --git a/CONTENT/BT/AUDIO/ERSCMP.SCP b/CONTENT/BT/AUDIO/ERSCMP.SCP new file mode 100644 index 0000000..ab13ade --- /dev/null +++ b/CONTENT/BT/AUDIO/ERSCMP.SCP @@ -0,0 +1,48 @@ +# +################################################################### +# Extended Range Small Laser Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserCFire01 +LaserFirePitchOffset=200 +LaserFireComponent=ERSLaserFireComponent +LaserFireIndex=LaserCFireIndex +LaserFireResourceSelect=ERSLaserFireResourceSelect +LaserFireSampleAndHold=ERSLaserFireSampleAndHold +# +LaserSustainResource=LaserCSustain01 +LaserSustainComponent=ERSLaserSustainComponent +LaserSustainIndex=LaserCSustainIndex +LaserSustainResourceSelect=ERSLaserSustainResourceSelect +LaserSustainSampleAndHold=ERSLaserSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=ERSLaserReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=ERSLaserReleaseResourceSelect +LaserReleaseSampleAndHold=ERSLaserReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=ERSLaserChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=ERSLaserChargeResourceSelect +LaserChargeSampleAndHold=ERSLaserChargeSampleAndHold +# +LaserLoadedComponent=ERSLaserLoadedComponent +LaserLoadedSequence=ERSLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=ERSLaserTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=ERSLaserMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=ERSLaserSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + + diff --git a/CONTENT/BT/AUDIO/ERSCMPE.SCP b/CONTENT/BT/AUDIO/ERSCMPE.SCP new file mode 100644 index 0000000..29494ed --- /dev/null +++ b/CONTENT/BT/AUDIO/ERSCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# ER Small Laser External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserCSustainExt01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=200 +LaserSustainComponent=ERSLaserExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/ERSTRG.SCP b/CONTENT/BT/AUDIO/ERSTRG.SCP new file mode 100644 index 0000000..3ac1265 --- /dev/null +++ b/CONTENT/BT/AUDIO/ERSTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# ER Small Laser Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/ERSTRGE.SCP b/CONTENT/BT/AUDIO/ERSTRGE.SCP new file mode 100644 index 0000000..ab9013c --- /dev/null +++ b/CONTENT/BT/AUDIO/ERSTRGE.SCP @@ -0,0 +1,8 @@ +# +################################################################### +# ER Laser External Triggers +################################################################### +# + +[include] +file=audio\lsrtrge.scp diff --git a/CONTENT/BT/AUDIO/FIND.TXT b/CONTENT/BT/AUDIO/FIND.TXT new file mode 100644 index 0000000..e69de29 diff --git a/CONTENT/BT/AUDIO/FIREXT.SCP b/CONTENT/BT/AUDIO/FIREXT.SCP new file mode 100644 index 0000000..ade38d8 --- /dev/null +++ b/CONTENT/BT/AUDIO/FIREXT.SCP @@ -0,0 +1,43 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# LLaser component +# +[include] +file=audio\glrcmpe.scp + +# LLaser watcher +[macro] +MechSubsystem=LLaser +[include] +file=audio\glrtrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/FIRINT.SCP b/CONTENT/BT/AUDIO/FIRINT.SCP new file mode 100644 index 0000000..33562db --- /dev/null +++ b/CONTENT/BT/AUDIO/FIRINT.SCP @@ -0,0 +1,79 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# LLaser component +# +[include] +file=audio\llrcmp.scp + +# LLaser watcher +[macro] +MechSubsystem=LLaser +[include] +file=audio\llrtrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# +# AmmoBinSTRK4 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinSTRK4 watcher +[macro] +MechSubsystem=AmmoBinSTRK4 +[include] +file=audio\abntrg.scp + +# +# STRK4 component +# +[include] +file=audio\srmcmp.scp + +# STRK4 watcher +[macro] +MechSubsystem=STRK4 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/FOTEXT.SCP b/CONTENT/BT/AUDIO/FOTEXT.SCP new file mode 100644 index 0000000..15893bf --- /dev/null +++ b/CONTENT/BT/AUDIO/FOTEXT.SCP @@ -0,0 +1,126 @@ +# +################################################################### +# Mech Foot Fall External Audio Script +################################################################### +# + +[!macro] +FootFallTopAcceleration=7.0 +FootFallTopSpeed=40.0 + +[!Dynamic3DPatchSource] +location=OriginLocation +resource=FootFallExt01 +priority=0 +mix_presence=0 +volume_mix_level=FootFallExternalVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=FootFallExternalComponent + +#------------------------------------------------------------------ + +# +# linear acceleration -> filter +# + +[!AudioMotionScale] +subsystem=Entity +attribute=LocalAcceleration +motion_type=0 +motion_value=3 +audio_component=FootFallExternalComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=FootFallTopAcceleration +control_ID=BrightnessAudioControlID +control_value_boundary1=0.5 +control_value_boundary2=1.0 +exponent=0.5 +dump_value=False + +# +# linear velocity -> pitch +# + +[!AudioMotionScale] +subsystem=Entity +attribute=LocalVelocity +motion_type=0 +motion_value=3 +audio_component=FootFallExternalComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=FootFallTopSpeed +control_ID=PitchAudioControlID +control_value_boundary1=-400 +control_value_boundary2=0 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[!AudioLogicalTrigger] +subsystem=Entity +attribute=FootStep +audio_component=FootFallExternalComponent +attribute_match_value=True +control_ID=StartAudioControlID +control_value=1.5 +dump_value=False + +# +################################################################### +# Mech Footfall and servo combo +################################################################### +# + +[macro] +MyomerServoTopSpeed=60.0 + +[Dynamic3DPatchSource] +location=OriginLocation +resource=FootFallExt02 +priority=0 +mix_presence=0 +volume_mix_level=FootFallExternalVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=FootFallExternalComponent + +#------------------------------------------------------------------ + +# +# linear velocity -> pitch +# + +[AudioMotionScale] +subsystem=Entity +attribute=LocalVelocity +motion_type=0 +motion_value=3 +audio_component=FootFallExternalComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=MyomerServoTopSpeed +control_ID=PitchAudioControlID +control_value_boundary1=-500 +control_value_boundary2=500 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[AudioLogicalTrigger] +subsystem=Entity +attribute=FootStep +audio_component=FootFallExternalComponent +attribute_match_value=True +control_ID=StartAudioControlID +control_value=1.5 +dump_value=False diff --git a/CONTENT/BT/AUDIO/FOTINT.SCP b/CONTENT/BT/AUDIO/FOTINT.SCP new file mode 100644 index 0000000..c73b3ab --- /dev/null +++ b/CONTENT/BT/AUDIO/FOTINT.SCP @@ -0,0 +1,131 @@ +# +################################################################### +# FootFall component +################################################################### +# + +[macro] +FootFallTopAcceleration=10 +FootFallTopAngularSpeed=0.6 + +# +################################################################### +# Mech Foot Fall Internal Audio Script +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=FootFallInt01 +position=FrontDirectPatchPosition +priority=0 +mix_presence=4 +volume_mix_level=FootFallVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=FootFallComponent + +#------------------------------------------------------------------ + +# +# amplitude mixer -> amplitude +# + +[AudioControlMixer] +audio_component=FootFallComponent +first_input_control_ID=100 +last_input_control_ID=101 +output_control_ID=VolumeAudioControlID +name=FootFallAmplitudeMixer + +# +# filter mixer -> filter +# + +[AudioControlMixer] +audio_component=FootFallComponent +first_input_control_ID=100 +last_input_control_ID=101 +output_control_ID=BrightnessAudioControlID +name=FootFallFilterMixer + +# +# control splitter +# + +[AudioControlSplitter] +audio_component=FootFallAmplitudeMixer +audio_component=FootFallFilterMixer +name=FootFallSplitter + +# +# smoother1 -> splitter +# + +[AudioControlSmoother] +audio_component=FootFallSplitter +number_of_samples=Sample2Sec +control_ID=100 +name=FootFallSmoother1 + +# +# linear acceleration -> smoother1 +# + +[AudioMotionScale] +subsystem=Entity +attribute=LocalAcceleration +motion_type=LinearMotionType +motion_value=LengthMotionValue +audio_component=FootFallSmoother1 +attribute_value_boundary1=0.0 +attribute_value_boundary2=FootFallTopAcceleration +control_ID=100 +control_value_boundary1=0.0 +control_value_boundary2=1.0 +exponent=0.4 +dump_value=False + +# +# smoother2 -> splitter +# + +[AudioControlSmoother] +audio_component=FootFallSplitter +number_of_samples=Sample1Sec +control_ID=101 +name=FootFallSmoother2 + +# +# angular velocity -> smoother2 +# + +[AudioMotionScale] +subsystem=Entity +attribute=LocalVelocity +motion_type=AngularMotionType +motion_value=LengthMotionValue +audio_component=FootFallSmoother2 +attribute_value_boundary1=0.0 +attribute_value_boundary2=FootFallTopAngularSpeed +control_ID=101 +control_value_boundary1=0.0 +control_value_boundary2=0.4 +exponent=0.4 +dump_value=False + +#------------------------------------------------------------------ + +[AudioLogicalTrigger] +subsystem=Entity +attribute=FootStep +audio_component=FootFallComponent +attribute_match_value=True +control_ID=StartAudioControlID +control_value=2.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/GENCMP.SCP b/CONTENT/BT/AUDIO/GENCMP.SCP new file mode 100644 index 0000000..f3da8dd --- /dev/null +++ b/CONTENT/BT/AUDIO/GENCMP.SCP @@ -0,0 +1,61 @@ +# +################################################################### +# Generator Audio Script +################################################################### +# + +# +################################################################### +# GeneratorOn component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=BasicBeep01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=GeneratorOnVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=GeneratorOnComponent + +# +################################################################### +# GeneratorOutWarning component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=Warnings01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=WarningVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=GeneratorOutWarningComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=GeneratorOutWarningComponent +tempo=160 +midi_file=audio\genwrn02.mid +is_looped=False +dump_value=False +name=GeneratorOutWarningSequence + +[AudioIdleWatcher] +audio_component=GeneratorOutWarningSequence + diff --git a/CONTENT/BT/AUDIO/GENTRG.SCP b/CONTENT/BT/AUDIO/GENTRG.SCP new file mode 100644 index 0000000..143e7af --- /dev/null +++ b/CONTENT/BT/AUDIO/GENTRG.SCP @@ -0,0 +1,65 @@ +# +################################################################### +# Generator Audio Script +################################################################### +# + +# +################################################################### +# Includes +################################################################### +# +[include] +file=audio\clttrg.scp + +# +################################################################### +# GeneratorOn component +################################################################### +# + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=GeneratorOn +audio_component=GeneratorOnComponent +attribute_match_value=True +control_ID=StartAudioControlID +control_value=0.5 +dump_value=False + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=GeneratorOn +audio_component=GeneratorOnComponent +attribute_match_value=False +control_ID=StartAudioControlID +control_value=0.5 +dump_value=False + +# +################################################################### +# GeneratorOutWarning component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=GeneratorState +audio_component=GeneratorOutWarningSequence +trigger_state=Generator::Off +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=GeneratorState +audio_component=GeneratorOutWarningSequence +trigger_state=Generator::Overheated +inverse_trigger=True +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + + diff --git a/CONTENT/BT/AUDIO/GENWRN01.MID b/CONTENT/BT/AUDIO/GENWRN01.MID new file mode 100644 index 0000000000000000000000000000000000000000..eb7ea959d4fc82c7910e7706ebec178b2aba18ed GIT binary patch literal 86 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz9FM hzak?8!vxv-MiW^E8-e;J2LT2Vsroh(DWGb71^^)}6Mp~z literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/GENWRN02.MID b/CONTENT/BT/AUDIO/GENWRN02.MID new file mode 100644 index 0000000000000000000000000000000000000000..c491531dc2e58a525e4a70a3e99e95602a0bc646 GIT binary patch literal 86 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz9FM hzak?8!vxv-MiW^E8-e;J2LT2VsrqIgDWGb71^^+v6O;e| literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/GLRCMPE.SCP b/CONTENT/BT/AUDIO/GLRCMPE.SCP new file mode 100644 index 0000000..603e5eb --- /dev/null +++ b/CONTENT/BT/AUDIO/GLRCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# Generic Laser External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserCSustainExt04 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=-200 +LaserSustainComponent=GenericLaserExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/GLRTRGE.SCP b/CONTENT/BT/AUDIO/GLRTRGE.SCP new file mode 100644 index 0000000..ab9013c --- /dev/null +++ b/CONTENT/BT/AUDIO/GLRTRGE.SCP @@ -0,0 +1,8 @@ +# +################################################################### +# ER Laser External Triggers +################################################################### +# + +[include] +file=audio\lsrtrge.scp diff --git a/CONTENT/BT/AUDIO/HETEXT.SCP b/CONTENT/BT/AUDIO/HETEXT.SCP new file mode 100644 index 0000000..f2ec50f --- /dev/null +++ b/CONTENT/BT/AUDIO/HETEXT.SCP @@ -0,0 +1,39 @@ +# +################################################################### +# Heat Management External Audio Script +################################################################### +# + +# +################################################################### +# CoolantDump component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=CoolantDumpExt01 +priority=0 +mix_presence=0 +volume_mix_level=CoolantDumpExternalVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=CoolantDumpComponent + +#------------------------------------------------------------------ + +[AudioStateTrigger] +subsystem=Reservoir +attribute=ReservoirState +audio_component=CoolantDumpComponent +trigger_state=Reservoir::InjectingState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=4.0 +dump_value=False + + diff --git a/CONTENT/BT/AUDIO/HETINT.SCP b/CONTENT/BT/AUDIO/HETINT.SCP new file mode 100644 index 0000000..927e68f --- /dev/null +++ b/CONTENT/BT/AUDIO/HETINT.SCP @@ -0,0 +1,85 @@ +# +################################################################### +# Heat Management Audio Script +################################################################### +# + +# +################################################################### +# CoolantDump component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=CoolantDump05 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=CoolantDumpVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=CoolantDumpComponent + +#------------------------------------------------------------------ + +[AudioScalarScale] +subsystem=HeatSink +attribute=CurrentTemperature +audio_component=CoolantDumpComponent +attribute_value_boundary1=300 +attribute_value_boundary2=1200 +control_ID=PitchAudioControlID +control_value_boundary1=-100 +control_value_boundary2=100 +exponent=3.0 +dump_value=False + +[AudioStateTrigger] +subsystem=Reservoir +attribute=ReservoirState +audio_component=CoolantDumpComponent +trigger_state=Reservoir::InjectingState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=6.0 +dump_value=False + +# +################################################################### +# HeatManagement component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=BasicClick01 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=HeatManagementVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=HeatManagementComponent + +#------------------------------------------------------------------ + +[AudioControlsButtonTrigger] +subsystem=Entity +attribute=ReduceButton +audio_component=HeatManagementComponent +attribute_value_threshold=0.0 +control_ID_on=StartAudioControlID +control_ID_off=NullAudioControlID +control_value_on=0.5 +control_value_off=0.0 +inverse_trigger=False +dump_value=False diff --git a/CONTENT/BT/AUDIO/ICOM.CFG b/CONTENT/BT/AUDIO/ICOM.CFG new file mode 100644 index 0000000..3b00802 --- /dev/null +++ b/CONTENT/BT/AUDIO/ICOM.CFG @@ -0,0 +1,15 @@ +/MA:229;0 +/VO:0;0 +/MI:229;0 +/CD:0;0 +/LI:0;0 +/MIC:0 +/SP:0 +/TR:114;0 +/BA:114;0 +/IPL:MIC- CDR- CDL- LIR- LIL+ MIR- MIL- +/IPR:MIC- CDR- CDL- LIR+ LIL- MIR- MIL- +/OPS:MIC- CDR- CDL- LIR+ LIL+ +/AGC:- +/IPG:1,1 +/OPG:1,1 diff --git a/CONTENT/BT/AUDIO/INCARM01.MID b/CONTENT/BT/AUDIO/INCARM01.MID new file mode 100644 index 0000000000000000000000000000000000000000..0ebaa2af53953c26cdd9478ac5bb25416297e6a2 GIT binary patch literal 107 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`ibE+R;_^;0ZRbayK VUy+f4VS-gkV}TU|0}&KZF97GX85sZo literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/JAKEXT.SCP b/CONTENT/BT/AUDIO/JAKEXT.SCP new file mode 100644 index 0000000..c99cdb2 --- /dev/null +++ b/CONTENT/BT/AUDIO/JAKEXT.SCP @@ -0,0 +1,49 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# GAUSS_1 component +# +[include] +file=audio\acncmpe.scp + +# GAUSS_1 watcher +[macro] +MechSubsystem=GAUSS_1 +[include] +file=audio\acntrge.scp + +# +# LLaser component +# +[include] +file=audio\glrcmpe.scp + +# LLaser watcher +[macro] +MechSubsystem=LLaser +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/JAKINT.SCP b/CONTENT/BT/AUDIO/JAKINT.SCP new file mode 100644 index 0000000..bde7649 --- /dev/null +++ b/CONTENT/BT/AUDIO/JAKINT.SCP @@ -0,0 +1,97 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinGAUSS_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinGAUSS_1 watcher +[macro] +MechSubsystem=AmmoBinGAUSS_1 +[include] +file=audio\abntrg.scp + +# +# GAUSS_1 component +# +[include] +file=audio\saccmp.scp + +# GAUSS_1 watcher +[macro] +MechSubsystem=GAUSS_1 +[include] +file=audio\sactrg.scp + +# +# LLaser component +# +[include] +file=audio\llrcmp.scp + +# LLaser watcher +[macro] +MechSubsystem=LLaser +[include] +file=audio\llrtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\erstrg.scp + +# AmmoBinLRM15_1 watcher +[macro] +MechSubsystem=AmmoBinLRM15_1 +[include] +file=audio\abntrg.scp + +# +# LRM15_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM15_1 watcher +[macro] +MechSubsystem=LRM15_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM15_2 watcher +[macro] +MechSubsystem=AmmoBinLRM15_2 +[include] +file=audio\abntrg.scp + +# LRM15_2 watcher +[macro] +MechSubsystem=LRM15_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/LACCMP.SCP b/CONTENT/BT/AUDIO/LACCMP.SCP new file mode 100644 index 0000000..cc36293 --- /dev/null +++ b/CONTENT/BT/AUDIO/LACCMP.SCP @@ -0,0 +1,38 @@ +# +################################################################### +# Large AutoCannon Audio Script +################################################################### +# + +[macro] +ProjectileFireResource=AutoCannonAction01 +ProjectileFireVolume=LargeAutoCannonFireVolume +ProjectileFirePitchOffset=-200 +ProjectileFireComponent=LargeAutoCannonFireComponent +# +ProjectileLaunchResource=AutoCannonFire01 +ProjectileLaunchVolume=LargeAutoCannonLaunchVolume +ProjectileLaunchPitchOffset=-200 +ProjectileLaunchComponent=LargeAutoCannonLaunchComponent +# +ProjectileLoadingResource=AutoCannonLoading01 +ProjectileLoadingComponent=LargeAutoCannonLoadingComponent +# +ProjectileLoadedResource=AutoCannonLoaded01 +ProjectileLoadedComponent=LargeAutoCannonLoadedComponent +ProjectileLoadedSequence=LargeAutoCannonLoadedSequence +# +ProjectileTriggerDuringLoadResource=TriggerDuringLoad01 +ProjectileTriggerDuringLoadComponent=LargeAutoCannonTriggerDuringLoadComponent +# +ProjectileMisfireResource=AutoCannonMisfire01 +ProjectileMisfireComponent=LargeAutoCannonMisfireComponent +ProjectileMisfireSequence=LargeAutoCannonMisfireSequence +# +ProjectileJamResource=AutoCannonJam01 +ProjectileJamComponent=LargeAutoCannonJamComponent +ProjectileJamSequence=LargeAutoCannonJamSequence + +[include] +file=audio\prjcmp.scp + diff --git a/CONTENT/BT/AUDIO/LACTRG.SCP b/CONTENT/BT/AUDIO/LACTRG.SCP new file mode 100644 index 0000000..98186fd --- /dev/null +++ b/CONTENT/BT/AUDIO/LACTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Mech AutoCannon Internal Audio Script +################################################################### +# + +[include] +file=audio\prjtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/LEGWRN01.MID b/CONTENT/BT/AUDIO/LEGWRN01.MID new file mode 100644 index 0000000000000000000000000000000000000000..d8b1ec83662141f3a1d7931f623c25d107be5313 GIT binary patch literal 86 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz9FM hzak?8!vxv-MiW^E8-e;J2LT2Vjrukd4WMd$1^^-q6Po}4 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/LLRCMP.SCP b/CONTENT/BT/AUDIO/LLRCMP.SCP new file mode 100644 index 0000000..3a5d7cc --- /dev/null +++ b/CONTENT/BT/AUDIO/LLRCMP.SCP @@ -0,0 +1,49 @@ +# +################################################################### +# Large Laser Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserBFire01 +LaserFirePitchOffset=-200 +LaserFireComponent=LargeLaserFireComponent +LaserFireIndex=LaserBFireIndex +LaserFireResourceSelect=LargeLaserFireResourceSelect +LaserFireSampleAndHold=LargeLaserFireSampleAndHold +# +LaserSustainResource=LaserBSustain01 +LaserSustainComponent=LargeLaserSustainComponent +LaserSustainIndex=LaserBSustainIndex +LaserSustainResourceSelect=LargeLaserSustainResourceSelect +LaserSustainSampleAndHold=LargeLaserSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=LargeLaserReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=LargeLaserReleaseResourceSelect +LaserReleaseSampleAndHold=LargeLaserReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=LargeLaserChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=LargeLaserChargeResourceSelect +LaserChargeSampleAndHold=LargeLaserChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=LargeLaserLoadedComponent +LaserLoadedSequence=LargeLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=LargeLaserTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=LargeLaserMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=LargeLaserSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + + diff --git a/CONTENT/BT/AUDIO/LLRCMPE.SCP b/CONTENT/BT/AUDIO/LLRCMPE.SCP new file mode 100644 index 0000000..aeea41a --- /dev/null +++ b/CONTENT/BT/AUDIO/LLRCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# Medium Laser External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserBSustainExt01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=-200 +LaserSustainComponent=LargeLaserExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/LLRTRG.SCP b/CONTENT/BT/AUDIO/LLRTRG.SCP new file mode 100644 index 0000000..8c6971c --- /dev/null +++ b/CONTENT/BT/AUDIO/LLRTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Large Laser Internal Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/LLRTRGE.SCP b/CONTENT/BT/AUDIO/LLRTRGE.SCP new file mode 100644 index 0000000..3b64622 --- /dev/null +++ b/CONTENT/BT/AUDIO/LLRTRGE.SCP @@ -0,0 +1,9 @@ +# +################################################################### +# Laser External Triggers +################################################################### +# + +[include] +file=audio\lsrtrge.scp + diff --git a/CONTENT/BT/AUDIO/LO1EXT.SCP b/CONTENT/BT/AUDIO/LO1EXT.SCP new file mode 100644 index 0000000..1ced3f0 --- /dev/null +++ b/CONTENT/BT/AUDIO/LO1EXT.SCP @@ -0,0 +1,67 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC1 component +# +[include] +file=audio\acncmpe.scp + +# AFC1 watcher +[macro] +MechSubsystem=AFC1 +[include] +file=audio\acntrge.scp + +# AFC2 watcher +[macro] +MechSubsystem=AFC2 +[include] +file=audio\acntrge.scp + +# +# ERMLaser component +# +[include] +file=audio\glrcmpe.scp + +# ERMLaser watcher +[macro] +MechSubsystem=ERMLaser +[include] +file=audio\glrtrge.scp + +# ERSLaser1 watcher +[macro] +MechSubsystem=ERSLaser1 +[include] +file=audio\glrtrge.scp + +# ERSLaser2 watcher +[macro] +MechSubsystem=ERSLaser2 +[include] +file=audio\glrtrge.scp + +# ERSLaser3 watcher +[macro] +MechSubsystem=ERSLaser3 +[include] +file=audio\glrtrge.scp + +# MLaser1 watcher +[macro] +MechSubsystem=MLaser1 +[include] +file=audio\glrtrge.scp + +# MLaser2 watcher +[macro] +MechSubsystem=MLaser2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/LO1INT.SCP b/CONTENT/BT/AUDIO/LO1INT.SCP new file mode 100644 index 0000000..1239b16 --- /dev/null +++ b/CONTENT/BT/AUDIO/LO1INT.SCP @@ -0,0 +1,121 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC1 watcher +[macro] +MechSubsystem=AmmoBinAFC1 +[include] +file=audio\abntrg.scp + +# +# AFC1 component +# +[include] +file=audio\laccmp.scp + +# AFC1 watcher +[macro] +MechSubsystem=AFC1 +[include] +file=audio\lactrg.scp + +# AmmoBinAFC2 watcher +[macro] +MechSubsystem=AmmoBinAFC2 +[include] +file=audio\abntrg.scp + +# +# AFC2 component +# +[include] +file=audio\maccmp.scp + +# AFC2 watcher +[macro] +MechSubsystem=AFC2 +[include] +file=audio\mactrg.scp + +# +# ERMLaser component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser watcher +[macro] +MechSubsystem=ERMLaser +[include] +file=audio\ermtrg.scp + +# +# ERSLaser1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser1 watcher +[macro] +MechSubsystem=ERSLaser1 +[include] +file=audio\erstrg.scp + +# ERSLaser2 watcher +[macro] +MechSubsystem=ERSLaser2 +[include] +file=audio\erstrg.scp + +# ERSLaser3 watcher +[macro] +MechSubsystem=ERSLaser3 +[include] +file=audio\erstrg.scp + +# +# MLaser1 component +# +[include] +file=audio\mlrcmp.scp + +# MLaser1 watcher +[macro] +MechSubsystem=MLaser1 +[include] +file=audio\mlrtrg.scp + +# MLaser2 watcher +[macro] +MechSubsystem=MLaser2 +[include] +file=audio\mlrtrg.scp + +# AmmoBinSRM watcher +[macro] +MechSubsystem=AmmoBinSRM +[include] +file=audio\abntrg.scp + +# +# SRM component +# +[include] +file=audio\srmcmp.scp + +# SRM watcher +[macro] +MechSubsystem=SRM +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/LOK1EXT.SCP b/CONTENT/BT/AUDIO/LOK1EXT.SCP new file mode 100644 index 0000000..ea11477 --- /dev/null +++ b/CONTENT/BT/AUDIO/LOK1EXT.SCP @@ -0,0 +1,61 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\glrtrge.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\glrtrge.scp + +# LLaser_1 watcher +[macro] +MechSubsystem=LLaser_1 +[include] +file=audio\glrtrge.scp + +# LLaser_2 watcher +[macro] +MechSubsystem=LLaser_2 +[include] +file=audio\glrtrge.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\glrtrge.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\glrtrge.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\glrtrge.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/LOK1INT.SCP b/CONTENT/BT/AUDIO/LOK1INT.SCP new file mode 100644 index 0000000..2728593 --- /dev/null +++ b/CONTENT/BT/AUDIO/LOK1INT.SCP @@ -0,0 +1,103 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC_1 component +# +[include] +file=audio\ppccmp.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\ppctrg.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\ppctrg.scp + +# +# LLaser_1 component +# +[include] +file=audio\llrcmp.scp + +# LLaser_1 watcher +[macro] +MechSubsystem=LLaser_1 +[include] +file=audio\llrtrg.scp + +# LLaser_2 watcher +[macro] +MechSubsystem=LLaser_2 +[include] +file=audio\llrtrg.scp + +# +# MLaser_1 component +# +[include] +file=audio\mlrcmp.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\mlrtrg.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\mlrtrg.scp + +# +# SLaser_1 component +# +[include] +file=audio\slrcmp.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\slrtrg.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\slrtrg.scp + +# +# AmmoBinSRM4 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinSRM4 watcher +[macro] +MechSubsystem=AmmoBinSRM4 +[include] +file=audio\abntrg.scp + +# +# SRM4 component +# +[include] +file=audio\srmcmp.scp + +# SRM4 watcher +[macro] +MechSubsystem=SRM4 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/LOK2EXT.SCP b/CONTENT/BT/AUDIO/LOK2EXT.SCP new file mode 100644 index 0000000..43d63da --- /dev/null +++ b/CONTENT/BT/AUDIO/LOK2EXT.SCP @@ -0,0 +1,67 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC component +# +[include] +file=audio\glrcmpe.scp + +# PPC watcher +[macro] +MechSubsystem=PPC +[include] +file=audio\glrtrge.scp + +# +# GAUSS component +# +[include] +file=audio\acncmpe.scp + +# GAUSS watcher +[macro] +MechSubsystem=GAUSS +[include] +file=audio\acntrge.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\acntrge.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\glrtrge.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\glrtrge.scp + +# MLaser_3 watcher +[macro] +MechSubsystem=MLaser_3 +[include] +file=audio\glrtrge.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\glrtrge.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/LOK2INT.SCP b/CONTENT/BT/AUDIO/LOK2INT.SCP new file mode 100644 index 0000000..3a559e8 --- /dev/null +++ b/CONTENT/BT/AUDIO/LOK2INT.SCP @@ -0,0 +1,115 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC component +# +[include] +file=audio\ppccmp.scp + +# PPC watcher +[macro] +MechSubsystem=PPC +[include] +file=audio\ppctrg.scp + +# +# AmmoBinGAUSS component +# +[include] +file=audio\abncmp.scp + +# AmmoBinGAUSS watcher +[macro] +MechSubsystem=AmmoBinGAUSS +[include] +file=audio\abntrg.scp + +# +# GAUSS component +# +[include] +file=audio\saccmp.scp + +# GAUSS watcher +[macro] +MechSubsystem=GAUSS +[include] +file=audio\sactrg.scp + +# AmmoBinAFC25 watcher +[macro] +MechSubsystem=AmmoBinAFC25 +[include] +file=audio\abntrg.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\sactrg.scp + +# +# MLaser_1 component +# +[include] +file=audio\mlrcmp.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\mlrtrg.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\mlrtrg.scp + +# MLaser_3 watcher +[macro] +MechSubsystem=MLaser_3 +[include] +file=audio\mlrtrg.scp + +# +# SLaser_1 component +# +[include] +file=audio\slrcmp.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\slrtrg.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\slrtrg.scp + +# AmmoBinSRM4 watcher +[macro] +MechSubsystem=AmmoBinSRM4 +[include] +file=audio\abntrg.scp + +# +# SRM4 component +# +[include] +file=audio\srmcmp.scp + +# SRM4 watcher +[macro] +MechSubsystem=SRM4 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/LOKEXT.SCP b/CONTENT/BT/AUDIO/LOKEXT.SCP new file mode 100644 index 0000000..e2576c5 --- /dev/null +++ b/CONTENT/BT/AUDIO/LOKEXT.SCP @@ -0,0 +1,55 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC50_1 component +# +[include] +file=audio\acncmpe.scp + +# AFC50_1 watcher +[macro] +MechSubsystem=AFC50_1 +[include] +file=audio\acntrge.scp + +# AFC50_2 watcher +[macro] +MechSubsystem=AFC50_2 +[include] +file=audio\acntrge.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/LOKINT.SCP b/CONTENT/BT/AUDIO/LOKINT.SCP new file mode 100644 index 0000000..3741c0a --- /dev/null +++ b/CONTENT/BT/AUDIO/LOKINT.SCP @@ -0,0 +1,97 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC50_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC50_1 watcher +[macro] +MechSubsystem=AmmoBinAFC50_1 +[include] +file=audio\abntrg.scp + +# +# AFC50_1 component +# +[include] +file=audio\maccmp.scp + +# AFC50_1 watcher +[macro] +MechSubsystem=AFC50_1 +[include] +file=audio\mactrg.scp + +# AmmoBinAFC50_2 watcher +[macro] +MechSubsystem=AmmoBinAFC50_2 +[include] +file=audio\abntrg.scp + +# AFC50_2 watcher +[macro] +MechSubsystem=AFC50_2 +[include] +file=audio\mactrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# AmmoBinSRM4 watcher +[macro] +MechSubsystem=AmmoBinSRM4 +[include] +file=audio\abntrg.scp + +# +# SRM4 component +# +[include] +file=audio\srmcmp.scp + +# SRM4 watcher +[macro] +MechSubsystem=SRM4 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/LRMCMP.SCP b/CONTENT/BT/AUDIO/LRMCMP.SCP new file mode 100644 index 0000000..7316f1e --- /dev/null +++ b/CONTENT/BT/AUDIO/LRMCMP.SCP @@ -0,0 +1,32 @@ +# +################################################################### +# LRM Audio Script +################################################################### +# + +[macro] +MissileFireResource=MissileLaunch01 +MissileFirePitchOffset=-100 +MissileFireComponent=LRMFireComponent +# +MissileLoadingResource=MissileLoading01 +MissileLoadingComponent=LRMLoadingComponent +# +MissileLoadedResource=MissileLoaded01 +MissileLoadedComponent=LRMLoadedComponent +MissileLoadedSequence=LRMLoadedSequence +# +MissileTriggerDuringLoadResource=TriggerDuringLoad01 +MissileTriggerDuringLoadComponent=LRMTriggerDuringLoadComponent +# +MissileMisfireResource=MissileMisfire01 +MissileMisfireComponent=LRMMisfireComponent +MissileMisfireSequence=LRMMisfireSequence +# +MissileJamResource=MissileJam01 +MissileJamComponent=LRMJamComponent +MissileJamSequence=LRMJamSequence + +[include] +file=audio\mslcmp.scp + diff --git a/CONTENT/BT/AUDIO/LRMTRG.SCP b/CONTENT/BT/AUDIO/LRMTRG.SCP new file mode 100644 index 0000000..4b922d3 --- /dev/null +++ b/CONTENT/BT/AUDIO/LRMTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# LRM Internal Audio Script +################################################################### +# + +[include] +file=audio\msltrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/LSRCMPE.SCP b/CONTENT/BT/AUDIO/LSRCMPE.SCP new file mode 100644 index 0000000..56aa9c8 --- /dev/null +++ b/CONTENT/BT/AUDIO/LSRCMPE.SCP @@ -0,0 +1,26 @@ +# +################################################################### +# Mech Laser External Audio Script +################################################################### +# + +# +################################################################### +# Laser Sustain component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=LaserSustainResource +priority=0 +mix_presence=0 +volume_mix_level=LaserSustainVolume +pitch_mix_offset=LaserPitchOffset +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=LaserSustainComponent + diff --git a/CONTENT/BT/AUDIO/LSREXP.SCP b/CONTENT/BT/AUDIO/LSREXP.SCP new file mode 100644 index 0000000..6879163 --- /dev/null +++ b/CONTENT/BT/AUDIO/LSREXP.SCP @@ -0,0 +1,109 @@ +# +################################################################### +# Laser Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.75 +name=OriginLocation + +# +################################################################### +# Laser Explosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=LaserExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=LaserExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=LaserExplosionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=LaserExplosionComponent +audio_resource_index=LaserExplosionIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=LaserExplosionResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=LaserExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=LaserExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=LaserExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=LaserExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=LaserExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=LaserExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=LaserExplosionSampleAndHold +audio_component=LaserExplosionPitchSampleAndHold +audio_component=LaserExplosionBrightnessSampleAndHold +name=LaserExplosionSplitter + +[AudioControlSend] +audio_component=LaserExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=LaserExplosionComponent +control_ID=StartAudioControlID +control_value=4.0 + diff --git a/CONTENT/BT/AUDIO/LSREXPI.SCP b/CONTENT/BT/AUDIO/LSREXPI.SCP new file mode 100644 index 0000000..5a277a0 --- /dev/null +++ b/CONTENT/BT/AUDIO/LSREXPI.SCP @@ -0,0 +1,109 @@ +# +################################################################### +# Laser Explosion Internal Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Laser Explosion Internal component +################################################################### +# + +[Static3DPatchSource] +location=OriginLocation +resource=LaserExplosionInt01 +priority=2 +mix_presence=3 +volume_mix_level=LaserExplosionIntVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +use_internal=False +name=LaserExplosionIntComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=LaserExplosionIntComponent +audio_resource_index=LaserExplosionIntIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=LaserExplosionIntResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=LaserExplosionIntResourceSelect +control_ID=100 +sample_duration=99.0 +name=LaserExplosionIntSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=LaserExplosionIntComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-100 +max_value=100 +name=LaserExplosionIntPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=LaserExplosionIntComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.8 +max_value=1.0 +name=LaserExplosionIntBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=LaserExplosionIntSampleAndHold +audio_component=LaserExplosionIntPitchSampleAndHold +audio_component=LaserExplosionIntBrightnessSampleAndHold +name=LaserExplosionIntSplitter + +[AudioControlSend] +audio_component=LaserExplosionIntSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=LaserExplosionIntComponent +control_ID=StartAudioControlID +control_value=4.0 + diff --git a/CONTENT/BT/AUDIO/LSRLDD01.MID b/CONTENT/BT/AUDIO/LSRLDD01.MID new file mode 100644 index 0000000000000000000000000000000000000000..d360727fd6054890c1aa1873afb2cc2120351e2a GIT binary patch literal 77 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8k4 Yzak?8!vvN33Ka&1kot-cpdx(+0DJEd$N&HU literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/LSRTRG.SCP b/CONTENT/BT/AUDIO/LSRTRG.SCP new file mode 100644 index 0000000..b704754 --- /dev/null +++ b/CONTENT/BT/AUDIO/LSRTRG.SCP @@ -0,0 +1,171 @@ +# +################################################################### +# Mech Laser Internal Audio Script +################################################################### +# + +# +################################################################### +# Laser Fire component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserFireComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.5 +dump_value=False + +# +################################################################### +# Laser Sustain component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserSustainComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserSustainComponent +trigger_state=MechWeapon::Firing +inverse_trigger=True +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Laser Release component +################################################################### +# + +[!AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserReleaseComponent +trigger_state=MechWeapon::Firing +inverse_trigger=True +control_ID=StartAudioControlID +control_value=0.1 +dump_value=False + +# +################################################################### +# Laser Charge component +################################################################### +# + +# +# percent charge -> volume +# + +[AudioScalarScale] +subsystem=MechSubsystem +attribute=PercentDone +audio_component=LaserChargeComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=1.0 +control_ID=VolumeAudioControlID +control_value_boundary1=0.0 +control_value_boundary2=1.0 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserChargeComponent +trigger_state=MechWeapon::Loading +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserChargeComponent +trigger_state=MechWeapon::Loading +inverse_trigger=True +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Laser Loaded component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserLoadedSequence +trigger_state=MechWeapon::Loaded +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Laser TriggerDuringLoad component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserTriggerDuringLoadComponent +trigger_state=MechWeapon::TriggerDuringLoad +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# Laser Misfire component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserMisfireComponent +trigger_state=MechWeapon::Misfire +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# LaserSeekLevel component +################################################################### +# + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=Emitter::ToggleSeekVoltageMessageID +audio_component=LaserSeekLevelComponent +control_ID=StartAudioControlID +control_value=0.5 +dump_value=False + + diff --git a/CONTENT/BT/AUDIO/LSRTRGE.SCP b/CONTENT/BT/AUDIO/LSRTRGE.SCP new file mode 100644 index 0000000..6acb055 --- /dev/null +++ b/CONTENT/BT/AUDIO/LSRTRGE.SCP @@ -0,0 +1,40 @@ +# +################################################################### +# Laser External Audio Script +################################################################### +# + +# +################################################################### +# Laser Sustain component +################################################################### +# + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=LaserOn +audio_component=LaserSustainComponent +attribute_match_value=True +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioLogicalTrigger] +subsystem=MechSubsystem +attribute=LaserOn +audio_component=LaserSustainComponent +attribute_match_value=False +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + +[!AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=LaserSustainComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/MACCMP.SCP b/CONTENT/BT/AUDIO/MACCMP.SCP new file mode 100644 index 0000000..a3bfcc0 --- /dev/null +++ b/CONTENT/BT/AUDIO/MACCMP.SCP @@ -0,0 +1,38 @@ +# +################################################################### +# Medium AutoCannon Audio Script +################################################################### +# + +[macro] +ProjectileFireResource=AutoCannonAction01 +ProjectileFireVolume=MediumAutoCannonFireVolume +ProjectileFirePitchOffset=0 +ProjectileFireComponent=MediumAutoCannonFireComponent +# +ProjectileLaunchResource=AutoCannonFire01 +ProjectileLaunchVolume=MediumAutoCannonLaunchVolume +ProjectileLaunchPitchOffset=0 +ProjectileLaunchComponent=MediumAutoCannonLaunchComponent +# +ProjectileLoadingResource=AutoCannonLoading01 +ProjectileLoadingComponent=MediumAutoCannonLoadingComponent +# +ProjectileLoadedResource=AutoCannonLoaded01 +ProjectileLoadedComponent=MediumAutoCannonLoadedComponent +ProjectileLoadedSequence=MediumAutoCannonLoadedSequence +# +ProjectileTriggerDuringLoadResource=TriggerDuringLoad01 +ProjectileTriggerDuringLoadComponent=MediumAutoCannonTriggerDuringLoadComponent +# +ProjectileMisfireResource=AutoCannonMisfire01 +ProjectileMisfireComponent=MediumAutoCannonMisfireComponent +ProjectileMisfireSequence=MediumAutoCannonMisfireSequence +# +ProjectileJamResource=AutoCannonJam01 +ProjectileJamComponent=MediumAutoCannonJamComponent +ProjectileJamSequence=MediumAutoCannonJamSequence + +[include] +file=audio\prjcmp.scp + diff --git a/CONTENT/BT/AUDIO/MACROS.SCP b/CONTENT/BT/AUDIO/MACROS.SCP new file mode 100644 index 0000000..a5d19d7 --- /dev/null +++ b/CONTENT/BT/AUDIO/MACROS.SCP @@ -0,0 +1,174 @@ +# +################################################################### +# Macros Audio Script +################################################################### +# + +# +################################################################### +# Compiled symbols +################################################################### +# +[include] +file=audio\symbols.scp + +# +################################################################### +# Boolean types +################################################################### +# +[macro] +True=1 +False=0 + +# +################################################################### +# Motion types and values +################################################################### +# +[macro] +LinearMotionType=0 +AngularMotionType=1 +XMotionValue=0 +YMotionValue=1 +ZMotionValue=2 +LengthMotionValue=3 + +# +################################################################### +# Simulation Sample Rates +################################################################### +# +[macro] +Sample2Sec=30 +Sample1Sec=15 +Sample0.5Sec=7 +Sample0.25Sec=4 + +# +################################################################### +# Internal Volume levels +################################################################### +# +[macro] +################################################################### +EngineWindUpVolume=0.9 +IdleMotorVolume=0.6 +MotorVolume=0.95 +AccelerationMotorVolume=1.0 +DamagedMotorVolume=0.9 +# +ShiftVolume=0.85 +FootFallVolume=1.0 +TorsoTwistStartVolume=0.8 +TorsoTwistStopVolume=0.85 +# +CollisionVolume=0.95 +# +DeathVolume=0.9 +TranslocationVolume=0.7 +################################################################### +LaserFireVolume=1.0 +LaserSustainVolume=0.85 +LaserReleaseVolume=0.85 +LaserChargeVolume=1.0 +LaserLoadedVolume=0.9 +LaserTriggerDuringLoadVolume=0.7 +LaserMisfireVolume=0.9 +# +LaserExplosionVolume=0.7 +LaserExplosionIntVolume=0.9 +# +PPCExplosionVolume=0.7 +PPCExplosionIntVolume=0.9 +################################################################### +AmmoBinEjectingVolume=1.0 +AmmoBinEjectedVolume=0.95 +AmmoBinDumpedVolume=1.0 +# +MissileFireVolume=1.0 +MissileLoadingVolume=0.65 +MissileLoadedVolume=0.9 +MissileTriggerDuringLoadVolume=0.7 +MissileMisfireVolume=0.9 +MissileJamVolume=1.0 +# +MissileTravelVolume=0.7 +MissileExplosionVolume=0.8 +MissileExplosionIntVolume=1.0 +################################################################### +ProjectileFireVolume=0.7 +ProjectileLaunchVolume=0.6 +ProjectileLoadingVolume=0.65 +ProjectileLoadedVolume=0.9 +ProjectileTriggerDuringLoadVolume=0.7 +ProjectileMisfireVolume=0.9 +ProjectileJamVolume=1.0 +# +ProjectileTravelVolume=0.8 +ProjectileExplosionVolume=0.8 +ProjectileExplosionIntVolume=0.9 +# +MachineGunExplosionVolume=0.7 +# +SmallAutoCannonFireVolume=0.75 +SmallAutoCannonLaunchVolume=0.65 +MediumAutoCannonFireVolume=0.85 +MediumAutoCannonLaunchVolume=0.75 +LargeAutoCannonFireVolume=0.95 +LargeAutoCannonLaunchVolume=0.85 +################################################################### +SubsystemDestroyedVolume=1.0 +# +HeatManagementVolume=0.85 +ToggleCoolingVolume=0.85 +CoolantLeakVolume=0.95 +CoolantPressureVolume=0.9 +CoolantDumpVolume=0.9 +# +IncomingAlarmVolume=1.0 +WarningVolume=0.97 +# +GeneratorOnVolume=0.85 +SelectGeneratorVolume=0.85 +GeneratorModeVolume=0.85 +# +ConfigureMappablesVolume=0.85 +ViewSwitchVolume=0.65 +DuckVolume=0.9 +DisplayModeVolume=0.85 +EngineeringDisplayVolume=0.9 +EngineeringExitVolume=0.85 +MyomerSeekLevelVolume=0.75 +LaserSeekLevelVolume=0.75 +HotBoxVolume=0.9 + +# +################################################################### +# External Volume levels +################################################################### +# +[macro] +MyomerServoVolume=0.6 +FootFallExternalVolume=0.95 +TorsoTwistExternalVolume=0.5 +CollisionExternalVolume=0.95 +CoolantDumpExternalVolume=0.85 +# +DamageBurnAVolume=0.6 +DamageBurnBVolume=0.5 +DamageBurnCVolume=0.9 +# +MechExplosionExternalVolume=1.0 +MechFireExternalVolume=0.95 +# +CrunchExplosionVolume=0.85 +SmallExplosionVolume=0.75 +SmallFireVolume=0.6 +MediumExplosionVolume=0.8 +BigExplosionVolume=0.9 +# +LaserExternalSustainVolume=0.8 +AutoCannonExtLaunchVolume=0.8 +# +WindVolume=0.35 diff --git a/CONTENT/BT/AUDIO/MACTRG.SCP b/CONTENT/BT/AUDIO/MACTRG.SCP new file mode 100644 index 0000000..98186fd --- /dev/null +++ b/CONTENT/BT/AUDIO/MACTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Mech AutoCannon Internal Audio Script +################################################################### +# + +[include] +file=audio\prjtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/MAD1EXT.SCP b/CONTENT/BT/AUDIO/MAD1EXT.SCP new file mode 100644 index 0000000..8459cf5 --- /dev/null +++ b/CONTENT/BT/AUDIO/MAD1EXT.SCP @@ -0,0 +1,55 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC25_1 component +# +[include] +file=audio\acncmpe.scp + +# AFC25_1 watcher +[macro] +MechSubsystem=AFC25_1 +[include] +file=audio\acntrge.scp + +# AFC25_2 watcher +[macro] +MechSubsystem=AFC25_2 +[include] +file=audio\acntrge.scp + +# +# MLaser1 component +# +[include] +file=audio\glrcmpe.scp + +# MLaser1 watcher +[macro] +MechSubsystem=MLaser1 +[include] +file=audio\glrtrge.scp + +# MLaser2 watcher +[macro] +MechSubsystem=MLaser2 +[include] +file=audio\glrtrge.scp + +# MLaser3 watcher +[macro] +MechSubsystem=MLaser3 +[include] +file=audio\glrtrge.scp + +# MLaser4 watcher +[macro] +MechSubsystem=MLaser4 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/MAD1INT.SCP b/CONTENT/BT/AUDIO/MAD1INT.SCP new file mode 100644 index 0000000..5f9fadf --- /dev/null +++ b/CONTENT/BT/AUDIO/MAD1INT.SCP @@ -0,0 +1,103 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC25_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC25_1 watcher +[macro] +MechSubsystem=AmmoBinAFC25_1 +[include] +file=audio\abntrg.scp + +# +# AFC25_1 component +# +[include] +file=audio\saccmp.scp + +# AFC25_1 watcher +[macro] +MechSubsystem=AFC25_1 +[include] +file=audio\sactrg.scp + +# AmmoBinAFC25_2 watcher +[macro] +MechSubsystem=AmmoBinAFC25_2 +[include] +file=audio\abntrg.scp + +# AFC25_2 watcher +[macro] +MechSubsystem=AFC25_2 +[include] +file=audio\sactrg.scp + +# +# MLaser1 component +# +[include] +file=audio\mlrcmp.scp + +# MLaser1 watcher +[macro] +MechSubsystem=MLaser1 +[include] +file=audio\mlrtrg.scp + +# MLaser2 watcher +[macro] +MechSubsystem=MLaser2 +[include] +file=audio\mlrtrg.scp + +# MLaser3 watcher +[macro] +MechSubsystem=MLaser3 +[include] +file=audio\mlrtrg.scp + +# MLaser4 watcher +[macro] +MechSubsystem=MLaser4 +[include] +file=audio\mlrtrg.scp + +# AmmoBinLRM10_1 watcher +[macro] +MechSubsystem=AmmoBinLRM10_1 +[include] +file=audio\abntrg.scp + +# +# LRM10_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM10_1 watcher +[macro] +MechSubsystem=LRM10_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM10_2 watcher +[macro] +MechSubsystem=AmmoBinLRM10_2 +[include] +file=audio\abntrg.scp + +# LRM10_2 watcher +[macro] +MechSubsystem=LRM10_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/MAD2EXT.SCP b/CONTENT/BT/AUDIO/MAD2EXT.SCP new file mode 100644 index 0000000..e15cc17 --- /dev/null +++ b/CONTENT/BT/AUDIO/MAD2EXT.SCP @@ -0,0 +1,43 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# ERPPC component +# +[include] +file=audio\glrcmpe.scp + +# ERPPC watcher +[macro] +MechSubsystem=ERPPC +[include] +file=audio\glrtrge.scp + +# +# AFC50 component +# +[include] +file=audio\acncmpe.scp + +# AFC50 watcher +[macro] +MechSubsystem=AFC50 +[include] +file=audio\acntrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/MAD2INT.SCP b/CONTENT/BT/AUDIO/MAD2INT.SCP new file mode 100644 index 0000000..c151e41 --- /dev/null +++ b/CONTENT/BT/AUDIO/MAD2INT.SCP @@ -0,0 +1,109 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# ERPPC component +# +[include] +file=audio\eppcmp.scp + +# ERPPC watcher +[macro] +MechSubsystem=ERPPC +[include] +file=audio\epptrg.scp + +# +# AmmoBinAFC50 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC50 watcher +[macro] +MechSubsystem=AmmoBinAFC50 +[include] +file=audio\abntrg.scp + +# +# AFC50 component +# +[include] +file=audio\maccmp.scp + +# AFC50 watcher +[macro] +MechSubsystem=AFC50 +[include] +file=audio\mactrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# AmmoBinLRM15 watcher +[macro] +MechSubsystem=AmmoBinLRM15 +[include] +file=audio\abntrg.scp + +# +# LRM15 component +# +[include] +file=audio\lrmcmp.scp + +# LRM15 watcher +[macro] +MechSubsystem=LRM15 +[include] +file=audio\lrmtrg.scp + +# AmmoBinSRM6_1 watcher +[macro] +MechSubsystem=AmmoBinSRM6_1 +[include] +file=audio\abntrg.scp + +# +# SRM6_1 component +# +[include] +file=audio\srmcmp.scp + +# SRM6_1 watcher +[macro] +MechSubsystem=SRM6_1 +[include] +file=audio\srmtrg.scp + +# AmmoBinSRM6_2 watcher +[macro] +MechSubsystem=AmmoBinSRM6_2 +[include] +file=audio\abntrg.scp + +# SRM6_2 watcher +[macro] +MechSubsystem=SRM6_2 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/MADEXT.SCP b/CONTENT/BT/AUDIO/MADEXT.SCP new file mode 100644 index 0000000..8d9c8c3 --- /dev/null +++ b/CONTENT/BT/AUDIO/MADEXT.SCP @@ -0,0 +1,43 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC100 component +# +[include] +file=audio\acncmpe.scp + +# AFC100 watcher +[macro] +MechSubsystem=AFC100 +[include] +file=audio\acntrge.scp + +# +# ERLLaser component +# +[include] +file=audio\glrcmpe.scp + +# ERLLaser watcher +[macro] +MechSubsystem=ERLLaser +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/MADINT.SCP b/CONTENT/BT/AUDIO/MADINT.SCP new file mode 100644 index 0000000..06e2b89 --- /dev/null +++ b/CONTENT/BT/AUDIO/MADINT.SCP @@ -0,0 +1,91 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC100 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC100 watcher +[macro] +MechSubsystem=AmmoBinAFC100 +[include] +file=audio\abntrg.scp + +# +# AFC100 component +# +[include] +file=audio\laccmp.scp + +# AFC100 watcher +[macro] +MechSubsystem=AFC100 +[include] +file=audio\lactrg.scp + +# +# ERLLaser component +# +[include] +file=audio\erlcmp.scp + +# ERLLaser watcher +[macro] +MechSubsystem=ERLLaser +[include] +file=audio\erltrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# AmmoBinLRM15_1 watcher +[macro] +MechSubsystem=AmmoBinLRM15_1 +[include] +file=audio\abntrg.scp + +# +# LRM15_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM15_1 watcher +[macro] +MechSubsystem=LRM15_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM15_2 watcher +[macro] +MechSubsystem=AmmoBinLRM15_2 +[include] +file=audio\abntrg.scp + +# LRM15_2 watcher +[macro] +MechSubsystem=LRM15_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/MBNEXP.SCP b/CONTENT/BT/AUDIO/MBNEXP.SCP new file mode 100644 index 0000000..811e7fb --- /dev/null +++ b/CONTENT/BT/AUDIO/MBNEXP.SCP @@ -0,0 +1,119 @@ +# +################################################################### +# Medium Burning Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.5 +name=OriginLocation + +# +################################################################### +# MediumExplosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=AuxExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=MediumExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=MediumExplosionComponent + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=MediumExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-200 +max_value=200 +name=MediumExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=MediumExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.7 +max_value=1.0 +name=MediumExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=MediumExplosionPitchSampleAndHold +audio_component=MediumExplosionBrightnessSampleAndHold +audio_component=MediumExplosionComponent +name=MediumExplosionSplitter + +[AudioControlSequence] +audio_component=MediumExplosionSplitter +tempo=160 +midi_file=audio\medexp01.mid +is_looped=False +dump_value=False +name=MediumExplosionSequence + +[AudioIdleWatcher] +audio_component=MediumExplosionSequence + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=MediumExplosionSequence +control_ID=StartAudioControlID +control_value=0.0 + +# +################################################################### +# SmallFire component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=SmallFireLoop01 +priority=0 +mix_presence=3 +volume_mix_level=SmallFireVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=SmallFireComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=SmallFireComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/MCHEXP03.MID b/CONTENT/BT/AUDIO/MCHEXP03.MID new file mode 100644 index 0000000000000000000000000000000000000000..027d7c3ac6c2b774fcd75e213078d717f90528ae GIT binary patch literal 155 zcmY+-u?m7v7(n53&7wExwg^rAsHktCxC;diwupm+(AL!U!=8dIp-O==2` h6O1Y&42Zm_;0r>CA-(_r literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MCHEXP05.MID b/CONTENT/BT/AUDIO/MCHEXP05.MID new file mode 100644 index 0000000000000000000000000000000000000000..70d989ee2e4995c9eb721e20e7094a579ed2a171 GIT binary patch literal 155 zcmXZVu?m7v7>42Zm_26LZXna0i z_}YG+fDML#d)wcxUVGd*41;Kky9D0uv|7JExPpH$;SL5~v34<(`q-72N~OZ&9yyFE nBMd47WPZvpjdsm1Ugi=Kl>}b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`ibE+R;_^;0ZRp7$# zUy+f4VS-$JfE)vZL46~S0Ry9by@ovlqaKi>$H0(KuNGI&l)#`C$H1gh-^gWO&!ofP R=Tt9Z&(Ip+1T<2g0RTZ@8r}c^ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MCHEXP07.MID b/CONTENT/BT/AUDIO/MCHEXP07.MID new file mode 100644 index 0000000000000000000000000000000000000000..fc6d6429dbdda6635cd055efd60b9f6dc5049226 GIT binary patch literal 108 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`ibE+R;_^;0ZRba~S zUy+f4VS-$Jg&YHeL4Ab*1A|_Dg&qS#LVZO71A|U|g$@IQeSL*J1A|k2Yl;)l41ERw Db@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz99K Zzak?8!vwkd067K*q54SzLO@me3;>3Y5jy|? literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MCHEXPI2.MID b/CONTENT/BT/AUDIO/MCHEXPI2.MID new file mode 100644 index 0000000000000000000000000000000000000000..98696d61ff1a12ca83607e2ab27d692a5e651bbb GIT binary patch literal 80 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+p+J$5 Yq0wZ5VSSU1Ap?VU{R9(jpgMg90J@eE$^ZZW literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MCHEXPI3.MID b/CONTENT/BT/AUDIO/MCHEXPI3.MID new file mode 100644 index 0000000000000000000000000000000000000000..b5e133c0a40f98640d609a75769e32abf9a6c1f7 GIT binary patch literal 73 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8Y0 Uzak?;OT>iu`aX_$paOjc06_#1l>h($ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MCHEXT.SCP b/CONTENT/BT/AUDIO/MCHEXT.SCP new file mode 100644 index 0000000..ec6131e --- /dev/null +++ b/CONTENT/BT/AUDIO/MCHEXT.SCP @@ -0,0 +1,29 @@ +# +################################################################### +# Mech External Audio Script +################################################################### +# + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.25 +name=OriginLocation + +# +################################################################### +# Includes +################################################################### +# + +[include] +file=audio\fotext.scp +file=audio\shfext.scp +file=audio\trsext.scp +file=audio\colext.scp +file=audio\hetext.scp diff --git a/CONTENT/BT/AUDIO/MCHFRE01.MID b/CONTENT/BT/AUDIO/MCHFRE01.MID new file mode 100644 index 0000000000000000000000000000000000000000..07dff85e16d1e73ee8e466e27687cf689895d76e GIT binary patch literal 80 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+p+J$5 Xp<7{sZpsb?T?Pg pitch +# + +[AudioSampleAndHold] +audio_component=MediumExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-200 +max_value=200 +name=MediumExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=MediumExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.7 +max_value=1.0 +name=MediumExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=MediumExplosionPitchSampleAndHold +audio_component=MediumExplosionBrightnessSampleAndHold +audio_component=MediumExplosionComponent +name=MediumExplosionSplitter + +[AudioControlSequence] +audio_component=MediumExplosionSplitter +tempo=160 +midi_file=audio\medexp01.mid +is_looped=False +dump_value=False +name=MediumExplosionSequence + +[AudioIdleWatcher] +audio_component=MediumExplosionSequence + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=MediumExplosionSequence +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/MEDEXP01.MID b/CONTENT/BT/AUDIO/MEDEXP01.MID new file mode 100644 index 0000000000000000000000000000000000000000..11a2d663bbb6595878a3adb3ffdf0e5e06809b13 GIT binary patch literal 78 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz99K Zzak?8!vxp*6jufY resource select +# + +[AudioSampleAndHold] +audio_component=MachineGunExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=MachineGunExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=MachineGunExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=MachineGunExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=MachineGunExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=MachineGunExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=MachineGunExplosionSampleAndHold +audio_component=MachineGunExplosionPitchSampleAndHold +audio_component=MachineGunExplosionBrightnessSampleAndHold +name=MachineGunExplosionSplitter + +[AudioControlSend] +audio_component=MachineGunExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=MachineGunExplosionComponent +control_ID=StartAudioControlID +control_value=1.0 + diff --git a/CONTENT/BT/AUDIO/MGNEXPC.SCP b/CONTENT/BT/AUDIO/MGNEXPC.SCP new file mode 100644 index 0000000..1934bc6 --- /dev/null +++ b/CONTENT/BT/AUDIO/MGNEXPC.SCP @@ -0,0 +1,108 @@ +# +################################################################### +# MachineGun Craft Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# MachineGun Explosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=MachineGunExpCraft01 +priority=0 +mix_presence=3 +volume_mix_level=MachineGunExplosionCraftVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=MachineGunExplosionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=MachineGunExplosionComponent +audio_resource_index=MachineGunExpCraftIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=MachineGunExplosionResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=MachineGunExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=MachineGunExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=MachineGunExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=MachineGunExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=MachineGunExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=MachineGunExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=MachineGunExplosionSampleAndHold +audio_component=MachineGunExplosionPitchSampleAndHold +audio_component=MachineGunExplosionBrightnessSampleAndHold +name=MachineGunExplosionSplitter + +[AudioControlSend] +audio_component=MachineGunExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=MachineGunExplosionComponent +control_ID=StartAudioControlID +control_value=1.0 + diff --git a/CONTENT/BT/AUDIO/MGNTRG.SCP b/CONTENT/BT/AUDIO/MGNTRG.SCP new file mode 100644 index 0000000..ed61292 --- /dev/null +++ b/CONTENT/BT/AUDIO/MGNTRG.SCP @@ -0,0 +1,74 @@ +# +################################################################### +# Mech AutoCannon Internal Audio Script +################################################################### +# + +# +################################################################### +# Projectile Internal Audio Script +################################################################### +# + +# +################################################################### +# Projectile Fire component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileFireComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=2.0 +dump_value=False + +# +################################################################### +# Projectile Misfire component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileMisfireComponent +trigger_state=MechWeapon::Misfire +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# Projectile Jam component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileJamComponent +trigger_state=ProjectileWeapon::TriggerDuringJam +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# Projectile Eject component +################################################################### +# + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=ProjectileWeapon::EjectAmmoMessageID +audio_component=ProjectileEjectComponent +control_ID=StartAudioControlID +control_value=0.5 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/MLRCMP.SCP b/CONTENT/BT/AUDIO/MLRCMP.SCP new file mode 100644 index 0000000..368b9d0 --- /dev/null +++ b/CONTENT/BT/AUDIO/MLRCMP.SCP @@ -0,0 +1,49 @@ +# +################################################################### +# Medium Laser Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserBFire01 +LaserFirePitchOffset=0 +LaserFireComponent=MediumLaserFireComponent +LaserFireIndex=LaserBFireIndex +LaserFireResourceSelect=MediumLaserFireResourceSelect +LaserFireSampleAndHold=MediumLaserFireSampleAndHold +# +LaserSustainResource=LaserBSustain01 +LaserSustainComponent=MediumLaserSustainComponent +LaserSustainIndex=LaserBSustainIndex +LaserSustainResourceSelect=MediumLaserSustainResourceSelect +LaserSustainSampleAndHold=MediumLaserSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=MediumLaserReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=MediumLaserReleaseResourceSelect +LaserReleaseSampleAndHold=MediumLaserReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=MediumLaserChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=MediumLaserChargeResourceSelect +LaserChargeSampleAndHold=MediumLaserChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=MediumLaserLoadedComponent +LaserLoadedSequence=MediumLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=MediumLaserTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=MediumLaserMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=MediumLaserSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + + diff --git a/CONTENT/BT/AUDIO/MLRCMPE.SCP b/CONTENT/BT/AUDIO/MLRCMPE.SCP new file mode 100644 index 0000000..859f7a8 --- /dev/null +++ b/CONTENT/BT/AUDIO/MLRCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# Medium Laser External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserBSustainExt01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=0 +LaserSustainComponent=MediumLaserExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/MLRTRG.SCP b/CONTENT/BT/AUDIO/MLRTRG.SCP new file mode 100644 index 0000000..645da98 --- /dev/null +++ b/CONTENT/BT/AUDIO/MLRTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Medium Laser Internal Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/MLRTRGE.SCP b/CONTENT/BT/AUDIO/MLRTRGE.SCP new file mode 100644 index 0000000..3b64622 --- /dev/null +++ b/CONTENT/BT/AUDIO/MLRTRGE.SCP @@ -0,0 +1,9 @@ +# +################################################################### +# Laser External Triggers +################################################################### +# + +[include] +file=audio\lsrtrge.scp + diff --git a/CONTENT/BT/AUDIO/MSLCMP.SCP b/CONTENT/BT/AUDIO/MSLCMP.SCP new file mode 100644 index 0000000..11f8ba9 --- /dev/null +++ b/CONTENT/BT/AUDIO/MSLCMP.SCP @@ -0,0 +1,171 @@ +# +################################################################### +# Mech Missile Audio Script +################################################################### +# + +# +################################################################### +# Missile Fire component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=MissileFireResource +position=RearDirectPatchPosition +priority=3 +mix_presence=3 +volume_mix_level=MissileFireVolume +pitch_mix_offset=MissileFirePitchOffset +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=MissileFireComponent + +# +################################################################### +# Missile Loading component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=MissileLoadingResource +position=RearDirectPatchPosition +priority=1 +mix_presence=0 +volume_mix_level=MissileLoadingVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=MissileLoadingComponent + +# +################################################################### +# Missile Loaded component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=MissileLoadedResource +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=MissileLoadedVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=MissileLoadedComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=MissileLoadedComponent +tempo=160 +midi_file=audio\prjldd01.mid +is_looped=False +dump_value=False +name=MissileLoadedSequence + +[AudioIdleWatcher] +audio_component=MissileLoadedSequence + +# +################################################################### +# Missile TriggerDuringLoad component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=MissileTriggerDuringLoadResource +position=FrontDirectPatchPosition +priority=2 +mix_presence=0 +volume_mix_level=MissileTriggerDuringLoadVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=MissileTriggerDuringLoadComponent + +# +################################################################### +# Missile Misfire component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=MissileMisfireResource +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=MissileMisfireVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=MissileMisfireComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=MissileMisfireComponent +tempo=160 +midi_file=audio\mslmfr01.mid +is_looped=False +dump_value=False +name=MissileMisfireSequence + +[AudioIdleWatcher] +audio_component=MissileMisfireSequence + +# +################################################################### +# Missile Jam component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=MissileJamResource +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=MissileJamVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=MissileJamComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=MissileJamComponent +tempo=160 +midi_file=audio\mslldd01.mid +is_looped=False +dump_value=False +name=MissileJamSequence + +[AudioIdleWatcher] +audio_component=MissileJamSequence + diff --git a/CONTENT/BT/AUDIO/MSLEXP.SCP b/CONTENT/BT/AUDIO/MSLEXP.SCP new file mode 100644 index 0000000..ddf2458 --- /dev/null +++ b/CONTENT/BT/AUDIO/MSLEXP.SCP @@ -0,0 +1,108 @@ +# +################################################################### +# Missile Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Missile Explosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=BigExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=MissileExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=MissileExplosionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=MissileExplosionComponent +audio_resource_index=MissileExplosionIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=MissileExplosionResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=MissileExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=MissileExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=MissileExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=MissileExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=MissileExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=MissileExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=MissileExplosionSampleAndHold +audio_component=MissileExplosionPitchSampleAndHold +audio_component=MissileExplosionBrightnessSampleAndHold +name=MissileExplosionSplitter + +[AudioControlSend] +audio_component=MissileExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=MissileExplosionComponent +control_ID=StartAudioControlID +control_value=5.0 + diff --git a/CONTENT/BT/AUDIO/MSLEXPI.SCP b/CONTENT/BT/AUDIO/MSLEXPI.SCP new file mode 100644 index 0000000..ad3573b --- /dev/null +++ b/CONTENT/BT/AUDIO/MSLEXPI.SCP @@ -0,0 +1,109 @@ +# +################################################################### +# Missile Internal Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Missile Internal Explosion component +################################################################### +# + +[Static3DPatchSource] +location=OriginLocation +resource=BigExplosionInt01 +priority=2 +mix_presence=3 +volume_mix_level=MissileExplosionIntVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +use_internal=False +name=MissileExplosionIntComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=MissileExplosionIntComponent +audio_resource_index=MissileExplosionIntIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=MissileExplosionIntResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=MissileExplosionIntResourceSelect +control_ID=100 +sample_duration=99.0 +name=MissileExplosionIntSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=MissileExplosionIntComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=MissileExplosionIntPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=MissileExplosionIntComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=MissileExplosionIntBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=MissileExplosionIntSampleAndHold +audio_component=MissileExplosionIntPitchSampleAndHold +audio_component=MissileExplosionIntBrightnessSampleAndHold +name=MissileExplosionIntSplitter + +[AudioControlSend] +audio_component=MissileExplosionIntSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=MissileExplosionIntComponent +control_ID=StartAudioControlID +control_value=5.0 + diff --git a/CONTENT/BT/AUDIO/MSLJAM01.MID b/CONTENT/BT/AUDIO/MSLJAM01.MID new file mode 100644 index 0000000000000000000000000000000000000000..2752b7611306049d18c6fe698ca9d183ac8c4cc4 GIT binary patch literal 77 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8k4 Yzak?8!vvN36cq-Bkot-cpdx(+0D9{Yv;Y7A literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MSLLDD01.MID b/CONTENT/BT/AUDIO/MSLLDD01.MID new file mode 100644 index 0000000000000000000000000000000000000000..d360727fd6054890c1aa1873afb2cc2120351e2a GIT binary patch literal 77 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8k4 Yzak?8!vvN33Ka&1kot-cpdx(+0DJEd$N&HU literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MSLMFR01.MID b/CONTENT/BT/AUDIO/MSLMFR01.MID new file mode 100644 index 0000000000000000000000000000000000000000..38680b034fd2a06736e68bb7251f109e45fe9d77 GIT binary patch literal 78 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz99K Zzak?8!vvN36cq-Bkorc25TGi31^|p*5#9g* literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/MSLTRG.SCP b/CONTENT/BT/AUDIO/MSLTRG.SCP new file mode 100644 index 0000000..82130d8 --- /dev/null +++ b/CONTENT/BT/AUDIO/MSLTRG.SCP @@ -0,0 +1,111 @@ +# +################################################################### +# Missile Internal Audio Script +################################################################### +# + +# +################################################################### +# Missile Fire trigger +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=MissileFireComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=2.5 +dump_value=False + +# +################################################################### +# Missile Loading trigger +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=MissileLoadingComponent +trigger_state=MechWeapon::Loading +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=MissileLoadingComponent +trigger_state=MechWeapon::Loading +inverse_trigger=True +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Missile Loaded component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=MissileLoadedSequence +trigger_state=MechWeapon::Loaded +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Missile TriggerDuringLoad trigger +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=MissileTriggerDuringLoadComponent +trigger_state=MechWeapon::TriggerDuringLoad +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# Missile Misfire trigger +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=MissileMisfireSequence +trigger_state=MechWeapon::Misfire +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Missile Jam component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=MissileJamSequence +trigger_state=ProjectileWeapon::TriggerDuringJam +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False diff --git a/CONTENT/BT/AUDIO/MSLTVL.SCP b/CONTENT/BT/AUDIO/MSLTVL.SCP new file mode 100644 index 0000000..806d858 --- /dev/null +++ b/CONTENT/BT/AUDIO/MSLTVL.SCP @@ -0,0 +1,46 @@ +# +################################################################### +# Missile Travel Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Missile Travel component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=MissileTravel01 +priority=0 +mix_presence=0 +volume_mix_level=MissileTravelVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=MissileTravelComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=MissileTravelComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/MYRCMP.SCP b/CONTENT/BT/AUDIO/MYRCMP.SCP new file mode 100644 index 0000000..0fb4b03 --- /dev/null +++ b/CONTENT/BT/AUDIO/MYRCMP.SCP @@ -0,0 +1,27 @@ +# +################################################################### +# Myomer Audio Script +################################################################### +# + +# +################################################################### +# MyomerSeekLevel component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=BasicBeep02 +position=FrontDirectPatchPosition +priority=3 +mix_presence=0 +volume_mix_level=MyomerSeekLevelVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=MyomerSeekLevelComponent + diff --git a/CONTENT/BT/AUDIO/MYRTRG.SCP b/CONTENT/BT/AUDIO/MYRTRG.SCP new file mode 100644 index 0000000..9dcd99e --- /dev/null +++ b/CONTENT/BT/AUDIO/MYRTRG.SCP @@ -0,0 +1,31 @@ +# +################################################################### +# Myomer Audio Script +################################################################### +# + +# +################################################################### +# Includes +################################################################### +# + +[include] +file=audio\buttrg.scp +file=audio\dsttrg.scp +file=audio\clttrg.scp + +# +################################################################### +# MyomerSeekLevel component +################################################################### +# + +[AudioControlsButtonMessageWatcher] +subsystem=MechSubsystem +message_ID=Myomers::ToggleSeekVoltageMessageID +audio_component=MyomerSeekLevelComponent +control_ID=StartAudioControlID +control_value=0.5 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/OWN1EXT.SCP b/CONTENT/BT/AUDIO/OWN1EXT.SCP new file mode 100644 index 0000000..1a1409d --- /dev/null +++ b/CONTENT/BT/AUDIO/OWN1EXT.SCP @@ -0,0 +1,37 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC25 component +# +[include] +file=audio\acncmpe.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\acntrge.scp + +# +# ERMLaser component +# +[include] +file=audio\glrcmpe.scp + +# ERMLaser watcher +[macro] +MechSubsystem=ERMLaser +[include] +file=audio\glrtrge.scp + +# ERSLaser watcher +[macro] +MechSubsystem=ERSLaser +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/OWN1INT.SCP b/CONTENT/BT/AUDIO/OWN1INT.SCP new file mode 100644 index 0000000..6ef9a50 --- /dev/null +++ b/CONTENT/BT/AUDIO/OWN1INT.SCP @@ -0,0 +1,85 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC25 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC25 watcher +[macro] +MechSubsystem=AmmoBinAFC25 +[include] +file=audio\abntrg.scp + +# +# AFC25 component +# +[include] +file=audio\saccmp.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\sactrg.scp + +# +# ERMLaser component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser watcher +[macro] +MechSubsystem=ERMLaser +[include] +file=audio\ermtrg.scp + +# +# ERSLaser component +# +[include] +file=audio\erscmp.scp + +# ERSLaser watcher +[macro] +MechSubsystem=ERSLaser +[include] +file=audio\erstrg.scp + +# AmmoBinNRK5_1 watcher +[macro] +MechSubsystem=AmmoBinNRK5_1 +[include] +file=audio\abntrg.scp + +# +# NRK5_1 component +# +[include] +file=audio\lrmcmp.scp + +# NRK5_1 watcher +[macro] +MechSubsystem=NRK5_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinNRK5_2 watcher +[macro] +MechSubsystem=AmmoBinNRK5_2 +[include] +file=audio\abntrg.scp + +# NRK5_2 watcher +[macro] +MechSubsystem=NRK5_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/OWNEXT.SCP b/CONTENT/BT/AUDIO/OWNEXT.SCP new file mode 100644 index 0000000..0caf0f3 --- /dev/null +++ b/CONTENT/BT/AUDIO/OWNEXT.SCP @@ -0,0 +1,49 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\glrtrge.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/OWNINT.SCP b/CONTENT/BT/AUDIO/OWNINT.SCP new file mode 100644 index 0000000..38e8726 --- /dev/null +++ b/CONTENT/BT/AUDIO/OWNINT.SCP @@ -0,0 +1,91 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\erstrg.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\erstrg.scp + +# +# AmmoBinSRM6_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinSRM6_1 watcher +[macro] +MechSubsystem=AmmoBinSRM6_1 +[include] +file=audio\abntrg.scp + +# +# SRM6_1 component +# +[include] +file=audio\srmcmp.scp + +# SRM6_1 watcher +[macro] +MechSubsystem=SRM6_1 +[include] +file=audio\srmtrg.scp + +# AmmoBinSRM6_2 watcher +[macro] +MechSubsystem=AmmoBinSRM6_2 +[include] +file=audio\abntrg.scp + +# SRM6_2 watcher +[macro] +MechSubsystem=SRM6_2 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/PLYINT.SCP b/CONTENT/BT/AUDIO/PLYINT.SCP new file mode 100644 index 0000000..8247fcd --- /dev/null +++ b/CONTENT/BT/AUDIO/PLYINT.SCP @@ -0,0 +1,88 @@ +# +################################################################### +# BT Player audio script +################################################################### +# + +# +################################################################### +# Includes +################################################################### +# +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Translocation component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=Translocation01 +position=FrontDirectPatchPosition +priority=4 +mix_presence=1 +volume_mix_level=TranslocationVolume +pitch_mix_offset=0.0 +brightness_mix_level=0.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=5.0 +name=TranslocationComponent01 + +[DirectPatchSource] +location=OriginLocation +resource=Translocation01 +position=RearDirectPatchPosition +priority=4 +mix_presence=1 +volume_mix_level=TranslocationVolume +pitch_mix_offset=0.0 +brightness_mix_level=0.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=5.0 +name=TranslocationComponent02 + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=TranslocationComponent01 +audio_component=TranslocationComponent02 +name=TranslocationSplitter + +[AudioStateTrigger] +subsystem=Entity +attribute=SimulationState +audio_component=TranslocationSplitter +trigger_state=BTPlayer::MissionStartingState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=5.0 +dump_value=0 + +[AudioStateTrigger] +subsystem=Entity +attribute=SimulationState +audio_component=TranslocationSplitter +trigger_state=BTPlayer::DropZoneAcquiredState +inverse_trigger=False +control_ID=StartAudioControlID +control_value=5.0 +dump_value=0 + + diff --git a/CONTENT/BT/AUDIO/PPCCMP.SCP b/CONTENT/BT/AUDIO/PPCCMP.SCP new file mode 100644 index 0000000..1a84d1f --- /dev/null +++ b/CONTENT/BT/AUDIO/PPCCMP.SCP @@ -0,0 +1,48 @@ +# +################################################################### +# PPC Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserAFire01 +LaserFirePitchOffset=0 +LaserFireComponent=PPCFireComponent +LaserFireIndex=LaserAFireIndex +LaserFireResourceSelect=PPCFireResourceSelect +LaserFireSampleAndHold=PPCFireSampleAndHold +# +LaserSustainResource=LaserASustain01 +LaserSustainComponent=PPCSustainComponent +LaserSustainIndex=LaserASustainIndex +LaserSustainResourceSelect=PPCSustainResourceSelect +LaserSustainSampleAndHold=PPCSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=PPCReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=PPCReleaseResourceSelect +LaserReleaseSampleAndHold=PPCReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=PPCChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=PPCChargeResourceSelect +LaserChargeSampleAndHold=PPCChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=SmallLaserLoadedComponent +LaserLoadedSequence=SmallLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=PPCTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=PPCMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=PPCSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + diff --git a/CONTENT/BT/AUDIO/PPCCMPE.SCP b/CONTENT/BT/AUDIO/PPCCMPE.SCP new file mode 100644 index 0000000..d0619db --- /dev/null +++ b/CONTENT/BT/AUDIO/PPCCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# PPC External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserASustain01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=100 +LaserSustainComponent=PPCExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/PPCEXP.SCP b/CONTENT/BT/AUDIO/PPCEXP.SCP new file mode 100644 index 0000000..207de43 --- /dev/null +++ b/CONTENT/BT/AUDIO/PPCEXP.SCP @@ -0,0 +1,108 @@ +# +################################################################### +# PPC Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# PPC Explosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=PPCExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=PPCExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=PPCExplosionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=PPCExplosionComponent +audio_resource_index=PPCExplosionIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=PPCExplosionResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=PPCExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=PPCExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=PPCExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=PPCExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=PPCExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=PPCExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=PPCExplosionSampleAndHold +audio_component=PPCExplosionPitchSampleAndHold +audio_component=PPCExplosionBrightnessSampleAndHold +name=PPCExplosionSplitter + +[AudioControlSend] +audio_component=PPCExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=PPCExplosionComponent +control_ID=StartAudioControlID +control_value=1.5 + diff --git a/CONTENT/BT/AUDIO/PPCEXPI.SCP b/CONTENT/BT/AUDIO/PPCEXPI.SCP new file mode 100644 index 0000000..1a9b993 --- /dev/null +++ b/CONTENT/BT/AUDIO/PPCEXPI.SCP @@ -0,0 +1,109 @@ +# +################################################################### +# PPC Explosion Internal Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# PPC Explosion Internal component +################################################################### +# + +[Static3DPatchSource] +location=OriginLocation +resource=PPCExplosionInt01 +priority=2 +mix_presence=3 +volume_mix_level=PPCExplosionIntVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +use_internal=False +name=PPCExplosionIntComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=PPCExplosionIntComponent +audio_resource_index=PPCExplosionIntIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=PPCExplosionIntResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=PPCExplosionIntResourceSelect +control_ID=100 +sample_duration=99.0 +name=PPCExplosionIntSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=PPCExplosionIntComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-100 +max_value=100 +name=PPCExplosionIntPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=PPCExplosionIntComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.8 +max_value=1.0 +name=PPCExplosionIntBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=PPCExplosionIntSampleAndHold +audio_component=PPCExplosionIntPitchSampleAndHold +audio_component=PPCExplosionIntBrightnessSampleAndHold +name=PPCExplosionIntSplitter + +[AudioControlSend] +audio_component=PPCExplosionIntSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=PPCExplosionIntComponent +control_ID=StartAudioControlID +control_value=3.0 + diff --git a/CONTENT/BT/AUDIO/PPCTRG.SCP b/CONTENT/BT/AUDIO/PPCTRG.SCP new file mode 100644 index 0000000..042ba9c --- /dev/null +++ b/CONTENT/BT/AUDIO/PPCTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# PPC Internal Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/PPCTRGE.SCP b/CONTENT/BT/AUDIO/PPCTRGE.SCP new file mode 100644 index 0000000..86e97c1 --- /dev/null +++ b/CONTENT/BT/AUDIO/PPCTRGE.SCP @@ -0,0 +1,9 @@ +# +################################################################### +# PPC External Audio Script +################################################################### +# + +[include] +file=audio\lsrtrge.scp + diff --git a/CONTENT/BT/AUDIO/PRGBUT01.MID b/CONTENT/BT/AUDIO/PRGBUT01.MID new file mode 100644 index 0000000000000000000000000000000000000000..75365f383d9ff8f0e88a7c43f862c33ea789c8c5 GIT binary patch literal 77 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`ibE+R;_^;0ZRUpRj UUy+f4VS;f=g)svIgapb00Aec;$p8QV literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/PRJCMP.SCP b/CONTENT/BT/AUDIO/PRJCMP.SCP new file mode 100644 index 0000000..1134dc9 --- /dev/null +++ b/CONTENT/BT/AUDIO/PRJCMP.SCP @@ -0,0 +1,192 @@ +# +################################################################### +# Projectile Internal Audio Script +################################################################### +# + +# +################################################################### +# Projectile Fire component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProjectileFireResource +position=RearDirectPatchPosition +priority=3 +mix_presence=3 +volume_mix_level=ProjectileFireVolume +pitch_mix_offset=ProjectileFirePitchOffset +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=ProjectileFireComponent + +# +################################################################### +# Projectile Launch component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProjectileLaunchResource +position=FrontDirectPatchPosition +priority=3 +mix_presence=3 +volume_mix_level=ProjectileLaunchVolume +pitch_mix_offset=ProjectileLaunchPitchOffset +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=ProjectileLaunchComponent + +# +################################################################### +# Projectile Loading component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProjectileLoadingResource +position=RearDirectPatchPosition +priority=1 +mix_presence=0 +volume_mix_level=ProjectileLoadingVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=ProjectileLoadingComponent + +# +################################################################### +# Projectile Loaded component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProjectileLoadedResource +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=ProjectileLoadedVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=ProjectileLoadedComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=ProjectileLoadedComponent +tempo=160 +midi_file=audio\prjldd01.mid +is_looped=False +dump_value=False +name=ProjectileLoadedSequence + +[AudioIdleWatcher] +audio_component=ProjectileLoadedSequence + +# +################################################################### +# Projectile TriggerDuringLoad component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProjectileTriggerDuringLoadResource +position=FrontDirectPatchPosition +priority=2 +mix_presence=0 +volume_mix_level=ProjectileTriggerDuringLoadVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=ProjectileTriggerDuringLoadComponent + +# +################################################################### +# Projectile Misfire component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProjectileMisfireResource +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=ProjectileMisfireVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=ProjectileMisfireComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=ProjectileMisfireComponent +tempo=160 +midi_file=audio\prjmfr01.mid +is_looped=False +dump_value=False +name=ProjectileMisfireSequence + +[AudioIdleWatcher] +audio_component=ProjectileMisfireSequence + +# +################################################################### +# Projectile Jam component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=ProjectileJamResource +position=RearDirectPatchPosition +priority=3 +mix_presence=2 +volume_mix_level=ProjectileJamVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=True +compression_duration=1.0 +name=ProjectileJamComponent + +#------------------------------------------------------------------ + +[AudioControlSequence] +audio_component=ProjectileJamComponent +tempo=160 +midi_file=audio\prjjam01.mid +is_looped=False +dump_value=False +name=ProjectileJamSequence + +[AudioIdleWatcher] +audio_component=ProjectileJamSequence + diff --git a/CONTENT/BT/AUDIO/PRJCMPE.SCP b/CONTENT/BT/AUDIO/PRJCMPE.SCP new file mode 100644 index 0000000..b7a4f62 --- /dev/null +++ b/CONTENT/BT/AUDIO/PRJCMPE.SCP @@ -0,0 +1,26 @@ +# +################################################################### +# Projectile External Audio Script +################################################################### +# + +# +################################################################### +# Projectile Launch component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=ProjectileLaunchResource +priority=0 +mix_presence=0 +volume_mix_level=ProjectileLaunchVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=ProjectileLaunchComponent + diff --git a/CONTENT/BT/AUDIO/PRJEXP.SCP b/CONTENT/BT/AUDIO/PRJEXP.SCP new file mode 100644 index 0000000..b88fddf --- /dev/null +++ b/CONTENT/BT/AUDIO/PRJEXP.SCP @@ -0,0 +1,108 @@ +# +################################################################### +# Projectile Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Projectile Explosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=MedExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=ProjectileExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=ProjectileExplosionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=ProjectileExplosionComponent +audio_resource_index=ProjectileExplosionIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=ProjectileExplosionResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=ProjectileExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=ProjectileExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=ProjectileExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=ProjectileExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=ProjectileExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=ProjectileExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=ProjectileExplosionSampleAndHold +audio_component=ProjectileExplosionPitchSampleAndHold +audio_component=ProjectileExplosionBrightnessSampleAndHold +name=ProjectileExplosionSplitter + +[AudioControlSend] +audio_component=ProjectileExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=ProjectileExplosionComponent +control_ID=StartAudioControlID +control_value=3.0 + diff --git a/CONTENT/BT/AUDIO/PRJEXPI.SCP b/CONTENT/BT/AUDIO/PRJEXPI.SCP new file mode 100644 index 0000000..556f67e --- /dev/null +++ b/CONTENT/BT/AUDIO/PRJEXPI.SCP @@ -0,0 +1,109 @@ +# +################################################################### +# Projectile Internal Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Projectile Internal Explosion component +################################################################### +# + +[Static3DPatchSource] +location=OriginLocation +resource=MedExplosionInt01 +priority=2 +mix_presence=3 +volume_mix_level=ProjectileExplosionIntVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +use_internal=False +name=ProjectileExplosionIntComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=ProjectileExplosionIntComponent +audio_resource_index=ProjectileExplosionIntIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=ProjectileExplosionIntResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=ProjectileExplosionIntResourceSelect +control_ID=100 +sample_duration=99.0 +name=ProjectileExplosionIntSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=ProjectileExplosionIntComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-400 +max_value=400 +name=ProjectileExplosionIntPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=ProjectileExplosionIntComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.9 +max_value=1.0 +name=ProjectileExplosionIntBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=ProjectileExplosionIntSampleAndHold +audio_component=ProjectileExplosionIntPitchSampleAndHold +audio_component=ProjectileExplosionIntBrightnessSampleAndHold +name=ProjectileExplosionIntSplitter + +[AudioControlSend] +audio_component=ProjectileExplosionIntSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=ProjectileExplosionIntComponent +control_ID=StartAudioControlID +control_value=3.0 + diff --git a/CONTENT/BT/AUDIO/PRJJAM01.MID b/CONTENT/BT/AUDIO/PRJJAM01.MID new file mode 100644 index 0000000000000000000000000000000000000000..46e6904d151e201852f341a2f6d795fce75288f1 GIT binary patch literal 77 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8k4 Yzak?8!vvLj4HX84kot-cpdx(+0C(RJcmMzZ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/PRJLDD01.MID b/CONTENT/BT/AUDIO/PRJLDD01.MID new file mode 100644 index 0000000000000000000000000000000000000000..2752b7611306049d18c6fe698ca9d183ac8c4cc4 GIT binary patch literal 77 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz8k4 Yzak?8!vvN36cq-Bkot-cpdx(+0D9{Yv;Y7A literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/PRJMFR01.MID b/CONTENT/BT/AUDIO/PRJMFR01.MID new file mode 100644 index 0000000000000000000000000000000000000000..d9e76c5e24821331d60a36e0ead8bc4813f06bc8 GIT binary patch literal 78 zcmeYb$w*;fU|?flWME>b@C_--2J$2s{ztH|FiCJQ{EuV;^8W`iv+lUT@L!(+sz99K Zzak?8!vvN302Ky?korc25TGi31^|mi5y}7n literal 0 HcmV?d00001 diff --git a/CONTENT/BT/AUDIO/PRJTRG.SCP b/CONTENT/BT/AUDIO/PRJTRG.SCP new file mode 100644 index 0000000..c2f787a --- /dev/null +++ b/CONTENT/BT/AUDIO/PRJTRG.SCP @@ -0,0 +1,128 @@ +# +################################################################### +# Projectile Internal Audio Script +################################################################### +# + +# +################################################################### +# Projectile Fire component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileFireComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=2.0 +dump_value=False + +# +################################################################### +# Projectile Launch component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileLaunchComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=2.0 +dump_value=False + +# +################################################################### +# Projectile Loading trigger +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileLoadingComponent +trigger_state=MechWeapon::Loading +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileLoadingComponent +trigger_state=MechWeapon::Loading +inverse_trigger=True +control_ID=StopAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Projectile Loaded component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileLoadedSequence +trigger_state=MechWeapon::Loaded +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Projectile TriggerDuringLoad component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileTriggerDuringLoadComponent +trigger_state=MechWeapon::TriggerDuringLoad +inverse_trigger=False +control_ID=StartAudioControlID +control_value=1.0 +dump_value=False + +# +################################################################### +# Projectile Misfire component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileMisfireSequence +trigger_state=MechWeapon::Misfire +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + +# +################################################################### +# Projectile Jam component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileJamSequence +trigger_state=ProjectileWeapon::TriggerDuringJam +inverse_trigger=False +control_ID=StartAudioControlID +control_value=0.0 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/PRJTRGE.SCP b/CONTENT/BT/AUDIO/PRJTRGE.SCP new file mode 100644 index 0000000..87268d9 --- /dev/null +++ b/CONTENT/BT/AUDIO/PRJTRGE.SCP @@ -0,0 +1,23 @@ +# +################################################################### +# Projectile External Audio Script +################################################################### +# + +# +################################################################### +# Projectile Launch component +################################################################### +# + +[AudioStateTrigger] +subsystem=MechSubsystem +attribute=WeaponState +audio_component=ProjectileLaunchComponent +trigger_state=MechWeapon::Firing +inverse_trigger=False +control_ID=StartAudioControlID +control_value=2.0 +dump_value=False + + diff --git a/CONTENT/BT/AUDIO/PRJTVL.SCP b/CONTENT/BT/AUDIO/PRJTVL.SCP new file mode 100644 index 0000000..81f25b0 --- /dev/null +++ b/CONTENT/BT/AUDIO/PRJTVL.SCP @@ -0,0 +1,46 @@ +# +################################################################### +# Projectile Travel Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# Projectile Travel component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=ProjectileATravel01 +priority=0 +mix_presence=0 +volume_mix_level=ProjectileTravelVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=ProjectileTravelComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=ProjectileTravelComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/RAPEXT.SCP b/CONTENT/BT/AUDIO/RAPEXT.SCP new file mode 100644 index 0000000..8aa3f10 --- /dev/null +++ b/CONTENT/BT/AUDIO/RAPEXT.SCP @@ -0,0 +1,37 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# MLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\glrtrge.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\glrtrge.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\glrtrge.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/RAPINT.SCP b/CONTENT/BT/AUDIO/RAPINT.SCP new file mode 100644 index 0000000..057a821 --- /dev/null +++ b/CONTENT/BT/AUDIO/RAPINT.SCP @@ -0,0 +1,91 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# MLaser_1 component +# +[include] +file=audio\mlrcmp.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\mlrtrg.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\mlrtrg.scp + +# +# SLaser_1 component +# +[include] +file=audio\slrcmp.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\slrtrg.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\slrtrg.scp + +# +# AmmoBinLRM5_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinLRM5_1 watcher +[macro] +MechSubsystem=AmmoBinLRM5_1 +[include] +file=audio\abntrg.scp + +# +# LRM5_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM5_1 watcher +[macro] +MechSubsystem=LRM5_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM5_2 watcher +[macro] +MechSubsystem=AmmoBinLRM5_2 +[include] +file=audio\abntrg.scp + +# LRM5_2 watcher +[macro] +MechSubsystem=LRM5_2 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM5_3 watcher +[macro] +MechSubsystem=AmmoBinLRM5_3 +[include] +file=audio\abntrg.scp + +# LRM5_3 watcher +[macro] +MechSubsystem=LRM5_3 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/SACCMP.SCP b/CONTENT/BT/AUDIO/SACCMP.SCP new file mode 100644 index 0000000..18518d9 --- /dev/null +++ b/CONTENT/BT/AUDIO/SACCMP.SCP @@ -0,0 +1,38 @@ +# +################################################################### +# Small AutoCannon Audio Script +################################################################### +# + +[macro] +ProjectileFireResource=AutoCannonAction01 +ProjectileFireVolume=SmallAutoCannonFireVolume +ProjectileFirePitchOffset=200 +ProjectileFireComponent=SmallAutoCannonFireComponent +# +ProjectileLaunchResource=AutoCannonFire01 +ProjectileLaunchVolume=SmallAutoCannonLaunchVolume +ProjectileLaunchPitchOffset=200 +ProjectileLaunchComponent=SmallAutoCannonLaunchComponent +# +ProjectileLoadingResource=AutoCannonLoading01 +ProjectileLoadingComponent=SmallAutoCannonLoadingComponent +# +ProjectileLoadedResource=AutoCannonLoaded01 +ProjectileLoadedComponent=SmallAutoCannonLoadedComponent +ProjectileLoadedSequence=SmallAutoCannonLoadedSequence +# +ProjectileTriggerDuringLoadResource=TriggerDuringLoad01 +ProjectileTriggerDuringLoadComponent=SmallAutoCannonTriggerDuringLoadComponent +# +ProjectileMisfireResource=AutoCannonMisfire01 +ProjectileMisfireComponent=SmallAutoCannonMisfireComponent +ProjectileMisfireSequence=SmallAutoCannonMisfireSequence +# +ProjectileJamResource=AutoCannonJam01 +ProjectileJamComponent=SmallAutoCannonJamComponent +ProjectileJamSequence=SmallAutoCannonJamSequence + +[include] +file=audio\prjcmp.scp + diff --git a/CONTENT/BT/AUDIO/SACTRG.SCP b/CONTENT/BT/AUDIO/SACTRG.SCP new file mode 100644 index 0000000..98186fd --- /dev/null +++ b/CONTENT/BT/AUDIO/SACTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Mech AutoCannon Internal Audio Script +################################################################### +# + +[include] +file=audio\prjtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/SBNEXP.SCP b/CONTENT/BT/AUDIO/SBNEXP.SCP new file mode 100644 index 0000000..573d015 --- /dev/null +++ b/CONTENT/BT/AUDIO/SBNEXP.SCP @@ -0,0 +1,136 @@ +# +################################################################### +# Small Burning Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.5 +name=OriginLocation + +# +################################################################### +# SmallExplosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=SmallExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=SmallExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=SmallExplosionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=SmallExplosionComponent +audio_resource_index=SmallExplosionIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=SmallExplosionResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=SmallExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=SmallExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=SmallExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-200 +max_value=200 +name=SmallExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=SmallExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.7 +max_value=1.0 +name=SmallExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=SmallExplosionSampleAndHold +audio_component=SmallExplosionPitchSampleAndHold +audio_component=SmallExplosionBrightnessSampleAndHold +name=SmallExplosionSplitter + +[AudioControlSend] +audio_component=SmallExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=SmallExplosionComponent +control_ID=StartAudioControlID +control_value=3.0 + +# +################################################################### +# SmallFire component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=SmallFireLoop01 +priority=0 +mix_presence=3 +volume_mix_level=SmallFireVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=SmallFireComponent + +#------------------------------------------------------------------ + +[AudioControlSend] +audio_component=SmallFireComponent +control_ID=StartAudioControlID +control_value=0.0 + diff --git a/CONTENT/BT/AUDIO/SHFEXT.SCP b/CONTENT/BT/AUDIO/SHFEXT.SCP new file mode 100644 index 0000000..30ea140 --- /dev/null +++ b/CONTENT/BT/AUDIO/SHFEXT.SCP @@ -0,0 +1,140 @@ +# +################################################################### +# Mech External Myomer Audio Script +################################################################### +# + +[macro] +MyomerServoTopSpeed=60.0 +MyomerServoDuration=1.5 + +# +################################################################### +# MyomerServo component +################################################################### +# + +[!Dynamic3DPatchSource] +location=OriginLocation +resource=MyomerServo01 +priority=0 +mix_presence=0 +volume_mix_level=MyomerServoVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=MyomerServoComponent + +#------------------------------------------------------------------ + +# +# linear velocity -> pitch +# + +[!AudioMotionScale] +subsystem=Entity +attribute=LocalVelocity +motion_type=0 +motion_value=3 +audio_component=MyomerServoComponent +attribute_value_boundary1=0.0 +attribute_value_boundary2=MyomerServoTopSpeed +control_ID=PitchAudioControlID +control_value_boundary1=-1200 +control_value_boundary2=0 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +# WalkForward + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::RightWalkForwardAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::LeftWalkForwardAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + +# Run + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::RightRunAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::LeftRunAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + +# Reverse + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::RightReverseAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::LeftReverseAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + +# Gimp + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::LeftGimpAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + +[!AudioStateTrigger] +subsystem=Entity +attribute=ReplicantAnimationState +audio_component=MyomerServoComponent +trigger_state=Mech::RightGimpAnimation +inverse_trigger=0 +control_ID=StartAudioControlID +control_value=MyomerServoDuration +dump_value=False + diff --git a/CONTENT/BT/AUDIO/SLRCMP.SCP b/CONTENT/BT/AUDIO/SLRCMP.SCP new file mode 100644 index 0000000..be58c60 --- /dev/null +++ b/CONTENT/BT/AUDIO/SLRCMP.SCP @@ -0,0 +1,49 @@ +# +################################################################### +# Small Laser Audio Script +################################################################### +# + +[macro] +LaserFireResource=LaserBFire01 +LaserFirePitchOffset=200 +LaserFireComponent=SmallLaserFireComponent +LaserFireIndex=LaserBFireIndex +LaserFireResourceSelect=SmallLaserFireResourceSelect +LaserFireSampleAndHold=SmallLaserFireSampleAndHold +# +LaserSustainResource=LaserBSustain01 +LaserSustainComponent=SmallLaserSustainComponent +LaserSustainIndex=LaserBSustainIndex +LaserSustainResourceSelect=SmallLaserSustainResourceSelect +LaserSustainSampleAndHold=SmallLaserSustainSampleAndHold +# +LaserReleaseResource=LaserARelease01 +LaserReleaseComponent=SmallLaserReleaseComponent +LaserReleaseIndex=LaserAReleaseIndex +LaserReleaseResourceSelect=SmallLaserReleaseResourceSelect +LaserReleaseSampleAndHold=SmallLaserReleaseSampleAndHold +# +LaserChargeResource=LaserACharge01 +LaserChargeComponent=SmallLaserChargeComponent +LaserChargeIndex=LaserAChargeIndex +LaserChargeResourceSelect=SmallLaserChargeResourceSelect +LaserChargeSampleAndHold=SmallLaserChargeSampleAndHold +# +LaserLoadedResource=LaserLoaded01 +LaserLoadedComponent=SmallLaserLoadedComponent +LaserLoadedSequence=SmallLaserLoadedSequence +# +LaserTriggerDuringLoadResource=TriggerDuringLoad01 +LaserTriggerDuringLoadComponent=SmallLaserTriggerDuringLoadComponent +# +LaserMisfireResource=LaserAMisfire01 +LaserMisfireComponent=SmallLaserMisfireComponent +# +LaserSeekLevelResource=BasicBeep02 +LaserSeekLevelComponent=SmallLaserSeekLevelComponent + +[include] +file=audio\lsrcmp.scp + + diff --git a/CONTENT/BT/AUDIO/SLRCMPE.SCP b/CONTENT/BT/AUDIO/SLRCMPE.SCP new file mode 100644 index 0000000..751a50e --- /dev/null +++ b/CONTENT/BT/AUDIO/SLRCMPE.SCP @@ -0,0 +1,14 @@ +# +################################################################### +# Small Laser External Audio Script +################################################################### +# + +[macro] +LaserSustainResource=LaserBSustainExt01 +LaserSustainVolume=LaserExternalSustainVolume +LaserPitchOffset=200 +LaserSustainComponent=SmallLaserExternalSustainComponent + +[include] +file=audio\lsrcmpe.scp diff --git a/CONTENT/BT/AUDIO/SLRTRG.SCP b/CONTENT/BT/AUDIO/SLRTRG.SCP new file mode 100644 index 0000000..924cb62 --- /dev/null +++ b/CONTENT/BT/AUDIO/SLRTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Small Laser Internal Audio Script +################################################################### +# + +[include] +file=audio\lsrtrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/SLRTRGE.SCP b/CONTENT/BT/AUDIO/SLRTRGE.SCP new file mode 100644 index 0000000..2901a5d --- /dev/null +++ b/CONTENT/BT/AUDIO/SLRTRGE.SCP @@ -0,0 +1,9 @@ +# +################################################################### +# Small Laser External Triggers +################################################################### +# + +[include] +file=audio\lsrtrge.scp + diff --git a/CONTENT/BT/AUDIO/SMLEXP.SCP b/CONTENT/BT/AUDIO/SMLEXP.SCP new file mode 100644 index 0000000..4f13b8e --- /dev/null +++ b/CONTENT/BT/AUDIO/SMLEXP.SCP @@ -0,0 +1,108 @@ +# +################################################################### +# Small Explosion Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +name=OriginLocation + +# +################################################################### +# SmallExplosion component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=SmallExplosion01 +priority=0 +mix_presence=3 +volume_mix_level=SmallExplosionVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=True +compression_duration=0.5 +name=SmallExplosionComponent + +#------------------------------------------------------------------ + +# +# resource select +# + +[AudioResourceSelector] +audio_source=SmallExplosionComponent +audio_resource_index=SmallExplosionIndex +control_ID=100 +min_control_value=0.0 +max_control_value=1.0 +dump_value=False +name=SmallExplosionResourceSelect + +# +# sample and hold -> resource select +# + +[AudioSampleAndHold] +audio_component=SmallExplosionResourceSelect +control_ID=100 +sample_duration=99.0 +name=SmallExplosionSampleAndHold + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=SmallExplosionComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-200 +max_value=200 +name=SmallExplosionPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=SmallExplosionComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.7 +max_value=1.0 +name=SmallExplosionBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=SmallExplosionSampleAndHold +audio_component=SmallExplosionPitchSampleAndHold +audio_component=SmallExplosionBrightnessSampleAndHold +name=SmallExplosionSplitter + +[AudioControlSend] +audio_component=SmallExplosionSplitter +control_ID=StartAudioControlID +control_value=0.0 + +[AudioControlSend] +audio_component=SmallExplosionComponent +control_ID=StartAudioControlID +control_value=3.0 + diff --git a/CONTENT/BT/AUDIO/SND1EXT.SCP b/CONTENT/BT/AUDIO/SND1EXT.SCP new file mode 100644 index 0000000..dd6cdc8 --- /dev/null +++ b/CONTENT/BT/AUDIO/SND1EXT.SCP @@ -0,0 +1,49 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\glrtrge.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\glrtrge.scp + +# PPC_3 watcher +[macro] +MechSubsystem=PPC_3 +[include] +file=audio\glrtrge.scp + +# +# AFC25 component +# +[include] +file=audio\acncmpe.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\acntrge.scp + +# ERSLaser watcher +[macro] +MechSubsystem=ERSLaser +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/SND1INT.SCP b/CONTENT/BT/AUDIO/SND1INT.SCP new file mode 100644 index 0000000..7b2587c --- /dev/null +++ b/CONTENT/BT/AUDIO/SND1INT.SCP @@ -0,0 +1,85 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC_1 component +# +[include] +file=audio\ppccmp.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\ppctrg.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\ppctrg.scp + +# PPC_3 watcher +[macro] +MechSubsystem=PPC_3 +[include] +file=audio\ppctrg.scp + +# +# AmmoBinAFC25 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC25 watcher +[macro] +MechSubsystem=AmmoBinAFC25 +[include] +file=audio\abntrg.scp + +# +# AFC25 component +# +[include] +file=audio\saccmp.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\sactrg.scp + +# +# ERSLaser component +# +[include] +file=audio\erscmp.scp + +# ERSLaser watcher +[macro] +MechSubsystem=ERSLaser +[include] +file=audio\erstrg.scp + +# AmmoBinLRM5 watcher +[macro] +MechSubsystem=AmmoBinLRM5 +[include] +file=audio\abntrg.scp + +# +# LRM5 component +# +[include] +file=audio\lrmcmp.scp + +# LRM5 watcher +[macro] +MechSubsystem=LRM5 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/SND2EXT.SCP b/CONTENT/BT/AUDIO/SND2EXT.SCP new file mode 100644 index 0000000..6641dc4 --- /dev/null +++ b/CONTENT/BT/AUDIO/SND2EXT.SCP @@ -0,0 +1,73 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\glrtrge.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\glrtrge.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\glrtrge.scp + +# MLaser_3 watcher +[macro] +MechSubsystem=MLaser_3 +[include] +file=audio\glrtrge.scp + +# MLaser_4 watcher +[macro] +MechSubsystem=MLaser_4 +[include] +file=audio\glrtrge.scp + +# MLaser_5 watcher +[macro] +MechSubsystem=MLaser_5 +[include] +file=audio\glrtrge.scp + +# MLaser_6 watcher +[macro] +MechSubsystem=MLaser_6 +[include] +file=audio\glrtrge.scp + +# +# AFC25_1 component +# +[include] +file=audio\acncmpe.scp + +# AFC25_1 watcher +[macro] +MechSubsystem=AFC25_1 +[include] +file=audio\acntrge.scp + +# AFC25_2 watcher +[macro] +MechSubsystem=AFC25_2 +[include] +file=audio\acntrge.scp + diff --git a/CONTENT/BT/AUDIO/SND2INT.SCP b/CONTENT/BT/AUDIO/SND2INT.SCP new file mode 100644 index 0000000..4cdd750 --- /dev/null +++ b/CONTENT/BT/AUDIO/SND2INT.SCP @@ -0,0 +1,115 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC_1 component +# +[include] +file=audio\eppcmp.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\epptrg.scp + +# +# MLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\ermtrg.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\ermtrg.scp + +# MLaser_3 watcher +[macro] +MechSubsystem=MLaser_3 +[include] +file=audio\ermtrg.scp + +# MLaser_4 watcher +[macro] +MechSubsystem=MLaser_4 +[include] +file=audio\ermtrg.scp + +# MLaser_5 watcher +[macro] +MechSubsystem=MLaser_5 +[include] +file=audio\ermtrg.scp + +# MLaser_6 watcher +[macro] +MechSubsystem=MLaser_6 +[include] +file=audio\ermtrg.scp + +# +# AmmoBinAFC25_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC25_1 watcher +[macro] +MechSubsystem=AmmoBinAFC25_1 +[include] +file=audio\abntrg.scp + +# +# AFC25_1 component +# +[include] +file=audio\saccmp.scp + +# AFC25_1 watcher +[macro] +MechSubsystem=AFC25_1 +[include] +file=audio\sactrg.scp + +# AmmoBinAFC25_2 watcher +[macro] +MechSubsystem=AmmoBinAFC25_2 +[include] +file=audio\abntrg.scp + +# AFC25_2 watcher +[macro] +MechSubsystem=AFC25_2 +[include] +file=audio\sactrg.scp + +# AmmoBinSRM6 watcher +[macro] +MechSubsystem=AmmoBinSRM6 +[include] +file=audio\abntrg.scp + +# +# SRM6 component +# +[include] +file=audio\srmcmp.scp + +# SRM6 watcher +[macro] +MechSubsystem=SRM6 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/SNDEXT.SCP b/CONTENT/BT/AUDIO/SNDEXT.SCP new file mode 100644 index 0000000..83b0955 --- /dev/null +++ b/CONTENT/BT/AUDIO/SNDEXT.SCP @@ -0,0 +1,67 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC25 component +# +[include] +file=audio\acncmpe.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\acntrge.scp + +# AFC100 watcher +[macro] +MechSubsystem=AFC100 +[include] +file=audio\acntrge.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\glrtrge.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/SNDINT.SCP b/CONTENT/BT/AUDIO/SNDINT.SCP new file mode 100644 index 0000000..019ae67 --- /dev/null +++ b/CONTENT/BT/AUDIO/SNDINT.SCP @@ -0,0 +1,121 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC25 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC25 watcher +[macro] +MechSubsystem=AmmoBinAFC25 +[include] +file=audio\abntrg.scp + +# +# AFC25 component +# +[include] +file=audio\saccmp.scp + +# AFC25 watcher +[macro] +MechSubsystem=AFC25 +[include] +file=audio\sactrg.scp + +# AmmoBinAFC100 watcher +[macro] +MechSubsystem=AmmoBinAFC100 +[include] +file=audio\abntrg.scp + +# +# AFC100 component +# +[include] +file=audio\laccmp.scp + +# AFC100 watcher +[macro] +MechSubsystem=AFC100 +[include] +file=audio\lactrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# +# MLaser_1 component +# +[include] +file=audio\mlrcmp.scp + +# MLaser_1 watcher +[macro] +MechSubsystem=MLaser_1 +[include] +file=audio\mlrtrg.scp + +# MLaser_2 watcher +[macro] +MechSubsystem=MLaser_2 +[include] +file=audio\mlrtrg.scp + +# AmmoBinLRM10 watcher +[macro] +MechSubsystem=AmmoBinLRM10 +[include] +file=audio\abntrg.scp + +# +# LRM10 component +# +[include] +file=audio\lrmcmp.scp + +# LRM10 watcher +[macro] +MechSubsystem=LRM10 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/SNRTRG.SCP b/CONTENT/BT/AUDIO/SNRTRG.SCP new file mode 100644 index 0000000..565b4be --- /dev/null +++ b/CONTENT/BT/AUDIO/SNRTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# Sensor Audio Script +################################################################### +# + +[include] +file=audio\buttrg.scp +file=audio\dsttrg.scp +file=audio\clttrg.scp + + diff --git a/CONTENT/BT/AUDIO/SRMCMP.SCP b/CONTENT/BT/AUDIO/SRMCMP.SCP new file mode 100644 index 0000000..beb0646 --- /dev/null +++ b/CONTENT/BT/AUDIO/SRMCMP.SCP @@ -0,0 +1,33 @@ +# +################################################################### +# SRM Audio Script +################################################################### +# + +[macro] +MissileFireResource=MissileLaunch01 +MissileFirePitchOffset=100 +MissileFireComponent=SRMFireComponent +# +MissileLoadingResource=MissileLoading01 +MissileLoadingComponent=SRMLoadingComponent +# +MissileLoadedResource=MissileLoaded01 +MissileLoadedComponent=SRMLoadedComponent +MissileLoadedSequence=SRMLoadedSequence +# +MissileTriggerDuringLoadResource=TriggerDuringLoad01 +MissileTriggerDuringLoadComponent=SRMTriggerDuringLoadComponent +# +MissileMisfireResource=MissileMisfire01 +MissileMisfireComponent=SRMMisfireComponent +MissileMisfireSequence=SRMMisfireSequence +# +MissileJamResource=MissileJam01 +MissileJamComponent=SRMJamComponent +MissileJamSequence=SRMJamSequence + +[include] +file=audio\mslcmp.scp + + diff --git a/CONTENT/BT/AUDIO/SRMTRG.SCP b/CONTENT/BT/AUDIO/SRMTRG.SCP new file mode 100644 index 0000000..d3e2639 --- /dev/null +++ b/CONTENT/BT/AUDIO/SRMTRG.SCP @@ -0,0 +1,12 @@ +# +################################################################### +# SRM Internal Audio Script +################################################################### +# + +[include] +file=audio\msltrg.scp +file=audio\clttrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUDIO/STATIC.SCP b/CONTENT/BT/AUDIO/STATIC.SCP new file mode 100644 index 0000000..bc91d7b --- /dev/null +++ b/CONTENT/BT/AUDIO/STATIC.SCP @@ -0,0 +1,14 @@ +# +#------------------------------------------------------------------ +# Static audio resources +#------------------------------------------------------------------ +# + +[include] +file=audio\macros.scp +file=audio\static1.scp +file=audio\static2.scp +file=audio\static3.scp +file=audio\static4.scp + + diff --git a/CONTENT/BT/AUDIO/STIEXT.SCP b/CONTENT/BT/AUDIO/STIEXT.SCP new file mode 100644 index 0000000..ba8b799 --- /dev/null +++ b/CONTENT/BT/AUDIO/STIEXT.SCP @@ -0,0 +1,37 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# +# GAUSS component +# +[include] +file=audio\acncmpe.scp + +# GAUSS watcher +[macro] +MechSubsystem=GAUSS +[include] +file=audio\acntrge.scp + diff --git a/CONTENT/BT/AUDIO/STIINT.SCP b/CONTENT/BT/AUDIO/STIINT.SCP new file mode 100644 index 0000000..99cfabd --- /dev/null +++ b/CONTENT/BT/AUDIO/STIINT.SCP @@ -0,0 +1,79 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# +# AmmoBinSRM6_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinSRM6_1 watcher +[macro] +MechSubsystem=AmmoBinSRM6_1 +[include] +file=audio\abntrg.scp + +# +# SRM6_1 component +# +[include] +file=audio\srmcmp.scp + +# SRM6_1 watcher +[macro] +MechSubsystem=SRM6_1 +[include] +file=audio\srmtrg.scp + +# AmmoBinSRM6_2 watcher +[macro] +MechSubsystem=AmmoBinSRM6_2 +[include] +file=audio\abntrg.scp + +# SRM6_2 watcher +[macro] +MechSubsystem=SRM6_2 +[include] +file=audio\srmtrg.scp + +# AmmoBinGAUSS watcher +[macro] +MechSubsystem=AmmoBinGAUSS +[include] +file=audio\abntrg.scp + +# +# GAUSS component +# +[include] +file=audio\saccmp.scp + +# GAUSS watcher +[macro] +MechSubsystem=GAUSS +[include] +file=audio\sactrg.scp + diff --git a/CONTENT/BT/AUDIO/SYMBOLS.SCP b/CONTENT/BT/AUDIO/SYMBOLS.SCP new file mode 100644 index 0000000..1fd6ae6 --- /dev/null +++ b/CONTENT/BT/AUDIO/SYMBOLS.SCP @@ -0,0 +1,127 @@ +[macro] +BoxedSolid::StoneMaterial=0 +BoxedSolid::GravelMaterial=1 +BoxedSolid::ConcreteMaterial=2 +BoxedSolid::WoodMaterial=4 +BoxedSolid::RockMaterial=5 +BoxedSolid::OurCraftMaterial=6 +BoxedSolid::OtherCraftMaterial=7 +TransientAudioRenderType=0 +SustainedAudioRenderType=1 +MinAudioSourcePriority=0 +LowAudioSourcePriority=1 +MedAudioSourcePriority=2 +HighAudioSourcePriority=3 +MaxAudioSourcePriority=4 +MinAudioSourceMixPresence=5 +LowAudioSourceMixPresence=4 +MedAudioSourceMixPresence=3 +HighAudioSourceMixPresence=2 +MaxAudioSourceMixPresence=1 +ManualAudioSourceMixPresence=0 +NullAudioControlID=0 +NoteAudioControlID=8 +AttackVolumeAudioControlID=6 +AttackTimeAudioControlID=7 +DurationAudioControlID=10 +VolumeAudioControlID=3 +PitchAudioControlID=4 +BrightnessAudioControlID=5 +StartAudioControlID=1 +StopAudioControlID=2 +IdleAudioControlID=9 +FlushMessagesAudioControlID=11 +TempoAudioControlID=12 +FrontDirectPatchPosition=0 +RearDirectPatchPosition=1 +FrontLeftDirectPatchPosition=2 +FrontRightDirectPatchPosition=3 +RearLeftDirectPatchPosition=4 +RearRightDirectPatchPosition=5 +BTPlayer::VehicleTranslocatedState=2 +BTPlayer::MissionStartingState=3 +BTPlayer::DropZoneAcquiredState=1 +Mech::BurningState=2 +Mech::NoCollisionState=0 +Mech::InitialHitState=1 +Mech::RestState=2 +Mech::StandingAnimation=0 +Mech::RightStandToWalkAnimation=5 +Mech::RightWalkForwardAnimation=6 +Mech::LeftWalkForwardAnimation=7 +Mech::RightWalkToStandAnimation=8 +Mech::LeftWalkToStandAnimation=9 +Mech::RightWalkToRunAnimation=10 +Mech::LeftWalkToRunAnimation=11 +Mech::RightRunAnimation=12 +Mech::LeftRunAnimation=13 +Mech::RightRunToWalkAnimation=14 +Mech::LeftRunToWalkAnimation=15 +Mech::RightStandToReverseAnimation=16 +Mech::LeftStandToReverseAnimation=17 +Mech::RightReverseAnimation=18 +Mech::LeftReverseAnimation=19 +Mech::RightReverseToStandAnimation=20 +Mech::LeftReverseToStandAnimation=21 +Mech::LeftWalkToGimpAnimation=22 +Mech::RightWalkToGimpAnimation=23 +Mech::LeftGimpAnimation=24 +Mech::RightGimpAnimation=25 +Mech::LeftGimpToStandAnimation=26 +Mech::RightGimpToStandAnimation=27 +Mech::FallForwardAnimation=28 +Mech::FallBackwardAnimation=29 +Mech::FallLeftAnimation=30 +Mech::FallRightAnimation=31 +Mech::CrashAnimation=32 +Mech::DuckedAnimation=1 +Mech::SitAnimation=2 +Mech::GimpLeftLegState=3 +Mech::GimpRightLegState=4 +MechSubsystem::Destroyed=1 +PoweredSubsystem::SelectGeneratorAMessageID=4 +PoweredSubsystem::SelectGeneratorBMessageID=5 +PoweredSubsystem::SelectGeneratorCMessageID=6 +PoweredSubsystem::SelectGeneratorDMessageID=7 +PoweredSubsystem::ToggleGeneratorModeMessageID=8 +HeatableSubsystem::ToggleCoolingMessageID=3 +Reservoir::InjectCoolantMessageID=4 +Reservoir::InjectingState=1 +Condenser::MoveValveMessageID=4 +Condenser::OpeningCondenserState=1 +Condenser::ClosingCondenserState=2 +Generator::Off=1 +Generator::Running=2 +Generator::Overheated=4 +Torso::HitExtent=2 +MechControlsMapper::Aux1Eng1MessageID=4 +MechControlsMapper::Aux1Eng2MessageID=5 +MechControlsMapper::Aux1Eng3MessageID=6 +MechControlsMapper::Aux1Eng4MessageID=7 +MechControlsMapper::Aux1QuadMessageID=3 +MechControlsMapper::Aux2Eng1MessageID=9 +MechControlsMapper::Aux2Eng2MessageID=10 +MechControlsMapper::Aux2Eng3MessageID=11 +MechControlsMapper::Aux2Eng4MessageID=12 +MechControlsMapper::Aux2QuadMessageID=8 +MechControlsMapper::Aux3Eng1MessageID=14 +MechControlsMapper::Aux3Eng2MessageID=15 +MechControlsMapper::Aux3Eng3MessageID=16 +MechControlsMapper::Aux3Eng4MessageID=17 +MechControlsMapper::Aux3QuadMessageID=13 +MechControlsMapper::CycleControlModeMessageID=20 +MechRIOMapper::HotboxMessageID=26 +Myomers::ToggleSeekVoltageMessageID=9 +MechWeapon::Firing=0 +MechWeapon::Misfire=1 +MechWeapon::Loaded=2 +MechWeapon::Loading=3 +MechWeapon::TriggerDuringLoad=4 +AmmoBin::Ejecting=3 +AmmoBin::Ejected=4 +AmmoBin::AmmoDumped=5 +ProjectileWeapon::NoAmmo=7 +ProjectileWeapon::Jammed=5 +ProjectileWeapon::TriggerDuringJam=6 +Emitter::ToggleSeekVoltageMessageID=11 +ProjectileWeapon::EjectAmmoMessageID=11 diff --git a/CONTENT/BT/AUDIO/THR1EXT.SCP b/CONTENT/BT/AUDIO/THR1EXT.SCP new file mode 100644 index 0000000..aa0f595 --- /dev/null +++ b/CONTENT/BT/AUDIO/THR1EXT.SCP @@ -0,0 +1,67 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# AFC25_1 component +# +[include] +file=audio\acncmpe.scp + +# AFC25_1 watcher +[macro] +MechSubsystem=AFC25_1 +[include] +file=audio\acntrge.scp + +# AFC25_2 watcher +[macro] +MechSubsystem=AFC25_2 +[include] +file=audio\acntrge.scp + +# +# LLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# LLaser_1 watcher +[macro] +MechSubsystem=LLaser_1 +[include] +file=audio\glrtrge.scp + +# LLaser_2 watcher +[macro] +MechSubsystem=LLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\glrtrge.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/THR1INT.SCP b/CONTENT/BT/AUDIO/THR1INT.SCP new file mode 100644 index 0000000..0427a14 --- /dev/null +++ b/CONTENT/BT/AUDIO/THR1INT.SCP @@ -0,0 +1,109 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# AmmoBinAFC25_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinAFC25_1 watcher +[macro] +MechSubsystem=AmmoBinAFC25_1 +[include] +file=audio\abntrg.scp + +# +# AFC25_1 component +# +[include] +file=audio\saccmp.scp + +# AFC25_1 watcher +[macro] +MechSubsystem=AFC25_1 +[include] +file=audio\sactrg.scp + +# AmmoBinAFC25_2 watcher +[macro] +MechSubsystem=AmmoBinAFC25_2 +[include] +file=audio\abntrg.scp + +# AFC25_2 watcher +[macro] +MechSubsystem=AFC25_2 +[include] +file=audio\sactrg.scp + +# +# LLaser_1 component +# +[include] +file=audio\llrcmp.scp + +# LLaser_1 watcher +[macro] +MechSubsystem=LLaser_1 +[include] +file=audio\llrtrg.scp + +# LLaser_2 watcher +[macro] +MechSubsystem=LLaser_2 +[include] +file=audio\llrtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\erstrg.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\erstrg.scp + +# AmmoBinLRM10 watcher +[macro] +MechSubsystem=AmmoBinLRM10 +[include] +file=audio\abntrg.scp + +# +# LRM10 component +# +[include] +file=audio\lrmcmp.scp + +# LRM10 watcher +[macro] +MechSubsystem=LRM10 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/THR6EXT.SCP b/CONTENT/BT/AUDIO/THR6EXT.SCP new file mode 100644 index 0000000..9d07691 --- /dev/null +++ b/CONTENT/BT/AUDIO/THR6EXT.SCP @@ -0,0 +1,73 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# ERPPC component +# +[include] +file=audio\glrcmpe.scp + +# ERPPC watcher +[macro] +MechSubsystem=ERPPC +[include] +file=audio\glrtrge.scp + +# ERLLaser watcher +[macro] +MechSubsystem=ERLLaser +[include] +file=audio\glrtrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + +# +# MG_1 component +# +[include] +file=audio\acncmpe.scp + +# MG_1 watcher +[macro] +MechSubsystem=MG_1 +[include] +file=audio\acntrge.scp + +# MG_2 watcher +[macro] +MechSubsystem=MG_2 +[include] +file=audio\acntrge.scp + +# MG_3 watcher +[macro] +MechSubsystem=MG_3 +[include] +file=audio\acntrge.scp + +# MG_4 watcher +[macro] +MechSubsystem=MG_4 +[include] +file=audio\acntrge.scp + +# MG_5 watcher +[macro] +MechSubsystem=MG_5 +[include] +file=audio\acntrge.scp + diff --git a/CONTENT/BT/AUDIO/THR6INT.SCP b/CONTENT/BT/AUDIO/THR6INT.SCP new file mode 100644 index 0000000..04eede1 --- /dev/null +++ b/CONTENT/BT/AUDIO/THR6INT.SCP @@ -0,0 +1,139 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# ERPPC component +# +[include] +file=audio\eppcmp.scp + +# ERPPC watcher +[macro] +MechSubsystem=ERPPC +[include] +file=audio\epptrg.scp + +# +# ERLLaser component +# +[include] +file=audio\erlcmp.scp + +# ERLLaser watcher +[macro] +MechSubsystem=ERLLaser +[include] +file=audio\erltrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# +# AmmoBinMG_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinMG_1 watcher +[macro] +MechSubsystem=AmmoBinMG_1 +[include] +file=audio\abntrg.scp + +# +# MG_1 component +# +[include] +file=audio\saccmp.scp + +# MG_1 watcher +[macro] +MechSubsystem=MG_1 +[include] +file=audio\sactrg.scp + +# AmmoBinMG_2 watcher +[macro] +MechSubsystem=AmmoBinMG_2 +[include] +file=audio\abntrg.scp + +# MG_2 watcher +[macro] +MechSubsystem=MG_2 +[include] +file=audio\sactrg.scp + +# AmmoBinMG_3 watcher +[macro] +MechSubsystem=AmmoBinMG_3 +[include] +file=audio\abntrg.scp + +# MG_3 watcher +[macro] +MechSubsystem=MG_3 +[include] +file=audio\sactrg.scp + +# AmmoBinMG_4 watcher +[macro] +MechSubsystem=AmmoBinMG_4 +[include] +file=audio\abntrg.scp + +# MG_4 watcher +[macro] +MechSubsystem=MG_4 +[include] +file=audio\sactrg.scp + +# AmmoBinMG_5 watcher +[macro] +MechSubsystem=AmmoBinMG_5 +[include] +file=audio\abntrg.scp + +# MG_5 watcher +[macro] +MechSubsystem=MG_5 +[include] +file=audio\sactrg.scp + +# AmmoBinNRK10 watcher +[macro] +MechSubsystem=AmmoBinNRK10 +[include] +file=audio\abntrg.scp + +# +# NRK10 component +# +[include] +file=audio\lrmcmp.scp + +# NRK10 watcher +[macro] +MechSubsystem=NRK10 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/THREXT.SCP b/CONTENT/BT/AUDIO/THREXT.SCP new file mode 100644 index 0000000..10e84bf --- /dev/null +++ b/CONTENT/BT/AUDIO/THREXT.SCP @@ -0,0 +1,49 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# ERPPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# ERPPC_1 watcher +[macro] +MechSubsystem=ERPPC_1 +[include] +file=audio\glrtrge.scp + +# ERPPC_2 watcher +[macro] +MechSubsystem=ERPPC_2 +[include] +file=audio\glrtrge.scp + +# LLaser watcher +[macro] +MechSubsystem=LLaser +[include] +file=audio\glrtrge.scp + +# ERMLaser watcher +[macro] +MechSubsystem=ERMLaser +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/THRINT.SCP b/CONTENT/BT/AUDIO/THRINT.SCP new file mode 100644 index 0000000..c58f08c --- /dev/null +++ b/CONTENT/BT/AUDIO/THRINT.SCP @@ -0,0 +1,91 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# ERPPC_1 component +# +[include] +file=audio\eppcmp.scp + +# ERPPC_1 watcher +[macro] +MechSubsystem=ERPPC_1 +[include] +file=audio\epptrg.scp + +# ERPPC_2 watcher +[macro] +MechSubsystem=ERPPC_2 +[include] +file=audio\epptrg.scp + +# +# LLaser component +# +[include] +file=audio\llrcmp.scp + +# LLaser watcher +[macro] +MechSubsystem=LLaser +[include] +file=audio\llrtrg.scp + +# +# ERMLaser component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser watcher +[macro] +MechSubsystem=ERMLaser +[include] +file=audio\ermtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# +# AmmoBinLRM15 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinLRM15 watcher +[macro] +MechSubsystem=AmmoBinLRM15 +[include] +file=audio\abntrg.scp + +# +# LRM15 component +# +[include] +file=audio\lrmcmp.scp + +# LRM15 watcher +[macro] +MechSubsystem=LRM15 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/TRSEXT.SCP b/CONTENT/BT/AUDIO/TRSEXT.SCP new file mode 100644 index 0000000..c056b05 --- /dev/null +++ b/CONTENT/BT/AUDIO/TRSEXT.SCP @@ -0,0 +1,52 @@ +# +################################################################### +# Mech External Torso component +################################################################### +# + +[!Dynamic3DPatchSource] +location=OriginLocation +resource=TorsoTwistExt01 +priority=0 +mix_presence=0 +volume_mix_level=TorsoTwistExternalVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=TorsoTwistExternalComponent + +#------------------------------------------------------------------ + +# +# torso speed -> pitch +# + +[!AudioScalarScale] +subsystem=Torso +attribute=SpeedOfTorsoHorizontal +audio_component=TorsoTwistExternalComponent +attribute_value_boundary1=0.5 +attribute_value_boundary2=0.9 +control_ID=PitchAudioControlID +control_value_boundary1=-200 +control_value_boundary2=200 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[!AudioScalarTrigger] +subsystem=Torso +attribute=SpeedOfTorsoHorizontal +audio_component=TorsoTwistExternalComponent +attribute_value_threshold=0.2 +control_ID_on=StartAudioControlID +control_ID_off=StopAudioControlID +control_value_on=0.0 +control_value_off=0.0 +inverse_trigger=False +dump_value=False + diff --git a/CONTENT/BT/AUDIO/TRSINT.SCP b/CONTENT/BT/AUDIO/TRSINT.SCP new file mode 100644 index 0000000..e52d995 --- /dev/null +++ b/CONTENT/BT/AUDIO/TRSINT.SCP @@ -0,0 +1,85 @@ +# +################################################################### +# Mech Internal Torso component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=TorsoTwistInt01 +position=RearDirectPatchPosition +priority=2 +mix_presence=0 +volume_mix_level=TorsoTwistStartVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=TosoTwistStartComponent + +#------------------------------------------------------------------ + +# +# torso speed -> pitch +# + +[AudioScalarScale] +subsystem=Torso +attribute=SpeedOfTorsoHorizontal +audio_component=TosoTwistStartComponent +attribute_value_boundary1=0.5 +attribute_value_boundary2=0.9 +control_ID=PitchAudioControlID +control_value_boundary1=-200 +control_value_boundary2=200 +exponent=1.0 +dump_value=False + +#------------------------------------------------------------------ + +[AudioScalarTrigger] +subsystem=Torso +attribute=SpeedOfTorsoHorizontal +audio_component=TosoTwistStartComponent +attribute_value_threshold=0.25 +control_ID_on=StartAudioControlID +control_ID_off=StopAudioControlID +control_value_on=0.0 +control_value_off=0.0 +inverse_trigger=False +dump_value=False + +# +################################################################### +# Mech Internal TorsoStop component +################################################################### +# + +[DirectPatchSource] +location=OriginLocation +resource=TorsoTwistStop01 +position=RearDirectPatchPosition +priority=2 +mix_presence=0 +volume_mix_level=TorsoTwistStopVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=True +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=TorsoTwistStopComponent + +#------------------------------------------------------------------ + +[AudioEnumerationTrigger] +subsystem=Torso +attribute=MotionState +audio_component=TorsoTwistStopComponent +attribute_match_value=Torso::HitExtent +control_ID=StartAudioControlID +control_value=1.5 +dump_value=False + diff --git a/CONTENT/BT/AUDIO/VUL1EXT.SCP b/CONTENT/BT/AUDIO/VUL1EXT.SCP new file mode 100644 index 0000000..a4b7f3f --- /dev/null +++ b/CONTENT/BT/AUDIO/VUL1EXT.SCP @@ -0,0 +1,49 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# PPC_1 component +# +[include] +file=audio\glrcmpe.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\glrtrge.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\glrtrge.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/VUL1INT.SCP b/CONTENT/BT/AUDIO/VUL1INT.SCP new file mode 100644 index 0000000..922879c --- /dev/null +++ b/CONTENT/BT/AUDIO/VUL1INT.SCP @@ -0,0 +1,91 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# PPC_1 component +# +[include] +file=audio\ppccmp.scp + +# PPC_1 watcher +[macro] +MechSubsystem=PPC_1 +[include] +file=audio\ppctrg.scp + +# PPC_2 watcher +[macro] +MechSubsystem=PPC_2 +[include] +file=audio\ppctrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# ERSLaser_3 watcher +[macro] +MechSubsystem=ERSLaser_3 +[include] +file=audio\erstrg.scp + +# ERSLaser_4 watcher +[macro] +MechSubsystem=ERSLaser_4 +[include] +file=audio\erstrg.scp + +# +# AmmoBinLRM15_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinLRM15_1 watcher +[macro] +MechSubsystem=AmmoBinLRM15_1 +[include] +file=audio\abntrg.scp + +# +# LRM15_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM15_1 watcher +[macro] +MechSubsystem=LRM15_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM15_2 watcher +[macro] +MechSubsystem=AmmoBinLRM15_2 +[include] +file=audio\abntrg.scp + +# LRM15_2 watcher +[macro] +MechSubsystem=LRM15_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/VUL2EXT.SCP b/CONTENT/BT/AUDIO/VUL2EXT.SCP new file mode 100644 index 0000000..10acd2d --- /dev/null +++ b/CONTENT/BT/AUDIO/VUL2EXT.SCP @@ -0,0 +1,37 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# SLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\glrtrge.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\glrtrge.scp + +# SLaser_3 watcher +[macro] +MechSubsystem=SLaser_3 +[include] +file=audio\glrtrge.scp + +# SLaser_4 watcher +[macro] +MechSubsystem=SLaser_4 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/VUL2INT.SCP b/CONTENT/BT/AUDIO/VUL2INT.SCP new file mode 100644 index 0000000..4b8e8b3 --- /dev/null +++ b/CONTENT/BT/AUDIO/VUL2INT.SCP @@ -0,0 +1,121 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# SLaser_1 component +# +[include] +file=audio\slrcmp.scp + +# SLaser_1 watcher +[macro] +MechSubsystem=SLaser_1 +[include] +file=audio\slrtrg.scp + +# SLaser_2 watcher +[macro] +MechSubsystem=SLaser_2 +[include] +file=audio\slrtrg.scp + +# SLaser_3 watcher +[macro] +MechSubsystem=SLaser_3 +[include] +file=audio\slrtrg.scp + +# SLaser_4 watcher +[macro] +MechSubsystem=SLaser_4 +[include] +file=audio\slrtrg.scp + +# +# AmmoBinSTRK6_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinSTRK6_1 watcher +[macro] +MechSubsystem=AmmoBinSTRK6_1 +[include] +file=audio\abntrg.scp + +# +# STRK6_1 component +# +[include] +file=audio\srmcmp.scp + +# STRK6_1 watcher +[macro] +MechSubsystem=STRK6_1 +[include] +file=audio\srmtrg.scp + +# AmmoBinSTRK6_2 watcher +[macro] +MechSubsystem=AmmoBinSTRK6_2 +[include] +file=audio\abntrg.scp + +# STRK6_2 watcher +[macro] +MechSubsystem=STRK6_2 +[include] +file=audio\srmtrg.scp + +# AmmoBinSTRK6_3 watcher +[macro] +MechSubsystem=AmmoBinSTRK6_3 +[include] +file=audio\abntrg.scp + +# STRK6_3 watcher +[macro] +MechSubsystem=STRK6_3 +[include] +file=audio\srmtrg.scp + +# AmmoBinSTRK6_4 watcher +[macro] +MechSubsystem=AmmoBinSTRK6_4 +[include] +file=audio\abntrg.scp + +# STRK6_4 watcher +[macro] +MechSubsystem=STRK6_4 +[include] +file=audio\srmtrg.scp + +# AmmoBinSTRK6_5 watcher +[macro] +MechSubsystem=AmmoBinSTRK6_5 +[include] +file=audio\abntrg.scp + +# STRK6_5 watcher +[macro] +MechSubsystem=STRK6_5 +[include] +file=audio\srmtrg.scp + +# AmmoBinSTRK6_6 watcher +[macro] +MechSubsystem=AmmoBinSTRK6_6 +[include] +file=audio\abntrg.scp + +# STRK6_6 watcher +[macro] +MechSubsystem=STRK6_6 +[include] +file=audio\srmtrg.scp + diff --git a/CONTENT/BT/AUDIO/VULEXT.SCP b/CONTENT/BT/AUDIO/VULEXT.SCP new file mode 100644 index 0000000..f8d8988 --- /dev/null +++ b/CONTENT/BT/AUDIO/VULEXT.SCP @@ -0,0 +1,49 @@ +# +# External Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchext.scp + +# +# LLaser_1 component +# +[include] +file=audio\glrcmpe.scp + +# LLaser_1 watcher +[macro] +MechSubsystem=LLaser_1 +[include] +file=audio\glrtrge.scp + +# LLaser_2 watcher +[macro] +MechSubsystem=LLaser_2 +[include] +file=audio\glrtrge.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\glrtrge.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\glrtrge.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\glrtrge.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\glrtrge.scp + diff --git a/CONTENT/BT/AUDIO/VULINT.SCP b/CONTENT/BT/AUDIO/VULINT.SCP new file mode 100644 index 0000000..8457aa5 --- /dev/null +++ b/CONTENT/BT/AUDIO/VULINT.SCP @@ -0,0 +1,97 @@ +# +# Internal Audio Script +# +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +# LLaser_1 component +# +[include] +file=audio\llrcmp.scp + +# LLaser_1 watcher +[macro] +MechSubsystem=LLaser_1 +[include] +file=audio\llrtrg.scp + +# LLaser_2 watcher +[macro] +MechSubsystem=LLaser_2 +[include] +file=audio\llrtrg.scp + +# +# ERSLaser_1 component +# +[include] +file=audio\erscmp.scp + +# ERSLaser_1 watcher +[macro] +MechSubsystem=ERSLaser_1 +[include] +file=audio\erstrg.scp + +# ERSLaser_2 watcher +[macro] +MechSubsystem=ERSLaser_2 +[include] +file=audio\erstrg.scp + +# +# ERMLaser_1 component +# +[include] +file=audio\ermcmp.scp + +# ERMLaser_1 watcher +[macro] +MechSubsystem=ERMLaser_1 +[include] +file=audio\ermtrg.scp + +# ERMLaser_2 watcher +[macro] +MechSubsystem=ERMLaser_2 +[include] +file=audio\ermtrg.scp + +# +# AmmoBinLRM20_1 component +# +[include] +file=audio\abncmp.scp + +# AmmoBinLRM20_1 watcher +[macro] +MechSubsystem=AmmoBinLRM20_1 +[include] +file=audio\abntrg.scp + +# +# LRM20_1 component +# +[include] +file=audio\lrmcmp.scp + +# LRM20_1 watcher +[macro] +MechSubsystem=LRM20_1 +[include] +file=audio\lrmtrg.scp + +# AmmoBinLRM20_2 watcher +[macro] +MechSubsystem=AmmoBinLRM20_2 +[include] +file=audio\abntrg.scp + +# LRM20_2 watcher +[macro] +MechSubsystem=LRM20_2 +[include] +file=audio\lrmtrg.scp + diff --git a/CONTENT/BT/AUDIO/WNDEXT01.SCP b/CONTENT/BT/AUDIO/WNDEXT01.SCP new file mode 100644 index 0000000..04a8bae --- /dev/null +++ b/CONTENT/BT/AUDIO/WNDEXT01.SCP @@ -0,0 +1,80 @@ +# +################################################################### +# Wind Audio Script +################################################################### +# + +[include] +file=audio\macros.scp + +# +################################################################### +# Audio locations +################################################################### +# + +[L4AudioLocation] +location_offset=0.0,0.0,0.0 +clipping_scale=0.5 +name=OriginLocation + +# +################################################################### +# WindLoop component +################################################################### +# + +[Dynamic3DPatchSource] +location=OriginLocation +resource=WindLoop01 +priority=0 +mix_presence=4 +volume_mix_level=WindVolume +pitch_mix_offset=0.0 +brightness_mix_level=1.0 +use_brightness_scale=False +use_attack_time_scale=False +has_compression_curve=False +compression_duration=0.0 +name=WindLoopComponent + +#------------------------------------------------------------------ + +# +# sample and hold -> pitch +# + +[AudioSampleAndHold] +audio_component=WindLoopComponent +control_ID=PitchAudioControlID +sample_duration=99.0 +min_value=-300 +max_value=100 +name=WindLoopPitchSampleAndHold + +# +# sample and hold -> filter +# + +[AudioSampleAndHold] +audio_component=WindLoopComponent +control_ID=BrightnessAudioControlID +sample_duration=99.0 +min_value=0.6 +max_value=1.0 +name=WindLoopBrightnessSampleAndHold + +#------------------------------------------------------------------ + +[AudioControlSplitter] +audio_component=WindLoopPitchSampleAndHold +audio_component=WindLoopBrightnessSampleAndHold +audio_component=WindLoopComponent +name=WindLoopSplitter + +[AudioControlSend] +audio_component=WindLoopSplitter +control_ID=StartAudioControlID +control_value=0.0 + + diff --git a/CONTENT/BT/AUDIO/WPNINT.SCP b/CONTENT/BT/AUDIO/WPNINT.SCP new file mode 100644 index 0000000..e20e57f --- /dev/null +++ b/CONTENT/BT/AUDIO/WPNINT.SCP @@ -0,0 +1,113 @@ +# +################################################################### +# Weapon Mech Internal Audio Script +################################################################### +# + +# +################################################################### +# Includes +################################################################### +# + +[include] +file=audio\macros.scp +file=audio\mchint.scp + +# +################################################################### +# Mech Subsystems +################################################################### +# +[include] +file=audio\butcmp.scp +file=audio\dstcmp.scp + +# +################################################################### +# Sensor +################################################################### +# +[macro] +MechSubsystem=Avionics + +[include] +file=audio\buttrg.scp +file=audio\dsttrg.scp + +# +################################################################### +# Myomers +################################################################### +# +[macro] +MechSubsystem=Myomers + +[include] +file=audio\buttrg.scp +file=audio\dsttrg.scp + +# +################################################################### +# PPC +################################################################### +# +[include] +file=audio\ppccmp.scp + +[macro] +MechSubsystem=PPC + +[include] +file=audio\ppctrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + +# +################################################################### +# MACHINE GUN +################################################################### +# +[include] +file=audio\mgncmp.scp + +[macro] +MechSubsystem=MG + +[include] +file=audio\mgntrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + +# +################################################################### +# AUTO CANON +################################################################### +# +[include] +file=audio\acncmp.scp + +[macro] +MechSubsystem=AutoCannon + +[include] +file=audio\acntrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + +# +################################################################### +# SRM +################################################################### +# +[include] +file=audio\srmcmp.scp + +[macro] +MechSubsystem=SRM6 + +[include] +file=audio\srmtrg.scp +file=audio\buttrg.scp +file=audio\dsttrg.scp + diff --git a/CONTENT/BT/AUTOEXEC.BAT b/CONTENT/BT/AUTOEXEC.BAT new file mode 100644 index 0000000..c1568e5 --- /dev/null +++ b/CONTENT/BT/AUTOEXEC.BAT @@ -0,0 +1,22 @@ +@ECHO Off +rem ******* +rem * Standard autoexec.bat for field pods, this should not be edited without +rem * approval from STS +rem ******* +PATH C:\;C:\NWDOS;C:\NWCLIENT;C:\VGL_LABS +VERIFY OFF +PROMPT $P$G +SET NWDOSCFG=C:\NWDOS +SET FBP_USER=Virtual World Entertainment +rem +rem *** load the network stuff +rem +lh c:\nwclient\lsl +lh c:\nwclient\lnepci +lh c:\nwclient\odipkt +NWCACHE 1024 1024 /LEND=OFF /DELAY=1000 +call PARAMETR.bat Rel410 BT POD SLOW SVGA +if exist c:\%VERSION%\%PREFGAME%\last.spl copy c:\%VERSION%\%PREFGAME%\last.spl c:\%VERSION%\%PREFGAME%\bad.spl +if exist c:\%VERSION%\%PREFGAME%\last.spl del c:\%VERSION%\%PREFGAME%\last.spl +call c:\vgl_labs\update.bat +c:\vgl_labs\go.bat diff --git a/CONTENT/BT/BLDTEST.SCN b/CONTENT/BT/BLDTEST.SCN new file mode 100644 index 0000000..d12d3fd --- /dev/null +++ b/CONTENT/BT/BLDTEST.SCN @@ -0,0 +1,88 @@ +# ------------------------- +# BattleTech Arena1 Scene +# ------------------------- +VIEWANGLE 60.0 +RETRACE 1 +CLIP 0.5 3500.0 +//FOG 40 1150.0 0.12 0.12 0.13 +FOG 400 3450.0 0.6 0.6 0.7 +//FOG 110 11150.0 0.3 0.2 0.18 +//FOG 30 1000.0 0.1 0.04 0.01 +//FOG 20 1000.0 0.0 0.0 0.0 +BACKGND 0.2 0.4 0.8 +AMBIENT 0.32 0.41 0.61 +LIGHT 1 1 1 -70 88 0 + +START 0 8.0 0 0 270 0 + +GEOMETRY \BTRAVINE\VIDEO\GEO +GEOMETRY \BTRAVINE\VIDEO\GEO\MORNING +GEOMETRY \BTRAVINE\VIDEO\GEO\DAY +MATERIAL \BTRAVINE\VIDEO\MAT +MATERIAL \BTRAVINE\VIDEO\MAT\MORNING +MATERIAL \BTRAVINE\VIDEO\MAT\DAY +MATERIAL \BTRAVINE\VIDEO\MAT\GRASS +TEXTURE \BTRAVINE\VIDEO\TEX + +STATIC bld01 1 000 0.1 0 0 0 0 +STATIC bld02 1 100 0.1 0 0 0 0 +STATIC bld03 1 200 0.1 0 0 0 0 +STATIC bld05 1 300 0.1 0 0 0 0 +STATIC bld06 1 400 0.1 0 0 0 0 +STATIC bld08 1 500 0.1 0 0 0 0 +STATIC bld20 1 600 0.1 0 0 0 0 +STATIC bld24 1 700 0.1 0 0 0 0 +STATIC bld26 1 800 0.1 0 0 0 0 +STATIC bld27 1 1900 0.1 0 0 0 0 +STATIC bld28 1 1000 0.1 0 0 0 0 +STATIC dsky 1 0 0 00 0 0 0 +//STATIC thr 1 -706 6 204 0 0 0 +//STATIC thr 10 -684 6 -185 0 0 0 +//DYNAMIC square1 1.0 \fx\still2.spl 0.0 0.005 \fx\devent2.evt 2 + + +//MORPH exdisk_1 exdisk_a exdisk_c v 1.0 still1.spl 0.0 0.01 0.1 +//MORPH exdisk_2 exdisk_a exdisk_c v 1.0 still3.spl 0.2 0.1 0.1 +//DYNAMIC exdisk_2 1.0 \fx\move.spl 0.0 0.01 +//DYNAMIC exdisk_1 1.0 \fx\still2.spl 0.0 0.01 + + +//SCROLL btfx:smoke1_scr_tex 0 0 0.05 -0.131 +//SCROLL btfx:firesmoke1_scr_tex 0 0 0.05 -0.331 +//SCROLL btfx:firesmoke2_scr_tex 0 0 0.05 0.131 +//SCROLL btfx:firesmoke3_scr_tex 0 0 0.5 -2.31 +//SCROLL btfx:sky_scr_tex 0 0 0.01 0.01 +//IMMUNE btfx:firesmoke1_mtl 0 +//IMMUNE btfx:sky_mtl 1 +//IMMUNE btfx:planet_mtl 0 +//IMMUNE btfx:space_mtl 0 +//IMMUNE btfx:stars_mtl 0 +//DITHER btfx:smoke1_mtl 50 + +# code type velocity y-off green varience cool count +# texture size bias red blue grav ocool reps + +SPECIALFX 0 btfx:firesmoke1_scr_tex 0 1.10 36.00 0.9 -3.0 0.999 0.950 0.950 0.070 30.0 0.97 0.013 12 1 +SPECIALFX 1 NOTEXT 2 0.00 04.50 0.5 -3.0 2.699 0.70 0.000 0.50 04.0 0.94 0.053 12 1 +SPECIALFX 2 btfx:firesmoke1_scr_tex 2 0.90 03.00 0.5 -3.0 0.600 1.70 4.000 0.80 04.0 0.70 0.083 05 1 +SPECIALFX 3 btfx:firesmoke1_scr_tex 2 1.90 05.00 0.1 -3.0 4.600 0.95 0.500 0.80 00.5 0.70 0.153 05 1 +SPECIALFX 4 btfx:firesmoke1_scr_tex 2 12.00 16.00 0.2 -3.0 4.600 2.00 1.500 0.80 00.5 0.50 0.353 09 1 +SPECIALFX 5 btfx:firesmoke2_scr_tex 2 14.00 12.00 1.7 -9.0 2.900 0.60 0.100 0.50 05.5 0.90 0.023 12 1 +//SPECIALFX 6 btfx:firesmoke1_scr_tex 0 01.30 40.40 1.1 -1.0 3.700 2.30 1.150 3.90 34.8 0.92 0.020 15 1 +SPECIALFX 6 btfx:firesmoke1_scr_tex 1 0.0 20.40 1.5 -1.0 1.700 1.30 0.150 0.90 04.8 0.92 0.050 12 1 +SPECIALFX 7 btfx:firesmoke1_scr_tex 0 2.10 51.80 0.6 -3.0 12.900 11.000 10.500 0.60 1.8 0.95 0.023 5 1 +SPECIALFX 8 btfx:firesmoke1_scr_tex 0 6.10 5.20 1.0 -3.0 2.900 1.000 0.500 0.60 1.8 0.80 0.023 4 1 +SPECIALFX 9 btfx:firesmoke1_scr_tex 0 7.05 1.20 4.0 -15.0 1.200 0.50 0.20 1.20 1.0 0.00982 0.00000001 3 1 +SPECIALFX 10 NOTEXT 2 0.00 21.00 0.1 -3.0 2.699 1.50 1.000 0.50 30.0 0.91 0.037 12 10 + + + +// TRACKER NONE 4.0 2.0 +// TRACKER THRUSTMASTER 4.0 0.3 +TRACKER KEYBOARD 0.2 0.3 + +SCROLL test:texture1 0.0 0.0 0.05 0.1 + +END + + \ No newline at end of file diff --git a/CONTENT/BT/BT.BAT b/CONTENT/BT/BT.BAT new file mode 100644 index 0000000..fe5a713 --- /dev/null +++ b/CONTENT/BT/BT.BAT @@ -0,0 +1,24 @@ +@echo off +call setenv.bat r s n n +call showenv.bat +set a0= +if exist btl4d3s.exe set a0=btl4d3s.exe +if exist btl4d2s.exe set a0=btl4d2s.exe +if exist btl4d0.exe set a0=btl4d0.exe +if exist btl4opt.exe set a0=btl4opt.exe +if "%a0%"=="" goto error +if "%1"=="" set aa=test +if not "%1"=="" set aa=%1 +echo on +32rtm.exe -x +%a0% -egg %aa%.egg +32rtm.exe -u +@echo off +set aa= +goto end +:error +echo. +echo Program not found in current directory. +echo. +:end +set a0= diff --git a/CONTENT/BT/BTCAM.BAT b/CONTENT/BT/BTCAM.BAT new file mode 100644 index 0000000..8fe0a06 --- /dev/null +++ b/CONTENT/BT/BTCAM.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM01.BAT b/CONTENT/BT/BTCAM/BTCAM01.BAT new file mode 100644 index 0000000..e0aa52f --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM01.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM02.BAT b/CONTENT/BT/BTCAM/BTCAM02.BAT new file mode 100644 index 0000000..9b1d296 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM02.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM03.BAT b/CONTENT/BT/BTCAM/BTCAM03.BAT new file mode 100644 index 0000000..edde84c --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM03.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM04.BAT b/CONTENT/BT/BTCAM/BTCAM04.BAT new file mode 100644 index 0000000..8b8de44 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM04.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM05.BAT b/CONTENT/BT/BTCAM/BTCAM05.BAT new file mode 100644 index 0000000..8fe0a06 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM05.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM06.BAT b/CONTENT/BT/BTCAM/BTCAM06.BAT new file mode 100644 index 0000000..5ef6e5a --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM06.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM07.BAT b/CONTENT/BT/BTCAM/BTCAM07.BAT new file mode 100644 index 0000000..ffdc350 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM07.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM08.BAT b/CONTENT/BT/BTCAM/BTCAM08.BAT new file mode 100644 index 0000000..2493074 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM08.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM09.BAT b/CONTENT/BT/BTCAM/BTCAM09.BAT new file mode 100644 index 0000000..81dda88 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM09.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM10.BAT b/CONTENT/BT/BTCAM/BTCAM10.BAT new file mode 100644 index 0000000..0e261c0 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM10.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM11.BAT b/CONTENT/BT/BTCAM/BTCAM11.BAT new file mode 100644 index 0000000..5be6414 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM11.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM12.BAT b/CONTENT/BT/BTCAM/BTCAM12.BAT new file mode 100644 index 0000000..afed698 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM12.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM13.BAT b/CONTENT/BT/BTCAM/BTCAM13.BAT new file mode 100644 index 0000000..2cd7bbc --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM13.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM14.BAT b/CONTENT/BT/BTCAM/BTCAM14.BAT new file mode 100644 index 0000000..dad1d08 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM14.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM15.BAT b/CONTENT/BT/BTCAM/BTCAM15.BAT new file mode 100644 index 0000000..1bf02df --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM15.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM16.BAT b/CONTENT/BT/BTCAM/BTCAM16.BAT new file mode 100644 index 0000000..28a44f6 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM16.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM17.BAT b/CONTENT/BT/BTCAM/BTCAM17.BAT new file mode 100644 index 0000000..f20835c --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM17.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM18.BAT b/CONTENT/BT/BTCAM/BTCAM18.BAT new file mode 100644 index 0000000..d9a1b23 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM18.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM19.BAT b/CONTENT/BT/BTCAM/BTCAM19.BAT new file mode 100644 index 0000000..c2ca9d4 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM19.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM20.BAT b/CONTENT/BT/BTCAM/BTCAM20.BAT new file mode 100644 index 0000000..760f59f --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM20.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM21.BAT b/CONTENT/BT/BTCAM/BTCAM21.BAT new file mode 100644 index 0000000..7e37ed9 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM21.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM22.BAT b/CONTENT/BT/BTCAM/BTCAM22.BAT new file mode 100644 index 0000000..982ee90 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM22.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM23.BAT b/CONTENT/BT/BTCAM/BTCAM23.BAT new file mode 100644 index 0000000..5311405 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM23.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM24.BAT b/CONTENT/BT/BTCAM/BTCAM24.BAT new file mode 100644 index 0000000..487e086 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM24.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM25.BAT b/CONTENT/BT/BTCAM/BTCAM25.BAT new file mode 100644 index 0000000..dec5a68 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM25.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM26.BAT b/CONTENT/BT/BTCAM/BTCAM26.BAT new file mode 100644 index 0000000..eecd505 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM26.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM27.BAT b/CONTENT/BT/BTCAM/BTCAM27.BAT new file mode 100644 index 0000000..c24b864 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM27.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM28.BAT b/CONTENT/BT/BTCAM/BTCAM28.BAT new file mode 100644 index 0000000..ef8cc23 --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM28.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM29.BAT b/CONTENT/BT/BTCAM/BTCAM29.BAT new file mode 100644 index 0000000..70d32eb --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM29.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM30.BAT b/CONTENT/BT/BTCAM/BTCAM30.BAT new file mode 100644 index 0000000..fcba19a --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM30.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM31.BAT b/CONTENT/BT/BTCAM/BTCAM31.BAT new file mode 100644 index 0000000..251f59e --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM31.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +rem set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTCAM/BTCAM32.BAT b/CONTENT/BT/BTCAM/BTCAM32.BAT new file mode 100644 index 0000000..0ba629b --- /dev/null +++ b/CONTENT/BT/BTCAM/BTCAM32.BAT @@ -0,0 +1,43 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +rem set L4EYES=25 5.9 -10 0 95 0 r +rem set L4EYES=0 7.3 -19 -7 180 0 r +rem Animation Cycle +rem set L4EYES=0 7.3 -19 -6 180 0 r +rem set L4EYES=-3.706716 7.3 -18.634920 -6 191.25 0 r +rem set L4EYES=-7.270985 7.3 -17.553711 -6 202.5 0 r +rem set L4EYES=-10.555834 7.3 -15.797922 -6 213.75 0 r +rem set L4EYES=-13.435028 7.3 -13.435028 -6 225 0 r +rem set L4EYES=-15.797922 7.3 -10.555834 -6 236.25 0 r +rem set L4EYES=-17.553711 7.3 -7.270985 -6 247.5 0 r +rem set L4EYES=-18.634920 7.3 -3.706716 -6 258.75 0 r +rem set L4EYES=-19 7.3 0 -6 270 0 r +rem set L4EYES=-18.634920 7.3 3.706716 -6 281.25 0 r +rem set L4EYES=-17.553711 7.3 7.270985 -6 292.5 0 r +rem set L4EYES=-15.797922 7.3 10.555834 -6 303.75 0 r +rem set L4EYES=-13.435028 7.3 13.435028 -6 315 0 r +rem set L4EYES=-10.555834 7.3 15.797922 -6 326.25 0 r +rem set L4EYES=-7.270985 7.3 17.553711 -6 337.5 0 r +rem set L4EYES=-3.706716 7.3 18.634920 -6 348.75 0 r +rem set L4EYES=0 7.3 19 -6 0 0 r +rem set L4EYES=3.706716 7.3 18.634920 -6 11.25 0 r +rem set L4EYES=7.270985 7.3 17.553711 -6 22.5 0 r +rem set L4EYES=10.555834 7.3 15.797922 -6 33.75 0 r +rem set L4EYES=13.435028 7.3 13.435028 -6 45 0 r +rem set L4EYES=15.797922 7.3 10.555834 -6 56.25 0 r +rem set L4EYES=17.553711 7.3 7.270985 -6 67.5 0 r +rem set L4EYES=18.634920 7.3 3.706716 -6 78.75 0 r +rem set L4EYES=19 7.3 0 -6 90 0 r +rem set L4EYES=18.634920 7.3 -3.706716 -6 101.25 0 r +rem set L4EYES=17.553711 7.3 -7.270985 -6 112.5 0 r +rem set L4EYES=15.797922 7.3 -10.555834 -6 123.75 0 r +rem set L4EYES=13.435028 7.3 -13.435028 -6 135 0 r +rem set L4EYES=10.555834 7.3 -15.797922 -6 146.25 0 r +rem set L4EYES=7.270985 7.3 -17.553711 -6 157.5 0 r +set L4EYES=3.706716 7.3 -18.634920 -6 168.75 0 r +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTGO.BAT b/CONTENT/BT/BTGO.BAT new file mode 100644 index 0000000..1a0932c --- /dev/null +++ b/CONTENT/BT/BTGO.BAT @@ -0,0 +1,9 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +set L4EYES= +set L4VIEWEXT= +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTL4.BLD b/CONTENT/BT/BTL4.BLD new file mode 100644 index 0000000..bd587cf --- /dev/null +++ b/CONTENT/BT/BTL4.BLD @@ -0,0 +1,230 @@ +[release] +version=1.0 + +// +// Official resource maps and models should have an +// id assigned to them, as should any object that could show up on a mission +// review spool (even a test one). +// +// the format is xxxxx=xxxx.xxx /id:# +// + +// The next number to use is: 169 +// + +[resource] +name=btl4.res +dircollision=solids\ +dirmodel=models\ +dirmap=maps\ +diraudio=audio\ +dirvideo=video\ +dirgauge=gauge\ +diranimation=anims\ +// +// Player Model File +// +model=player.mod /id:75 +// +// Explosion Model Files +// +model=lzrhiti.mod /id:1 +model=ppchiti.mod /id:2 +model=canhiti.mod /id:3 +model=mslhiti.mod /id:4 +model=mghiti.mod /id:152 +model=dam3exp.mod /id:5 +model=dam4exp.mod /id:6 +model=dam4expi.mod /id:7 +model=dam1hiti.mod /id:8 +model=dam2hiti.mod /id:9 +model=dam3hiti.mod /id:10 +model=dam4hiti.mod /id:11 +model=desthiti.mod /id:12 +static=explode.onl +model=explode.mod /id:13 +model=mghit.mod /id:14 +model=ppchit.mod /id:15 +model=lzrhit.mod /id:16 +model=mslhit.mod /id:17 +model=canhit.mod /id:18 +model=gndhit.mod /id:19 +model=minhit.mod /id:20 +model=majhit.mod /id:21 +model=blhdead.mod /id:22 +model=lokdead.mod /id:23 +model=maddead.mod /id:76 +model=owndead.mod /id:24 +model=thrdead.mod /id:25 +model=vuldead.mod /id:77 +model=avadead.mod /id:113 +model=rapdead.mod /id:150 +model=mechdead.mod /id:74 +model=dam1hit.mod /id:26 +model=dam2hit.mod /id:27 +model=dam3hit.mod /id:28 +model=dam4hit.mod /id:29 +model=desthit.mod /id:30 +model=stephit.mod /id:31 +model=trkdead.mod /id:32 +model=smldead.mod /id:78 +model=meddead.mod /id:34 +model=bigdead.mod /id:33 +model=msldead.mod /id:79 +model=twrdead.mod /id:80 +// +// Ballistic Ammo +// +model=projtile.mod /id:35 +model=srm.mod /id:36 +model=lrm.mod /id:37 +model=strk.mod /id:153 +model=nrk.mod /id:155 +//model=lbx.mod /id:166 +// +// Scenario Role Model Files +// +//model=convoy.mod /id:38 +model=dfltrole.mod /id:39 +//model=attacker.mod /id:40 +//model=defender.mod /id:41 +//model=decoy.mod /id:42 +//model=hostage.mod /id:43 +//model=ambssdor.mod /id:44 +model=NoReturn.mod /id:112 +// +// Mech Model Files +// +model=mechalrm.mod /id:83 +// + +model=madcat.mod /id:72 +model=mad1.mod /id:118 +model=mad2.mod /id:164 +model=loki.mod /id:45 +model=lok1.mod /id:119 +model=lok2.mod /id:160 +model=thor.mod /id:46 +model=thr1.mod /id:115 +//model=thr6.mod /id:167 +model=blkhawk.mod /id:47 +model=bhk1.mod /id:116 +model=owens.mod /id:48 +model=own1.mod /id:147 +model=vulture.mod /id:73 +model=vul1.mod /id:117 +//model=vul2.mod /id:163 +model=avatar.mod /id:110 +model=ava1.mod /id:114 +//model=ava2.mod /id:168 +model=sunder.mod /id:111 +model=snd1.mod /id:148 +//model=snd2.mod /id:165 + +//model=firstrtr.mod /id:156 +//model=blkjack.mod /id:157 +//model=raptor.mod /id:146 +//model=strider.mod /id:151 +//model=wpnmech.mod +// +// +//model=bat.mod /id:158 +// +// Camera Model File +// +model=camera.mod /id:49 +// +// Cultural Icons (stuff what can blow up) +// +model=tt1.mod /id:50 +model=tt2.mod /id:51 +model=snh.mod /id:52 +model=trk1.mod /id:53 +model=trk3.mod /id:54 +model=trk4.mod /id:55 +model=bpip1.mod /id:56 +model=bac1.mod /id:57 +model=awwlk1.mod /id:58 +model=adwlk1.mod /id:59 +model=adwlk2.mod /id:60 +model=adwlk3.mod /id:61 +model=arban1.mod /id:62 +model=arban2.mod /id:63 +model=arban3.mod /id:64 +model=arban4.mod /id:65 +model=arban5.mod /id:66 +model=arban6.mod /id:67 +model=bwlk1.mod /id:68 +model=bdet4.mod /id:69 +model=hn1.mod /id:85 +model=pdsh.mod /id:86 +model=sl2.mod /id:87 +model=twr.mod /id:88 +model=plit.mod /id:89 +model=gnr.mod /id:90 +model=tnt.mod /id:91 +model=bnk.mod /id:92 +model=msl.mod /id:93 +model=crt.mod /id:94 +model=hut.mod /id:95 +model=ft1.mod /id:96 +model=ft2.mod /id:97 +model=wst.mod /id:98 +model=mslg.mod /id:99 +model=fp0.mod /id:100 +model=fp1.mod /id:101 +model=fp2.mod /id:102 +model=fp3.mod /id:103 +model=hc1.mod /id:104 +model=hc2.mod /id:105 +model=hwz.mod /id:106 +//model=jax1.mod /id:107 +//model=jax2.mod /id:108 +model=ab07.mod /id:109 +model=apc.mod /id:141 +model=armrmovr.mod /id:142 +model=bulldog.mod /id:143 +model=comtruck.mod /id:123 +model=coolant.mod /id:124 +model=dozer.mod /id:125 +model=harasser.mod /id:126 +model=hummer.mod /id:127 +model=lrmcarry.mod /id:128 +model=mechmovr.mod /id:129 +model=rommel.mod /id:130 +model=semi.mod /id:131 +model=semirig.mod /id:132 +model=srmcarry.mod /id:133 +model=striker.mod /id:134 +model=swiftwnd.mod /id:135 +model=bld03.mod /id:136 +model=bld04.mod /id:137 +model=bld20.mod /id:138 +model=bld24.mod /id:139 +model=bld26.mod /id:140 +model=tree.mod /id:144 +model=mslr.mod /id:161 +// +// Maps +// +//map=test.map /id:145 +map=blank.map /id:154 +//map=polar1.map /id:71 +//map=polar2.map + +map=arena1.map /id:70 +map=arena2.map /id:84 +//map=arena3.map /id:162 +map=polar3.map /id:81 +map=polar4.map /id:82 +map=rav.map /id:120 +//map=rav1.map /id:159 +map=grass.map /id:121 +map=dbase.map /id:122 +map=cavern.map /id:149 + +zone=all.zne + +[zones] +zone=all.zne + diff --git a/CONTENT/BT/BTL4.OPS b/CONTENT/BT/BTL4.OPS new file mode 100644 index 0000000..da0367c --- /dev/null +++ b/CONTENT/BT/BTL4.OPS @@ -0,0 +1,154 @@ +[resource] +res name=btl4 + +[btl4::Standard::LocationList] +location=btl4::Standard::Location::blank +location=btl4::Standard::Location::arena1 +location=btl4::Standard::Location::arenall +location=btl4::Standard::Location::artrucks +location=btl4::Standard::Location::adrop +location=btl4::Standard::Location::arena2 +location=btl4::Standard::Location::arenall2 +location=btl4::Standard::Location::adrop +location=btl4::Standard::Location::polar3 +location=btl4::Standard::Location::polar4 +location=btl4::Standard::Location::pol4sfx +location=btl4::Standard::Location::rav +location=btl4::Standard::Location::grass +location=btl4::Standard::Location::dbase +location=btl4::Standard::Location::cavern + +[btl4::Standard::Location::blank] +tag=blank + +[btl4::blank::DropZoneList] + +[btl4::Standard::Location::arena1] +tag=arena1 + +[btl4::Standard::Location::arenall] +tag=arenall + +[btl4::arenall::DropZoneList] + +[btl4::Standard::Location::artrucks] +tag=artrucks + +[btl4::artrucks::DropZoneList] + +[btl4::Standard::Location::adrop] +tag=adrop + + +[btl4::adrop::DropZoneList] + + +[btl4::arena1::DropZoneList] + +[btl4::Standard::Location::arena2] +tag=arena2 + +[btl4::Standard::Location::arenall2] +tag=arenall2 + +[btl4::arenall2::DropZoneList] + +[btl4::arena2::DropZoneList] + +[btl4::Standard::Location::polar3] +tag=polar3 + +[btl4::polar3::DropZoneList] + +[btl4::Standard::Location::polar4] +tag=polar4 + +[btl4::Standard::Location::pol4sfx] +tag=pol4sfx + +[btl4::pol4sfx::DropZoneList] + +[btl4::polar4::DropZoneList] + +[btl4::Standard::Location::rav] +tag=rav + +[btl4::rav::DropZoneList] + +[btl4::Standard::Location::grass] +tag=grass + +[btl4::grass::DropZoneList] + +[btl4::Standard::Location::dbase] +tag=dbase + +[btl4::dbase::DropZoneList] + +[btl4::Standard::Location::cavern] +tag=cavern + +[btl4::cavern::DropZoneList] + +[btl4::Standard::ColorList] +color=btl4::Standard::Color::Black +color=btl4::Standard::Color::Brown +color=btl4::Standard::Color::Crimson +color=btl4::Standard::Color::Green +color=btl4::Standard::Color::Grey +color=btl4::Standard::Color::Tan +color=btl4::Standard::Color::White + +[btl4::Standard::Color::Black] +tag=Black + +[btl4::Standard::Color::Brown] +tag=Brown + +[btl4::Standard::Color::Crimson] +tag=Crimson + +[btl4::Standard::Color::Green] +tag=Green + +[btl4::Standard::Color::Grey] +tag=Grey + +[btl4::Standard::Color::Tan] +tag=Tan + +[btl4::Standard::Color::White] +tag=White + +[btl4::Standard::BadgeList] +badge=btl4::Standard::Badge::Davion +badge=btl4::Standard::Badge::Kurita +badge=btl4::Standard::Badge::Liao +badge=btl4::Standard::Badge::Marik +badge=btl4::Standard::Badge::None +badge=btl4::Standard::Badge::Steiner +badge=btl4::Standard::Badge::VGL + +[btl4::Standard::Badge::Davion] +tag=Davion + +[btl4::Standard::Badge::Kurita] +tag=Kurita + +[btl4::Standard::Badge::Liao] +tag=Liao + +[btl4::Standard::Badge::Marik] +tag=Marik + +[btl4::Standard::Badge::None] +tag=None + +[btl4::Standard::Badge::Steiner] +tag=Steiner + +[btl4::Standard::Badge::VGL] +tag=VGL + +[btl4::Standard::VehicleList] + diff --git a/CONTENT/BT/BTL4.ORG b/CONTENT/BT/BTL4.ORG new file mode 100644 index 0000000..f3f646c --- /dev/null +++ b/CONTENT/BT/BTL4.ORG @@ -0,0 +1,230 @@ +[release] +version=1.0 + +// +// Official resource maps and models should have an +// id assigned to them, as should any object that could show up on a mission +// review spool (even a test one). +// +// the format is xxxxx=xxxx.xxx /id:# +// + +// The next number to use is: 169 +// + +[resource] +name=btl4.res +dircollision=solids\ +dirmodel=models\ +dirmap=maps\ +diraudio=audio\ +dirvideo=video\ +dirgauge=gauge\ +diranimation=anims\ +// +// Player Model File +// +model=player.mod /id:75 +// +// Explosion Model Files +// +model=lzrhiti.mod /id:1 +model=ppchiti.mod /id:2 +model=canhiti.mod /id:3 +model=mslhiti.mod /id:4 +model=mghiti.mod /id:152 +model=dam3exp.mod /id:5 +model=dam4exp.mod /id:6 +model=dam4expi.mod /id:7 +model=dam1hiti.mod /id:8 +model=dam2hiti.mod /id:9 +model=dam3hiti.mod /id:10 +model=dam4hiti.mod /id:11 +model=desthiti.mod /id:12 +static=explode.onl +model=explode.mod /id:13 +model=mghit.mod /id:14 +model=ppchit.mod /id:15 +model=lzrhit.mod /id:16 +model=mslhit.mod /id:17 +model=canhit.mod /id:18 +model=gndhit.mod /id:19 +model=minhit.mod /id:20 +model=majhit.mod /id:21 +model=blhdead.mod /id:22 +model=lokdead.mod /id:23 +model=maddead.mod /id:76 +model=owndead.mod /id:24 +model=thrdead.mod /id:25 +model=vuldead.mod /id:77 +model=avadead.mod /id:113 +model=rapdead.mod /id:150 +model=mechdead.mod /id:74 +model=dam1hit.mod /id:26 +model=dam2hit.mod /id:27 +model=dam3hit.mod /id:28 +model=dam4hit.mod /id:29 +model=desthit.mod /id:30 +model=stephit.mod /id:31 +model=trkdead.mod /id:32 +model=smldead.mod /id:78 +model=meddead.mod /id:34 +model=bigdead.mod /id:33 +model=msldead.mod /id:79 +model=twrdead.mod /id:80 +// +// Ballistic Ammo +// +model=projtile.mod /id:35 +model=srm.mod /id:36 +model=lrm.mod /id:37 +model=strk.mod /id:153 +model=nrk.mod /id:155 +//model=lbx.mod /id:166 +// +// Scenario Role Model Files +// +//model=convoy.mod /id:38 +model=dfltrole.mod /id:39 +//model=attacker.mod /id:40 +//model=defender.mod /id:41 +//model=decoy.mod /id:42 +//model=hostage.mod /id:43 +//model=ambssdor.mod /id:44 +model=NoReturn.mod /id:112 +// +// Mech Model Files +// +model=mechalrm.mod /id:83 +// + +model=madcat.mod /id:72 +model=mad1.mod /id:118 +model=mad2.mod /id:164 +model=loki.mod /id:45 +model=lok1.mod /id:119 +model=lok2.mod /id:160 +model=thor.mod /id:46 +model=thr1.mod /id:115 +//model=thr6.mod /id:167 +model=blkhawk.mod /id:47 +model=bhk1.mod /id:116 +model=owens.mod /id:48 +model=own1.mod /id:147 +model=vulture.mod /id:73 +model=vul1.mod /id:117 +model=vul2.mod /id:163 +model=avatar.mod /id:110 +model=ava1.mod /id:114 +//model=ava2.mod /id:168 +model=sunder.mod /id:111 +model=snd1.mod /id:148 +//model=snd2.mod /id:165 + +//model=firstrtr.mod /id:156 +//model=blkjack.mod /id:157 +//model=raptor.mod /id:146 +//model=strider.mod /id:151 +//model=wpnmech.mod +// +// +//model=bat.mod /id:158 +// +// Camera Model File +// +model=camera.mod /id:49 +// +// Cultural Icons (stuff what can blow up) +// +model=tt1.mod /id:50 +model=tt2.mod /id:51 +model=snh.mod /id:52 +model=trk1.mod /id:53 +model=trk3.mod /id:54 +model=trk4.mod /id:55 +model=bpip1.mod /id:56 +model=bac1.mod /id:57 +model=awwlk1.mod /id:58 +model=adwlk1.mod /id:59 +model=adwlk2.mod /id:60 +model=adwlk3.mod /id:61 +model=arban1.mod /id:62 +model=arban2.mod /id:63 +model=arban3.mod /id:64 +model=arban4.mod /id:65 +model=arban5.mod /id:66 +model=arban6.mod /id:67 +model=bwlk1.mod /id:68 +model=bdet4.mod /id:69 +model=hn1.mod /id:85 +model=pdsh.mod /id:86 +model=sl2.mod /id:87 +model=twr.mod /id:88 +model=plit.mod /id:89 +model=gnr.mod /id:90 +model=tnt.mod /id:91 +model=bnk.mod /id:92 +model=msl.mod /id:93 +model=crt.mod /id:94 +model=hut.mod /id:95 +model=ft1.mod /id:96 +model=ft2.mod /id:97 +model=wst.mod /id:98 +model=mslg.mod /id:99 +model=fp0.mod /id:100 +model=fp1.mod /id:101 +model=fp2.mod /id:102 +model=fp3.mod /id:103 +model=hc1.mod /id:104 +model=hc2.mod /id:105 +model=hwz.mod /id:106 +//model=jax1.mod /id:107 +//model=jax2.mod /id:108 +model=ab07.mod /id:109 +model=apc.mod /id:141 +model=armrmovr.mod /id:142 +model=bulldog.mod /id:143 +model=comtruck.mod /id:123 +model=coolant.mod /id:124 +model=dozer.mod /id:125 +model=harasser.mod /id:126 +model=hummer.mod /id:127 +model=lrmcarry.mod /id:128 +model=mechmovr.mod /id:129 +model=rommel.mod /id:130 +model=semi.mod /id:131 +model=semirig.mod /id:132 +model=srmcarry.mod /id:133 +model=striker.mod /id:134 +model=swiftwnd.mod /id:135 +model=bld03.mod /id:136 +model=bld04.mod /id:137 +model=bld20.mod /id:138 +model=bld24.mod /id:139 +model=bld26.mod /id:140 +model=tree.mod /id:144 +model=mslr.mod /id:161 +// +// Maps +// +//map=test.map /id:145 +//map=blank.map /id:154 +//map=polar1.map /id:71 +//map=polar2.map + +map=arena1.map /id:70 +map=arena2.map /id:84 +//map=arena3.map /id:162 +map=polar3.map /id:81 +map=polar4.map /id:82 +map=rav.map /id:120 +//map=rav1.map /id:159 +map=grass.map /id:121 +map=dbase.map /id:122 +//map=cavern.map /id:149 + +zone=all.zne + +[zones] +zone=all.zne + diff --git a/CONTENT/BT/BTL4BU.BLD b/CONTENT/BT/BTL4BU.BLD new file mode 100644 index 0000000..09e66ff --- /dev/null +++ b/CONTENT/BT/BTL4BU.BLD @@ -0,0 +1,203 @@ +[release] +version=1.0 + +// +// Official resource maps and models should have an +// id assigned to them, as should any object that could show up on a mission +// review spool (even a test one). +// +// the format is xxxxx=xxxx.xxx /id:# +// + +// The next number to use is: 141 +// + +[resource] +name=btl4.res +dircollision=solids\ +dirmodel=models\ +dirmap=maps\ +diraudio=audio\ +dirvideo=video\ +dirgauge=gauge\ +diranimation=anims\ +// +// Player Model File +// +model=player.mod /id:75 +// +// Explosion Model Files +// +model=lzrhiti.mod /id:1 +model=ppchiti.mod /id:2 +model=canhiti.mod /id:3 +model=mslhiti.mod /id:4 +model=dam3exp.mod /id:5 +model=dam4exp.mod /id:6 +model=dam4expi.mod /id:7 +model=dam1hiti.mod /id:8 +model=dam2hiti.mod /id:9 +model=dam3hiti.mod /id:10 +model=dam4hiti.mod /id:11 +model=desthiti.mod /id:12 +static=explode.onl +model=explode.mod /id:13 +model=mghit.mod /id:14 +model=ppchit.mod /id:15 +model=lzrhit.mod /id:16 +model=mslhit.mod /id:17 +model=canhit.mod /id:18 +model=gndhit.mod /id:19 +model=minhit.mod /id:20 +model=majhit.mod /id:21 +model=blhdead.mod /id:22 +model=lokdead.mod /id:23 +model=maddead.mod /id:76 +model=owndead.mod /id:24 +model=thrdead.mod /id:25 +model=vuldead.mod /id:77 +model=avadead.mod /id:116 +model=mechdead.mod /id:74 +model=dam1hit.mod /id:26 +model=dam2hit.mod /id:27 +model=dam3hit.mod /id:28 +model=dam4hit.mod /id:29 +model=desthit.mod /id:30 +model=stephit.mod /id:31 +model=trkdead.mod /id:32 +model=smldead.mod /id:78 +model=meddead.mod /id:34 +model=bigdead.mod /id:33 +model=msldead.mod /id:79 +model=twrdead.mod /id:80 +model=apc.mod /id:120 +model=armrmovr.mod /id:121 +model=bulldog.mod /id:122 +model=comtruck.mod /id:123 +model=coolant.mod /id:124 +model=dozer.mod /id:125 +model=harasser.mod /id:126 +model=hummer.mod /id:127 +model=lrmcarry.mod /id:128 +model=mechmovr.mod /id:129 +model=rommel.mod /id:130 +model=semi.mod /id:131 +model=semirig.mod /id:132 +model=srmcarry.mod /id:133 +model=striker.mod /id:134 +model=swiftwnd.mod /id:135 +model=bld03.mod /id:136 +model=bld04.mod /id:137 +model=bld20.mod /id:138 +model=bld24.mod /id:139 +model=bld26.mod /id:140 +// +// Ballistic Ammo +// +model=projtile.mod /id:35 +model=srm.mod /id:36 +model=lrm.mod /id:37 +// +// Scenario Role Model Files +// +model=convoy.mod /id:38 +model=dfltrole.mod /id:39 +model=attacker.mod /id:40 +model=defender.mod /id:41 +model=decoy.mod /id:42 +model=hostage.mod /id:43 +model=ambssdor.mod /id:44 +model=NoReturn.mod /id:112 +// +// Mech Model Files +// +model=mechalrm.mod /id:83 +// + +model=madcat.mod /id:72 +model=loki.mod /id:45 +model=lok1.mod /id:117 +model=thor.mod /id:46 +model=blkhawk.mod /id:47 +model=bhk1.mod /id:114 +model=owens.mod /id:48 +model=vulture.mod /id:73 +//model=vul1.mod /id:118 +model=thr1.mod /id:113 +model=avatar.mod /id:110 +model=ava1.mod /id:115 +model=sunder.mod /id:111 + +//model=firstrtr.mod +//model=blkjack.mod +//model=raptor.mod +//model=wpnmech.mod +//model=strider.mod +// +// Camera Model File +// +model=camera.mod /id:49 +// +// Cultural Icons (stuff what can blow up) +// +model=tt1.mod /id:50 +model=tt2.mod /id:51 +model=snh.mod /id:52 +model=trk1.mod /id:53 +model=trk3.mod /id:54 +model=trk4.mod /id:55 +model=bpip1.mod /id:56 +model=bac1.mod /id:57 +model=awwlk1.mod /id:58 +model=adwlk1.mod /id:59 +model=adwlk2.mod /id:60 +model=adwlk3.mod /id:61 +model=arban1.mod /id:62 +model=arban2.mod /id:63 +model=arban3.mod /id:64 +model=arban4.mod /id:65 +model=arban5.mod /id:66 +model=arban6.mod /id:67 +model=bwlk1.mod /id:68 +model=bdet4.mod /id:69 +model=hn1.mod /id:85 +model=pdsh.mod /id:86 +model=sl2.mod /id:87 +model=twr.mod /id:88 +model=plit.mod /id:89 +model=gnr.mod /id:90 +model=tnt.mod /id:91 +model=bnk.mod /id:92 +model=msl.mod /id:93 +model=crt.mod /id:94 +model=hut.mod /id:95 +model=ft1.mod /id:96 +model=ft2.mod /id:97 +model=wst.mod /id:98 +model=mslg.mod /id:99 +model=fp0.mod /id:100 +model=fp1.mod /id:101 +model=fp2.mod /id:102 +model=fp3.mod /id:103 +model=hc1.mod /id:104 +model=hc2.mod /id:105 +model=hwz.mod /id:106 +//model=jax1.mod /id:107 +//model=jax2.mod /id:108 +model=ab07.mod /id:109 +// +// Maps +// +map=arena1.map /id:70 +map=arena2.map /id:84 +map=rav.map /id:71 +map=des.map /id:119 +map=grass.map +map=polar3.map /id:81 +map=polar4.map /id:82 +map=dbase.map +zone=all.zne + +[zones] +zone=all.zne + \ No newline at end of file diff --git a/CONTENT/BT/BTLOOK.BAT b/CONTENT/BT/BTLOOK.BAT new file mode 100644 index 0000000..6beb8c4 --- /dev/null +++ b/CONTENT/BT/BTLOOK.BAT @@ -0,0 +1,12 @@ +@echo off +rem ------------------------------------------------------------------ +rem L4EYES=x y z pitch yaw roll [relative] +rem ------------------------------------------------------------------ +set L4EYES=195 4 250 2 60.5 0 +if "%1"=="arena0" set L4EYES= 45 4 142 2 10.5 0 +rem if "%1"=="arena1" set L4EYES=-229 4 -131 2 200.0 0 +if "%1"=="arena1" set L4EYES=195 4 250 2 60.5 0 +set L4VIEWEXT=True +rem ------------------------------------------------------------------ +call btprep.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +menu.bat short diff --git a/CONTENT/BT/BTNET.BAT b/CONTENT/BT/BTNET.BAT new file mode 100644 index 0000000..bc112b2 --- /dev/null +++ b/CONTENT/BT/BTNET.BAT @@ -0,0 +1,22 @@ +@echo off +call setenv.bat t s n n +call showenv.bat +set a0= +if exist btl4d3s.exe set a0=btl4d3s.exe +if exist btl4d2s.exe set a0=btl4d2s.exe +if exist btl4d0.exe set a0=btl4d0.exe +if exist btl4opt.exe set a0=btl4opt.exe +if "%a0%"=="" goto error +echo on +32rtm.exe -x +netnub.exe -f %a0% +32rtm.exe -u +@echo off +goto end +:error +echo. +echo Program not found in current directory. +echo. +:end +set a0= +menu.bat short diff --git a/CONTENT/BT/BTPREP.BAT b/CONTENT/BT/BTPREP.BAT new file mode 100644 index 0000000..cc5f449 --- /dev/null +++ b/CONTENT/BT/BTPREP.BAT @@ -0,0 +1,44 @@ +@echo off +rem +rem usage: btprep.bat [course [vehicle [dropzone [inifile]]]] +rem +rem ------------------------------------------------------------------ +rem L4ANIMATION=scale (default = 1.0 NEVER make zero or negative) +rem ------------------------------------------------------------------ +set L4ANIMATION=1.0 +rem ------------------------------------------------------------------ +if "%1"=="" set a1=arena1 +if not "%1"=="" set a1=%1 +if not exist maps\%a1%.map goto nomap +rem ------------------------------------------------------------------ +if "%2"=="" set a2=thor +if not "%2"=="" set a2=%2 +if not exist models\%a2%.mod goto noveh +rem ------------------------------------------------------------------ +set A4DPLCFG= +if "%4"=="" goto bt +set A4DPLCFG=%4.ini +if not exist %A4DPLCFG% goto noenv +rem ------------------------------------------------------------------ +:bt +call makeegg.bat %a1% %a2% %3 +call bt.bat temp +goto end +:nomap +echo. +echo Course '%a1%' not found. +echo. +goto end +:noveh +echo. +echo Vehicle '%a2%' not found. +echo. +goto end +:noenv +echo. +echo Renderer configuration file '%A4DPLCFG%' not found. +echo. +goto end +:end +set a2= +set a1= diff --git a/CONTENT/BT/BUILD.BAT b/CONTENT/BT/BUILD.BAT new file mode 100644 index 0000000..fe7342b --- /dev/null +++ b/CONTENT/BT/BUILD.BAT @@ -0,0 +1,6 @@ +@echo off +rem build.bat +set s0=test.bld +if not exist %s0% set s0= +btl4tool.exe -b btl4.bld %s0% +set s0= diff --git a/CONTENT/BT/BUILD1.BAT b/CONTENT/BT/BUILD1.BAT new file mode 100644 index 0000000..12c5dc2 --- /dev/null +++ b/CONTENT/BT/BUILD1.BAT @@ -0,0 +1,82 @@ +@REM ************************************************************************** +@REM * BUILDRES.BAT - 11-11-96 cpb * +@REM * This file is intended to simplify the development of BTL4 resources * +@REM * on a Win95 system. It must be executed under MS-DOS (but NOT in a * +@REM * "dos box": the current tools won't run at all under Win32)! * +@REM * See the document "Modifying Resources" for more information. * +@REM ************************************************************************** +@ECHO ON +xdel d:\dev\*.bak /s /n +set Path=c:\nwdos;c:\nwclient;c:\net;c:\pkware;d:\dev\bt;d:\dev\bt\models +d: +cd \dev\bt +cd models +@echo Building Mechs... > ..\result1.txt +@echo Building avatar... >> ..\result1.txt +mechbld avatar.mch >> ..\result1.txt +@echo Building blkhawk... >> ..\result1.txt +mechbld blkhawk.mch >> ..\result1.txt +@echo Building loki... >> ..\result1.txt +mechbld loki.mch >> ..\result1.txt +@echo Building madcat... >> ..\result1.txt +mechbld madcat.mch >> ..\result1.txt +@echo Building owens... >> ..\result1.txt +mechbld owens.mch >> ..\result1.txt +@echo Building sunder... >> ..\result1.txt +mechbld sunder.mch >> ..\result1.txt +@echo Building thor... >> ..\result1.txt +mechbld thor.mch >> ..\result1.txt +@echo Building vulture... >> ..\result1.txt +mechbld vulture.mch >> ..\result1.txt +@rem @echo Building firestarter... >> ..\result1.txt +@rem mechbld firstrtr.mch >> ..\result1.txt +@rem @echo Building blackjack... >> ..\result1.txt +@rem mechbld blkjack.mch >> ..\result1.txt +@echo Building ava1... >> ..\result1.txt +mechbld ava1.mch >> ..\result1.txt +@echo Building bhk1... >> ..\result1.txt +mechbld bhk1.mch >> ..\result1.txt +@echo Building Lok1... >> ..\result1.txt +mechbld lok1.mch >> ..\result1.txt +@echo Building Lok2... >> ..\result1.txt +mechbld lok2.mch >> ..\result1.txt +@echo Building mad1... >> ..\result1.txt +mechbld mad1.mch >> ..\result1.txt +@echo Building mad2... >> ..\result1.txt +mechbld mad2.mch >> ..\result1.txt +@echo Building thr1... >> ..\result1.txt +mechbld thr1.mch >> ..\result1.txt +@echo Building vul1... >> ..\result1.txt +mechbld vul1.mch >> ..\result1.txt +@echo Building own1... >> ..\result1.txt +mechbld own1.mch >> ..\result1.txt +@echo Building snd1... >> ..\result1.txt +mechbld snd1.mch >> ..\result1.txt +@REM @echo Building snd2... >> ..\result1.txt +@REM mechbld snd2.mch >> ..\result1.txt +@REM @echo Building vul2... >> ..\result1.txt +@REM mechbld vul2.mch >> ..\result1.txt +@REM @echo Building thr6... >> ..\result1.txt +@REM mechbld thr6.mch >> ..\result1.txt +@REM @echo Building ava2... >> ..\result1.txt +@REM mechbld ava2.mch >> ..\result1.txt + +@rem @echo Building raptor... >> ..\result1.txt +@rem mechbld raptor.mch >> ..\result1.txt +@rem @echo Building strider... >> ..\result1.txt +@rem mechbld strider.mch >> ..\result1.txt +@REM @echo Building bat... >> ..\result1.txt +@REM mechbld bat.mch >> ..\result1.txt +cd .. +btl4tool -b btl4.bld >> result1.txt +rem call arcbt f . >> result1.txt +rem del c:\vgl_labs\archive\bt%1.exe +rem copy bt.zip c:\vgl_labs\archive\bt%1.zip +rem del bt.zip +rem c: +rem cd c:\vgl_labs\archive +rem zip2exe bt%1.zip +rem del bt%1.zip +rem d: +rem cd d:\dev\bt +rem edit result1.txt diff --git a/CONTENT/BT/BUILDRES.BAT b/CONTENT/BT/BUILDRES.BAT new file mode 100644 index 0000000..ea3464a --- /dev/null +++ b/CONTENT/BT/BUILDRES.BAT @@ -0,0 +1,82 @@ +@REM ************************************************************************** +@REM * BUILDRES.BAT - 11-11-96 cpb * +@REM * This file is intended to simplify the development of BTL4 resources * +@REM * on a Win95 system. It must be executed under MS-DOS (but NOT in a * +@REM * "dos box": the current tools won't run at all under Win32)! * +@REM * See the document "Modifying Resources" for more information. * +@REM ************************************************************************** +@ECHO ON +xdel d:\dev\*.bak /s /n +set Path=c:\nwdos;c:\nwclient;c:\net;c:\pkware;d:\dev\bt;d:\dev\bt\models +d: +cd \dev\bt +cd models +@echo Building Mechs... > ..\result1.txt +@echo Building avatar... >> ..\result1.txt +mechbld avatar.mch >> ..\result1.txt +@echo Building blkhawk... >> ..\result1.txt +mechbld blkhawk.mch >> ..\result1.txt +@echo Building loki... >> ..\result1.txt +mechbld loki.mch >> ..\result1.txt +@echo Building madcat... >> ..\result1.txt +mechbld madcat.mch >> ..\result1.txt +@echo Building owens... >> ..\result1.txt +mechbld owens.mch >> ..\result1.txt +@echo Building sunder... >> ..\result1.txt +mechbld sunder.mch >> ..\result1.txt +@echo Building thor... >> ..\result1.txt +mechbld thor.mch >> ..\result1.txt +@echo Building vulture... >> ..\result1.txt +mechbld vulture.mch >> ..\result1.txt +@rem @echo Building firestarter... >> ..\result1.txt +@rem mechbld firstrtr.mch >> ..\result1.txt +@rem @echo Building blackjack... >> ..\result1.txt +@rem mechbld blkjack.mch >> ..\result1.txt +@echo Building ava1... >> ..\result1.txt +mechbld ava1.mch >> ..\result1.txt +@echo Building bhk1... >> ..\result1.txt +mechbld bhk1.mch >> ..\result1.txt +@echo Building Lok1... >> ..\result1.txt +mechbld lok1.mch >> ..\result1.txt +@echo Building Lok2... >> ..\result1.txt +mechbld lok2.mch >> ..\result1.txt +@echo Building mad1... >> ..\result1.txt +mechbld mad1.mch >> ..\result1.txt +@echo Building mad2... >> ..\result1.txt +mechbld mad2.mch >> ..\result1.txt +@echo Building thr1... >> ..\result1.txt +mechbld thr1.mch >> ..\result1.txt +@echo Building vul1... >> ..\result1.txt +mechbld vul1.mch >> ..\result1.txt +@echo Building own1... >> ..\result1.txt +mechbld own1.mch >> ..\result1.txt +@echo Building snd1... >> ..\result1.txt +mechbld snd1.mch >> ..\result1.txt +@REM @echo Building snd2... >> ..\result1.txt +@REM mechbld snd2.mch >> ..\result1.txt +@REM @echo Building vul2... >> ..\result1.txt +@REM mechbld vul2.mch >> ..\result1.txt +@REM @echo Building thr6... >> ..\result1.txt +@REM mechbld thr6.mch >> ..\result1.txt +@REM @echo Building ava2... >> ..\result1.txt +@REM mechbld ava2.mch >> ..\result1.txt + +@rem @echo Building raptor... >> ..\result1.txt +@rem mechbld raptor.mch >> ..\result1.txt +@rem @echo Building strider... >> ..\result1.txt +@rem mechbld strider.mch >> ..\result1.txt +@REM @echo Building bat... >> ..\result1.txt +@REM mechbld bat.mch >> ..\result1.txt +cd .. +btl4tool -b btl4.bld >> result1.txt +call arcbt f . >> result1.txt +del c:\vgl_labs\archive\bt%1.exe +copy bt.zip c:\vgl_labs\archive\bt%1.zip +del bt.zip +c: +cd c:\vgl_labs\archive +zip2exe bt%1.zip +del bt%1.zip +d: +cd d:\dev\bt +rem edit result1.txt diff --git a/CONTENT/BT/DEARCBT.BAT b/CONTENT/BT/DEARCBT.BAT new file mode 100644 index 0000000..abd65cb --- /dev/null +++ b/CONTENT/BT/DEARCBT.BAT @@ -0,0 +1,19 @@ +rem -------------------------------------- +rem - %1=o restore to the directory +rem - %1=f freshen to the directory +rem - %2=path to the zipfile +rem -------------------------------------- + +if "%1"=="o" goto RESTORE + +if "%1"=="f" goto FRESHEN + +:RESTORE +pkunzip -o -d %2\bt.zip +goto END + +:FRESHEN +pkunzip -n -d %2\bt.zip +goto END + +:END diff --git a/CONTENT/BT/EXCLUDE.LST b/CONTENT/BT/EXCLUDE.LST new file mode 100644 index 0000000..001f660 --- /dev/null +++ b/CONTENT/BT/EXCLUDE.LST @@ -0,0 +1,7 @@ +joystick.ini +anims\vcs.cfg +audio\vcs.cfg +gauge\vcs.cfg +maps\vcs.cfg +models\vcs.cfg +solids\vcs.cfg diff --git a/CONTENT/BT/FAILURE.LOG b/CONTENT/BT/FAILURE.LOG new file mode 100644 index 0000000..ecf86ed --- /dev/null +++ b/CONTENT/BT/FAILURE.LOG @@ -0,0 +1,12 @@ +[RIOBoardErrors] +error=missing_board@Slot=5:Address=0 +[RIODeadLamps] +lamp=TeslaRelay3 +lamp=undefined_0x17 +lamp=TeslaRelay1 +lamp=PanicButton +lamp=IcomAmpEnableRelay +lamp=IcomIncRelay +lamp=IcomPTTRelay +lamp=undefined_0x3D +lamp=FloorEntry diff --git a/CONTENT/BT/FILELIST b/CONTENT/BT/FILELIST new file mode 100644 index 0000000..4660224 --- /dev/null +++ b/CONTENT/BT/FILELIST @@ -0,0 +1,68 @@ + +---------- c:filelist +--a--- 249 3-06-97 1:48a c:\btravine\models\swiftwnd.mod +--a--- 247 3-06-97 1:48a c:\btravine\models\striker.mod +--a--- 247 3-06-97 1:48a c:\btravine\models\srmcarry.mod +--a--- 247 3-06-97 1:48a c:\btravine\models\semirig.mod +--a--- 240 3-06-97 1:48a c:\btravine\models\semi.mod +--a--- 243 3-06-97 1:48a c:\btravine\models\rommel.mod +--a--- 249 3-06-97 1:48a c:\btravine\models\mechmovr.mod +--a--- 247 3-06-97 1:48a c:\btravine\models\lrmcarry.mod +--a--- 244 3-06-97 1:48a c:\btravine\models\hummer.mod +--a--- 249 3-06-97 1:48a c:\btravine\models\harasser.mod +--a--- 241 3-06-97 1:48a c:\btravine\models\dozer.mod +--a--- 246 3-06-97 1:48a c:\btravine\models\coolant.mod +--a--- 247 3-06-97 1:48a c:\btravine\models\comtruck.mod +--a--- 246 3-06-97 1:48a c:\btravine\models\bulldog.mod +--a--- 248 3-06-97 1:48a c:\btravine\models\armrmovr.mod +--a--- 237 3-06-97 1:48a c:\btravine\models\apc.mod +--a--- 65,606 3-06-97 12:59a c:\btravine\video\tex\bexp.bsl +--a--- 32,886 3-06-97 12:46a c:\btravine\video\tex\basev.bsl +DIRECTORY 3-06-97 12:40a c:\btravine\video\mat\grass\.. +DIRECTORY 3-06-97 12:40a c:\btravine\video\mat\grass\. +DIRECTORY 3-06-97 12:40a c:\btravine\video\mat\grass +--a--- 2,880 3-06-97 12:40a c:\btravine\video\mat\grass\basev.bmf +--a--- 24,087 3-06-97 12:40a c:\btravine\video\geo\swiftwnd.bgf +--a--- 14,760 3-06-97 12:40a c:\btravine\video\geo\swiftd.bgf +--a--- 19,052 3-06-97 12:40a c:\btravine\video\geo\striker.bgf +--a--- 10,537 3-06-97 12:40a c:\btravine\video\geo\strikd.bgf +--a--- 9,411 3-06-97 12:40a c:\btravine\video\geo\srmd.bgf +--a--- 14,943 3-06-97 12:40a c:\btravine\video\geo\srmcarry.bgf +--a--- 15,853 3-06-97 12:40a c:\btravine\video\geo\semirig.bgf +--a--- 8,359 3-06-97 12:40a c:\btravine\video\geo\semird.bgf +--a--- 11,085 3-06-97 12:40a c:\btravine\video\geo\semid.bgf +--a--- 22,307 3-06-97 12:40a c:\btravine\video\geo\semi.bgf +--a--- 16,697 3-06-97 12:40a c:\btravine\video\geo\rommel.bgf +--a--- 10,870 3-06-97 12:40a c:\btravine\video\geo\romd.bgf +--a--- 27,552 3-06-97 12:40a c:\btravine\video\geo\mechmovr.bgf +--a--- 14,832 3-06-97 12:40a c:\btravine\video\geo\mechmd.bgf +--a--- 8,600 3-06-97 12:40a c:\btravine\video\geo\lrmd.bgf +--a--- 9,584 3-06-97 12:40a c:\btravine\video\geo\lrmcarry.bgf +--a--- 16,626 3-06-97 12:40a c:\btravine\video\geo\hummer.bgf +--a--- 9,068 3-06-97 12:40a c:\btravine\video\geo\hummd.bgf +--a--- 9,556 3-06-97 12:40a c:\btravine\video\geo\harsrd.bgf +--a--- 21,446 3-06-97 12:40a c:\btravine\video\geo\harasser.bgf +--a--- 15,038 3-06-97 12:40a c:\btravine\video\geo\dozer.bgf +--a--- 9,343 3-06-97 12:40a c:\btravine\video\geo\dozd.bgf +--a--- 15,545 3-06-97 12:40a c:\btravine\video\geo\coold.bgf +--a--- 25,909 3-06-97 12:40a c:\btravine\video\geo\coolant.bgf +--a--- 26,916 3-06-97 12:40a c:\btravine\video\geo\comtruck.bgf +--a--- 12,188 3-06-97 12:40a c:\btravine\video\geo\comd.bgf +--a--- 12,730 3-06-97 12:40a c:\btravine\video\geo\bulldog.bgf +--a--- 8,129 3-06-97 12:40a c:\btravine\video\geo\bulld.bgf +--a--- 22,889 3-06-97 12:40a c:\btravine\video\geo\armrmovr.bgf +--a--- 11,050 3-06-97 12:40a c:\btravine\video\geo\armrd.bgf +--a--- 10,839 3-06-97 12:39a c:\btravine\video\geo\apcd.bgf +--a--- 22,590 3-06-97 12:39a c:\btravine\video\geo\apc.bgf +--a--- 381 3-05-97 11:48p c:\btravine\video\mat\grass.bmf +--a--- 65,578 3-05-97 11:17p c:\btravine\video\tex\tree.bsl +--a--- 291 3-05-97 10:21p c:\btravine\video\geo\treesh.bgf +--a--- 2,761 3-05-97 10:02p c:\btravine\video\geo\tree.bgf +--a--- 6,381 3-05-97 8:59p c:\btravine\video\geo\hillg3.bgf +--a--- 6,189 3-05-97 8:42p c:\btravine\video\geo\hillg2.bgf +--a--- 8,241 3-05-97 8:25p c:\btravine\video\geo\hillg1.bgf +--a--- 14,755 3-05-97 6:50p c:\btravine\video\geo\grnd100.bgf +--a--- 49,209 3-04-97 5:17p c:\btravine\video\tex\grassc.vtx +--a--- 49,209 3-04-97 5:17p c:\btravine\video\mat\grassb.vtx +--a--- 49,209 3-04-97 5:16p c:\btravine\video\mat\grassc.vtx +--a--- 6,791 3-04-97 4:35p c:\btravine\video\geo\bcone1.bgf diff --git a/CONTENT/BT/GAUGE/AB01_GA.GIM b/CONTENT/BT/GAUGE/AB01_GA.GIM new file mode 100644 index 0000000..b09f101 --- /dev/null +++ b/CONTENT/BT/GAUGE/AB01_GA.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=20, 0, 50 +v1=-69, 0, 50 +v2=-69, 0, -50 +v3=20, 0, -50 + +[level0] +linelist=a_bld v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/AB02_GA.GIM b/CONTENT/BT/GAUGE/AB02_GA.GIM new file mode 100644 index 0000000..04db4ca --- /dev/null +++ b/CONTENT/BT/GAUGE/AB02_GA.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=25, 0, 45 +v1=-25, 0, 45 +v2=-25, 0, -45 +v3=25, 0, -45 + +[level0] +linelist=a_bld v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/AB03_GA.GIM b/CONTENT/BT/GAUGE/AB03_GA.GIM new file mode 100644 index 0000000..b3a9879 --- /dev/null +++ b/CONTENT/BT/GAUGE/AB03_GA.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=68, 0, 50 +v1=-20, 0, 50 +v2=-20, 0, -50 +v3=68, 0, -50 + +[level0] +linelist=a_bld v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/AB04_GA.GIM b/CONTENT/BT/GAUGE/AB04_GA.GIM new file mode 100644 index 0000000..723bd2a --- /dev/null +++ b/CONTENT/BT/GAUGE/AB04_GA.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=38, 0, 38 +v1=-37, 0, 38 +v2=-37, 0, -51 +v3=38, 0, -51 + +[level0] +linelist=a_bld v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/AB05_GA.GIM b/CONTENT/BT/GAUGE/AB05_GA.GIM new file mode 100644 index 0000000..ab8b5b0 --- /dev/null +++ b/CONTENT/BT/GAUGE/AB05_GA.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=150, 0, 44 +v1=-150, 0, 44 +v2=-150, 0, -45 +v3=150, 0, -45 + +[level0] +linelist=a_bld v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/AB06_GA.GIM b/CONTENT/BT/GAUGE/AB06_GA.GIM new file mode 100644 index 0000000..0fe0e4c --- /dev/null +++ b/CONTENT/BT/GAUGE/AB06_GA.GIM @@ -0,0 +1,29 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=3000 +level1=10000 + +[vertices] +v0=50, 0, -7 +v1=35, 0, -7 +v2=35, 0, -33 +v3=50, 0, -33 +v4=50, 0, 33 +v5=35, 0, 33 +v6=35, 0, 7 +v7=50, 0, 7 +v8=50, 0, 50 +v9=-50, 0, 50 +v10=-50, 0, -50 +v11=50, 0, -50 + +[level0] +linelist=a_bay v0 v1 v2 v3 v0 +linelist=a_bay v4 v5 v6 v7 v4 +linelist=a_hanger v8 v9 v10 v11 v8 + +[level1] +linelist=a_hanger v8 v9 v10 v11 v8 + diff --git a/CONTENT/BT/GAUGE/AB07_GA.GIM b/CONTENT/BT/GAUGE/AB07_GA.GIM new file mode 100644 index 0000000..34d357b --- /dev/null +++ b/CONTENT/BT/GAUGE/AB07_GA.GIM @@ -0,0 +1,20 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=2500 +level1=10000 + +[vertices] +v0=10, 0, 15 +v1=0, 0, 15 +v2=-15, 0, 0 +v3=-15, 0, -10 +v4=10, 0, -10 + +[level0] +linelist=a_hanger v0 v1 v2 v3 v4 v0 + +[level1] +linelist=a_hanger v0 v1 v2 v3 v4 v0 + diff --git a/CONTENT/BT/GAUGE/AB08_GA.GIM b/CONTENT/BT/GAUGE/AB08_GA.GIM new file mode 100644 index 0000000..f90ec6d --- /dev/null +++ b/CONTENT/BT/GAUGE/AB08_GA.GIM @@ -0,0 +1,16 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=60, 0, -60 +v1=60, 0, -2.62268e-06 +v2=2.62268e-06, 0, 60 +v3=-60, 0, 60 +v4=-60, 0, -60 + +[level0] +linelist=a_stands v0 v1 v2 v3 v4 v0 + diff --git a/CONTENT/BT/GAUGE/AB09_GA.GIM b/CONTENT/BT/GAUGE/AB09_GA.GIM new file mode 100644 index 0000000..b5fc55c --- /dev/null +++ b/CONTENT/BT/GAUGE/AB09_GA.GIM @@ -0,0 +1,25 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=7, 0, 23 +v1=7, 0, 6 +v2=33, 0, 6 +v3=33, 0, 23 +v4=-33, 0, 23 +v5=-33, 0, 6 +v6=-7, 0, 6 +v7=-7, 0, 23 +v8=-50, 0, 23 +v9=-50, 0, -27 +v10=50, 0, -27 +v11=50, 0, 23 + +[level0] +linelist=a_bay v0 v1 v2 v3 v0 +linelist=a_bay v4 v5 v6 v7 v4 +linelist=a_hanger v8 v9 v10 v11 v8 + diff --git a/CONTENT/BT/GAUGE/AB10_GA.GIM b/CONTENT/BT/GAUGE/AB10_GA.GIM new file mode 100644 index 0000000..cd7d52b --- /dev/null +++ b/CONTENT/BT/GAUGE/AB10_GA.GIM @@ -0,0 +1,29 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=2000 +level1=10000 + +[vertices] +v0=7, 0, -23 +v1=33, 0, -23 +v2=33, 0, -6 +v3=7, 0, -6 +v4=-33, 0, -23 +v5=-7, 0, -23 +v6=-7, 0, -6 +v7=-33, 0, -6 +v8=-50, 0, -23 +v9=50, 0, -23 +v10=50, 0, 27 +v11=-50, 0, 27 + +[level0] +linelist=a_bay v0 v1 v2 v3 v0 +linelist=a_bay v4 v5 v6 v7 v4 +linelist=a_hanger v8 v9 v10 v11 v8 + +[level1] +linelist=a_hanger v8 v9 v10 v11 v8 + diff --git a/CONTENT/BT/GAUGE/AD01_GA.GIM b/CONTENT/BT/GAUGE/AD01_GA.GIM new file mode 100644 index 0000000..7a0e541 --- /dev/null +++ b/CONTENT/BT/GAUGE/AD01_GA.GIM @@ -0,0 +1,40 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=3000 +level1=10000 + +[vertices] +v0=14, 0, -7 +v1=-9, 0, -7 +v2=-9, 0, -11 +v3=14, 0, -11 +v4=55, 0, 9 +v5=28, 0, 9 +v6=55, 0, -18 +v7=28, 0, -1 +v8=15, 0, -1 +v9=15, 0, -18 +v10=-10, 0, -1 +v11=-23, 0, -1 +v12=-10, 0, -18 +v13=-50, 0, -18 +v14=-50, 0, 9 +v15=-23, 0, 9 + +[level0] +linelist=a_door v0 v1 v2 v3 v0 +linelist=a_wall v4 v5 v6 v4 +linelist=a_wall v5 v7 v6 v5 +linelist=a_wall v8 v9 v7 v8 +linelist=a_wall v7 v9 v6 v7 +linelist=a_wall v10 v11 v12 v10 +linelist=a_wall v12 v11 v13 v12 +linelist=a_wall v13 v11 v14 v13 +linelist=a_wall v11 v15 v14 v11 + +[level1] +linelist=a_door v0 v1 v2 v3 v0 +linelist=a_wall v4 v14 v13 v6 v4 + diff --git a/CONTENT/BT/GAUGE/ADPAL.PCC b/CONTENT/BT/GAUGE/ADPAL.PCC new file mode 100644 index 0000000000000000000000000000000000000000..987e374f03fc06f3927e885df9f1ff0c9f731379 GIT binary patch literal 907 zcmeIup-%#F7{>AMF&$3b2p0?l1HnKb5DW%_!9XAw393aJcIF)c?IJw_YTHK<`axG NTRSEF_jeXZ(=RV)tr7qL literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ADPAL2.PCC b/CONTENT/BT/GAUGE/ADPAL2.PCC new file mode 100644 index 0000000000000000000000000000000000000000..fe29ea2c9e8b28cb109e86bf1a6c8c6235c121c6 GIT binary patch literal 907 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 aCj_OFwS4e!-wy}-|MR~B|GEO}_4+S29rhdm literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BLD03_GA.GIM b/CONTENT/BT/GAUGE/BLD03_GA.GIM new file mode 100644 index 0000000..51de1e5 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD03_GA.GIM @@ -0,0 +1,26 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-29, 0, -17 +v1=17, 0, -17 +v2=17, 0, 11 +v3=-29, 0, 11 + +v4=1, 0, -23 +v5=29, 0, -23 +v6=29, 0, 23 +v7=1, 0, 23 + +v8=10, 0, 5 +v9=20, 0, 5 +v10=20, 0, 15 +v11=10, 0, 15 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 +linelist=a_bunker v8 v9 v10 v11 v8 \ No newline at end of file diff --git a/CONTENT/BT/GAUGE/BLD04_GA.GIM b/CONTENT/BT/GAUGE/BLD04_GA.GIM new file mode 100644 index 0000000..1479251 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD04_GA.GIM @@ -0,0 +1,24 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-7, 0, 9 +v1=-7, 0, 20 +v2=6.5, 0, 20 +v3=6.5, 0, 9 +v4=-12, 0, -17 +v5=-12, 0, 3 +v6=12, 0, 3 +v7=12, 0, -17 +v8=-5.5, 0, 3 +v9=-5.5, 0, 9 +v10=4.5, 0, 9 +v11=4.5, 0, 3 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 +linelist=a_bunker v8 v9 v10 v11 v8 diff --git a/CONTENT/BT/GAUGE/BLD06_GA.GIM b/CONTENT/BT/GAUGE/BLD06_GA.GIM new file mode 100644 index 0000000..e540372 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD06_GA.GIM @@ -0,0 +1,50 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-20.0781, 0, -7.04688 +v1=-2.92188, 0, -7.04688 +v2=-2.92188, 0, 11.0469 +v3=-20.0781, 0, 11.0469 + +v4=2.92188, 0, -7.04688 +v5=20.0781, 0, -7.04688 +v6=20.0781, 0, 11.0469 +v7=2.92188, 0, 11.0469 + +v8=-9.07812, 0, -3.04688 +v9=9.07812, 0, -3.04688 +v10=9.07812, 0, 15.0469 +v11=-9.07812, 0, 15.0469 + +v12=20, 0, -10 +v13=22, 0, -10 +v14=22, 0, -3 +v15=20, 0, -3 + +v16=2.54688, 0, -10 +v17=4.54688, 0, -10 +v18=4.54688, 0, -3 +v19=2.54688, 0, -3 + +v20=-21.9219, 0, -10 +v21=-19.9219, 0, -10 +v22=-19.9219, 0, -3 +v23=-21.9219, 0, -3 + +v24=-4.46094, 0, -10 +v25=-2.46094, 0, -10 +v26=-2.46094, 0, -3 +v27=-4.46094, 0, -3 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 +linelist=a_bunker v8 v9 v10 v11 v8 +linelist=a_bunker v12 v13 v14 v15 v12 +linelist=a_bunker v16 v17 v18 v19 v16 +linelist=a_bunker v20 v21 v22 v23 v20 +linelist=a_bunker v24 v25 v26 v27 v24 \ No newline at end of file diff --git a/CONTENT/BT/GAUGE/BLD08_GA.GIM b/CONTENT/BT/GAUGE/BLD08_GA.GIM new file mode 100644 index 0000000..2e040a4 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD08_GA.GIM @@ -0,0 +1,146 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=35.5, 0, -21.5 +v1=46.5, 0, -21.5 +v2=45.5, 0, -19 +v3=35.5, 0, -19 + +v4=-10.5, 0, -21.5 +v5=0.5, 0, -21.5 +v6=0.5, 0, -19 +v7=-10.5, 0, -19 + +v8=31.5, 0, -37 +v9=50.5, 0, -37 +v10=50.5, 0, -21.5 +v11=31.5, 0, -21.5 + +v12=-14.5, 0, -37 +v13=4.5, 0, -37 +v14=4.5, 0, -21.5 +v15=-14.5, 0, -21.5 + +v16=8, 0, -40 +v17=28.5, 0, -40 +v18=28.5, 0, -28 +v19=8, 0, -28 + +v20=8, 0, -28 +v21=28.5, 0, -28 +v22=28.5, 0, -19 +v23=8, 0, -19 + +v24=4.5, 0, -40 +v25=8, 0, -40 +v26=8, 0, -19 +v27=4.5, 0, -19 + +v28=-38, 0, -40 +v29=-18, 0, -40 +v30=-18, 0, -28 +v31=-38, 0, -28 + +v32=-38, 0, -28 +v33=-18, 0, -28 +v34=-18, 0, -19 +v35=-38, 0, -19 + +v36=-42, 0, -40 +v37=-38, 0, -40 +v38=-38, 0, -19 +v39=-42, 0, -19 + +v40=-18, 0, -40 +v41=-14.5, 0, -40 +v42=-14.5, 0, -19 +v43=-18, 0, -19 + +v44=54.5, 0, -40 +v45=74.5, 0, -40 +v46=74.5, 0, -28 +v47=54.5, 0, -28 + +v48=54.5, 0, -28 +v49=74.5, 0, -28 +v50=74.5, 0, -19 +v51=54.5, 0, -19 + +v52=50.5, 0, -40 +v53=54.5, 0, -40 +v54=54.5, 0, -19 +v55=50.5, 0, -19 + +v56=74.5, 0, -40 +v57=77.75, 0, -40 +v58=77.75, 0, -19 +v59=74.5, 0, -19 + +v60=-58, 0, -28 +v61=-40, 0, -28 +v62=-40, 0, -8 +v63=-58, 0, -8 + +v64=-83, 0, -19 +v65=-63, 0, -19 +v66=-63, 0, -6 +v67=-83, 0, -6 + +v68=-63, 0, -19 +v69=-52, 0, -19 +v70=-52, 0, -6 +v71=-63, 0, -6 + +v72=-87, 0, -19 +v73=-83, 0, -19 +v74=-83, 0, -6 +v75=-87, 0, -6 + +v76=-87, 0, -6 +v77=-52, 0, -6 +v78=-52, 0, 8.5 +v79=-87, 0, 8.5 + +v80=-82, 0, 8.5 +v81=-58, 0, 8.5 +v82=-58, 0, 14.5 +v83=-82, 0, 14.5 + +v84=-87, 0, 14.5 +v85=-52, 0, 14.5 +v86=-52, 0, 40 +v87=-87, 0, 40 + +v88=31.5, 0, -40 +v89=28.5, 0, -40 +v90=28.5, 0, -19 +v91=31.5, 0, -19 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 +linelist=a_bunker v8 v9 v10 v11 v8 +linelist=a_bunker v12 v13 v14 v15 v12 +linelist=a_bunker v20 v21 v22 v23 v20 +linelist=a_bunker v24 v25 v26 v27 v24 +linelist=a_bunker v32 v33 v34 v35 v32 +linelist=a_bunker v36 v37 v38 v39 v36 +linelist=a_bunker v40 v41 v42 v43 v40 +linelist=a_bunker v48 v49 v50 v51 v48 +linelist=a_bunker v52 v53 v54 v55 v52 +linelist=a_bunker v56 v57 v58 v59 v56 +linelist=a_bunker v60 v61 v62 v63 v60 +linelist=a_bunker v68 v69 v70 v71 v68 +linelist=a_bunker v72 v73 v74 v75 v72 +linelist=a_bunker v76 v77 v78 v79 v76 +linelist=a_bunker v80 v81 v82 v83 v80 +linelist=a_bunker v84 v85 v86 v87 v84 +linelist=a_bunker v88 v89 v90 v91 v88 +linelist=a_hanger v16 v17 v18 v19 v16 +linelist=a_hanger v28 v29 v30 v31 v28 +linelist=a_hanger v44 v45 v46 v47 v44 +linelist=a_hanger v64 v65 v66 v67 v64 diff --git a/CONTENT/BT/GAUGE/BLD08_GA.ORG b/CONTENT/BT/GAUGE/BLD08_GA.ORG new file mode 100644 index 0000000..8f66da1 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD08_GA.ORG @@ -0,0 +1,146 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=35.5, 0, -21.5 +v1=46.5, 0, -21.5 +v2=45.5, 0, -19 +v3=35.5, 0, -19 + +v4=-10.5, 0, -21.5 +v5=0.5, 0, -21.5 +v6=0.5, 0, -19 +v7=-10.5, 0, -19 + +v8=31.5, 0, -37 +v9=50.5, 0, -37 +v10=50.5, 0, -21.5 +v11=31.5, 0, -21.5 + +v12=-14.5, 0, -37 +v13=4.5, 0, -37 +v14=4.5, 0, -21.5 +v15=-14.5, 0, -21.5 + +v16=8, 0, -40 +v17=28.5, 0, -40 +v18=28.5, 0, -28 +v19=8, 0, -28 + +v20=8, 0, -28 +v21=28.5, 0, -28 +v22=28.5, 0, -19 +v23=8, 0, -19 + +v24=4.5, 0, -40 +v25=8, 0, -40 +v26=8, 0, -19 +v27=4.5, 0, -19 + +v28=-38, 0, -40 +v29=-18, 0, -40 +v30=-18, 0, -28 +v31=-38, 0, -28 + +v32=-38, 0, -28 +v33=-18, 0, -28 +v34=-18, 0, -19 +v35=-38, 0, -19 + +v36=-42, 0, -40 +v37=-38, 0, -40 +v38=-38, 0, -19 +v39=-42, 0, -19 + +v40=-18, 0, -40 +v41=-14.5, 0, -40 +v42=-14.5, 0, -19 +v43=-18, 0, -19 + +v44=54.5, 0, -40 +v45=74.5, 0, -40 +v46=74.5, 0, -28 +v47=54.5, 0, -28 + +v48=54.5, 0, -28 +v49=74.5, 0, -28 +v50=74.5, 0, -19 +v51=54.5, 0, -19 + +v52=50.5, 0, -40 +v53=54.5, 0, -40 +v54=54.5, 0, -19 +v55=50.5, 0, -19 + +v56=74.5, 0, -40 +v57=77.75, 0, -40 +v58=77.75, 0, -19 +v59=74.5, 0, -19 + +v60=-58, 0, -28 +v61=-40, 0, -28 +v62=-40, 0, -8 +v63=-58, 0, -8 + +v64=-83, 0, -19 +v65=-63, 0, -19 +v66=-63, 0, -6 +v67=-83, 0, -6 + +v68=-63, 0, -19 +v69=-52, 0, -19 +v70=-52, 0, -6 +v71=-63, 0, -6 + +v72=-87, 0, -19 +v73=-83, 0, -19 +v74=-83, 0, -6 +v75=-87, 0, -6 + +v76=-87, 0, -6 +v77=-52, 0, -6 +v78=-52, 0, 8.5 +v79=-87, 0, 8.5 + +v80=-82, 0, 8.5 +v81=-58, 0, 8.5 +v82=-58, 0, 14.5 +v83=-82, 0, 14.5 + +v84=-87, 0, 14.5 +v85=-52, 0, 14.5 +v86=-52, 0, 40 +v87=-87, 0, 40 + +v88=31.5, 0, -40 +v89=28.5, 0, -40 +v90=28.5, 0, -19 +v91=31.5, 0, -19 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 +linelist=a_bunker v8 v9 v10 v11 v8 +linelist=a_bunker v12 v13 v14 v15 v12 +linelist=a_hanger v16 v17 v18 v19 v16 +linelist=a_bunker v20 v21 v22 v23 v20 +linelist=a_bunker v24 v25 v26 v27 v24 +linelist=a_hanger v28 v29 v30 v31 v28 +linelist=a_bunker v32 v33 v34 v35 v32 +linelist=a_bunker v36 v37 v38 v39 v36 +linelist=a_bunker v40 v41 v42 v43 v40 +linelist=a_hanger v44 v45 v46 v47 v44 +linelist=a_bunker v48 v49 v50 v51 v48 +linelist=a_bunker v52 v53 v54 v55 v52 +linelist=a_bunker v56 v57 v58 v59 v56 +linelist=a_bunker v60 v61 v62 v63 v60 +linelist=a_hanger v64 v65 v66 v67 v64 +linelist=a_bunker v68 v69 v70 v71 v68 +linelist=a_bunker v72 v73 v74 v75 v72 +linelist=a_bunker v76 v77 v78 v79 v76 +linelist=a_bunker v80 v81 v82 v83 v80 +linelist=a_bunker v84 v85 v86 v87 v84 +linelist=a_bunker v88 v89 v90 v91 v88 \ No newline at end of file diff --git a/CONTENT/BT/GAUGE/BLD20_GA.GIM b/CONTENT/BT/GAUGE/BLD20_GA.GIM new file mode 100644 index 0000000..95cc2c9 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD20_GA.GIM @@ -0,0 +1,33 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-17.0312, 0, -11.9375 +v1=15.9688, 0, -11.9375 +v2=15.9688, 0, 8.0625 +v3=-17.0312, 0, 8.0625 + +v4=-26.0312, 0, -3.9375 +v5=-9.03125, 0, -3.9375 +v6=-9.03125, 0, 14.0625 +v7=-26.0312, 0, 14.0625 + +v8=7.96875, 0, -13.9375 +v9=25.9688, 0, -13.9375 +v10=25.9688, 0, 14.0625 +v11=7.96875, 0, 14.0625 + +v12=-9.03125, 0, -2.9375 +v13=2.96875, 0, -2.9375 +v14=2.96875, 0, 5.0625 +v15=-9.03125, 0, 5.0625 + + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 +linelist=a_bunker v8 v9 v10 v11 v8 +linelist=a_bunker v12 v13 v14 v15 v12 diff --git a/CONTENT/BT/GAUGE/BLD24_GA.GIM b/CONTENT/BT/GAUGE/BLD24_GA.GIM new file mode 100644 index 0000000..af5cf88 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD24_GA.GIM @@ -0,0 +1,20 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-2.24219, 0, -21.3906 +v1=9.25781, 0, -21.3906 +v2=9.25781, 0, 0.109375 +v3=-2.24219, 0, 0.109375 + +v4=-8.74219, 0, 0.109375 +v5=9.25781, 0, 0.109375 +v6=9.25781, 0, 22.1094 +v7=-8.74219, 0, 22.1094 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 \ No newline at end of file diff --git a/CONTENT/BT/GAUGE/BLD26_GA.GIM b/CONTENT/BT/GAUGE/BLD26_GA.GIM new file mode 100644 index 0000000..e85e379 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD26_GA.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-6, 0, -9 +v1=6, 0, -9 +v2=6, 0, 9 +v3=-6, 0, 9 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/BLD27_GA.GIM b/CONTENT/BT/GAUGE/BLD27_GA.GIM new file mode 100644 index 0000000..a3237da --- /dev/null +++ b/CONTENT/BT/GAUGE/BLD27_GA.GIM @@ -0,0 +1,45 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-40, 0, -8 +v1=-40, 0, -28 +v2=-58, 0, -28 +v3=-58, 0, -8 +v4=-52, 0, -19 +v5=-52, 0, -6 +v6=-63, 0, -6 +v7=-63, 0, -19 +v8=-83, 0, -19 +v9=-83, 0, -6 +v10=-87, 0, -6 +v11=-87, 0, -19 +v12=-83, 0, -19 +v13=-83, 0, -6 +v14=-63, 0, -6 +v15=-63, 0, -19 +v16=-87, 0, 8.5 +v17=-87, 0, -6 +v18=-52, 0, -6 +v19=-52, 0, 8.5 +v20=-82, 0, 8.5 +v21=-82, 0, 14.5 +v22=-58, 0, 14.5 +v23=-58, 0, 8.5 +v24=-87, 0, 40 +v25=-87, 0, 14.5 +v26=-52, 0, 14.5 +v27=-52, 0, 40 + +[level0] +linelist=a_bunker v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 +linelist=a_bunker v8 v9 v10 v11 v8 +linelist=a_hanger v12 v13 v14 v15 v12 +linelist=a_bunker v16 v17 v18 v19 v16 +linelist=a_bunker v20 v21 v22 v23 v20 +linelist=a_bunker v24 v25 v26 v27 v24 + diff --git a/CONTENT/BT/GAUGE/BLHHT.PCC b/CONTENT/BT/GAUGE/BLHHT.PCC new file mode 100644 index 0000000000000000000000000000000000000000..99dbe03c93d6f51a881f517a6f69a5869b641de8 GIT binary patch literal 6421 zcmeHLxpEUh5PbwxQ9zXg2Za6v0*4L=2q1IdkbuCS;DCU@fdT?TeFC50FR&!bvR2j! z5@3#i%jPNyQ9w~Z^WKbyU9DEunlq8)*6jAYp6TxC=^oGNlP6ArpJ%AyGQa$+k%m}Z zT`gXmFR#uIi}S;ci{uRXS758(!U~3EtSka2o=fJJKL&jd-0!T-GpS`=J$td6dH<6KZ&!~Qp)5^~}m|%hUqlg`pEF!mxiVNL{?e?McIJ$M2bfZEZjw9TB53m=y&x z#ORKj?2lbc+t>d)@BH1Y*Ty4P9u${~Y*{;=MO8c=kkrnQ|Jq9tGk!gX_q)veLUwbk zQN(-~PGHklR2kkMAkypKLw}?)3#DAw7}K|JJ!qyUq)^8_dfQd3WNZo3MTfsn$IxXf zF$<^tAzTL<<5^0gP2JOIVcL-W&vT%KX`#vA7YTGkE9IB6)28Zd2%Z$K3BQ+OYo$ep zQnE|W0qsvW^4I|>_(pAyHL{oD3Dbbi4=)ovs$;K7YQwndkD!@ek;1q-X}l$c6NmWf zuR~87BOq0;-jPDxiu*Oon*>so^F1k4P$AV{9eI>Ggixz@@poK8c*v(aB!#RHYV|ID-6a>5 z`@j_9GykGvTKL*Tk@^;eWeewqQn&N)NHy){YL({i!v%5v-fjoDM{x0?`Z*z}# z2~2@YSmbRmaODct*AYdSyM)5JEnGVX++12(np-?`{W@-}py;j~4ReMC!+FC6!?NM3 zVa-r56b-iw8!GDP8J-wEeFD$B-2E)DwgI~ZE5Zt}HP}_yGVB8EJZu3rr|V4q%|0^^ J{GtcU><3W~pvwRN literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BLH_GA.GIM b/CONTENT/BT/GAUGE/BLH_GA.GIM new file mode 100644 index 0000000..a692b91 --- /dev/null +++ b/CONTENT/BT/GAUGE/BLH_GA.GIM @@ -0,0 +1,21 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=1000 + +[vertices] +v0=2.5, 0, -0.6 +v1=0, 0, -3 +v2=-2.5, 0, -0.6 +v3=-2.5, 0, 0.7 +v4=2.5, 0, 0.7 +v5=-0.2, 0, -1.5 +v6=-1.5, 0, -1.5 +v7=-1.5, 0, 0.9 +v8=-0.2, 0, 0.9 + +[level0] +linelist=a_mech v0 v1 v2 v3 v4 v0 +linelist=a_mech v5 v6 v7 v8 v5 + diff --git a/CONTENT/BT/GAUGE/BNK_GA.GIM b/CONTENT/BT/GAUGE/BNK_GA.GIM new file mode 100644 index 0000000..750f0d4 --- /dev/null +++ b/CONTENT/BT/GAUGE/BNK_GA.GIM @@ -0,0 +1,24 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=3000 +level1=10000 + +[vertices] +v0=-1.7, 0, 3 +v1=1.7, 0, 3 +v2=2, 0, 3.7 +v3=-2, 0, 3.7 +v4=3.7, 0, -3.7 +v5=3.7, 0, 3.7 +v6=-3.7, 0, 3.7 +v7=-3.7, 0, -3.7 + +[level0] +linelist=a_bay v0 v1 v2 v3 v0 +linelist=a_bunker v4 v5 v6 v7 v4 + +[level1] +linelist=a_bunker v4 v5 v6 v7 v4 + diff --git a/CONTENT/BT/GAUGE/BTEBUS.PCC b/CONTENT/BT/GAUGE/BTEBUS.PCC new file mode 100644 index 0000000000000000000000000000000000000000..47e2a1944111896302b1f4766c1371bbd8db0def GIT binary patch literal 2028 zcmeH{KW-C26vn?nLPCHs`<8I_qTP z*iM9^5Sd7b#uNwy8oqC42Sc==Bz0DPp4oZ7o%iPbnVZ+m4e9JA&gYbHwzItK zTF)!U@;&g{XMIjZ(lR~;*^Er#6JgCM-xriF)^c6;?K#-MDR!rn|L;4ZzTmzZRYQ5} z^I1P)9&>Vvqs9i6_rL3mkQ0 zZZ{w}|Dxe8UA4O(Wzxyn_|5Xv?*Lv&r7N=l=SsuEYp zB<*_M_F3c;>a>sa3S&h+^kgix(7KUV+3I+*uQaJ4Lz}BPE2ePebxK>GX>a`1p#EMN zezu@6U^8AIrN0<{G7+E6G26ZN7szd1QWv}1_`ycJ*|P00+i;14d+_2O@VeLQ-Fb9t ea}!%n@g{=j8DDW@-kleGX!q)O6@g1ez`0+j6oL!@ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTECMODE.PCC b/CONTENT/BT/GAUGE/BTECMODE.PCC new file mode 100644 index 0000000000000000000000000000000000000000..1b8508684b9e80909d694805e5c013fdf843cf28 GIT binary patch literal 1630 zcmeHGJ8r^25M5hFB2lEciL{B7Vk@*I2t{&}C@7UHL`h3JN|(@u(pMlipve(zzz}d! zM`^f24zPJ+du{WP5>YdFmVM8&^LZG6QffRN`@TOKjRu1O zn@l{<>-YOTSU0gwhZ#+M;;8>Qi>xIJt#=k!AFMrPD=T7CPzemNo#XAipaMWTFhc~M zMH&cV1)pw{ffa)wGJr>Ll)xGzG)!1Zov?xRi4BqDdnDzcia1|H9waG>UTj6qvVvPA z6`^7v!@N;yl9~mHRkvSei%DtrG_)+rg3XeYC>g=2$`bM+VJdC_twVyT^gA#{OR<%O zW}vtQ>MMZK?Q+44LQ;JNnkfb-GpY7EQLg)6#2T`$twR4@T=ce^vQW3&hQ6j`p8e(z zOc)|cOPXcUl4ej#n!$_wllbS?)PcFKX}r3w>o}p?B6A;_HNe)R<2ZH4xxMr1j+6vo zv`BjJlQ)fql#)F$DLEHCF1k{PD~UyLA;8)~TwdRE&KaQKHs@9BIk#J5QfJ{NC=Q9DY*b0We&grI1B|15(o-PZsdKDWH;d<5Tc^t4s^>u_U zyCjf;0^!8*+Mdt9J@!t#x$ZUy>74fIbnVsQu|~r0_rByV7+*Qn5V}Dg{(U1SKT}yD zx42qT`4jWSgK_V23o+TH#-1j6dNn=ChB&}jHjx{$@$jDzW~1lNhISssXA?gS*?7vW z(M#LV4&x|mn_^i}=}Pi0L0M4la;os$%%`I~rEOa*X9CM;;!%(ehkW%Q>x9Fa=k72pjVcNl{QpHQ&&MFL76mq_nH!W*-bwk!0t4bbz&Vgw76SM zb!W1JtUseq<{B#+F+o`|_DO*}(`5fJML{;_K(l+> zBVb}whzSag;*8|Tyr=T)8q+DnO%sbVk%p|_8xw&r7X#;bO;ftT3QFWjn6(K>Oc<&N z)*K6BOo*OSF$%;V34mtpt5tjPakXLMNtCP!pt7qM^z7z;ZQP5lHNAiNAHI#d!OyM~ w01oYi;;>F|N!UByCAu1oMmq;vCnt1yMAz1EQT+@9<6iTh{yp$p9>B@}08F@TUjP6A literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTEFIRE.PCC b/CONTENT/BT/GAUGE/BTEFIRE.PCC new file mode 100644 index 0000000000000000000000000000000000000000..fcafe89d498df170a68ab8db11f0aa15759a7bd9 GIT binary patch literal 1773 zcmeH{y>1&Z5QJv~7zi8#E>q?qQmT&;w|*EGZUUr8;nHtJo^*HA$x@J?Dn;tJlLNQs zZ}(2Npdzq?Ae9JmIXgStrO2ZW5A3CA@AXa}Ui>s*Ps2W~%T9gyU$?cAeb+7an|>=y zvadk5pJnuwvVGACX5~(Wv&4x=WkuG6?}DYK){1`38Xui3!6AZPKrB!#oSbcuT_}@5 z&WSgS4dpWlx}d=xpU2!rzFLVLwJ;?{v8k*E)~c}0L$KIP^vVa8@E9!MF)$-}O*J2l zA~0o7j0n^q56+P%XCspF8msVT>MWy3_`W7%OL&zQM3y64p^LykX7R(>PIj7pZ75Tm z5y@CdPx@ih*!EtNy;U?}Qmy^H*22F}s2NxzRrRBTp SNMinB_HBOx|LX+!^6vqZHgm}U literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTEHFAIL.PCC b/CONTENT/BT/GAUGE/BTEHFAIL.PCC new file mode 100644 index 0000000000000000000000000000000000000000..de0ad97d4f18a9d538af6ffb7407361de17bfc30 GIT binary patch literal 1952 zcmeHHK~BRk5ZpyVLQsh#M~*yzV;;~4@R%NYLE^xHBR{eeg457~_y8w_#2diOI5Me{ zG)+szsa7|(>+xhVyY}&+9tqmJT*&pon_}qE@ErCN{owYko5zd1e1_*P`fsu75EfC0 zL0{-A;t}Kczn4_nxKdvR;jHH1en!kC1#k7PZcZE47Xz`>H%B~4wwAZX8pRe$;wP_? zQ3P76C2TN%#xIuarOlM=Gy`{v@dKjPvI(}Cy2xFnGHY@7;b+jZtYbCSNjU&(LTVho zkzTLkj_HYIM_+1B+FHoVGU>yUgX>jq13t%`{&(@GC{N~sYq4aBpJ7fdO+A^=Gadux z(4bZ#&gs|hfypHY8xK_%YS+hkgo|af`v@Dx&D&_~Ergv<&P48#Bssl2nNH>QO75G$ TzWEJ^aVhTG-huye0G0m(@GIkF literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTEJAM.PCC b/CONTENT/BT/GAUGE/BTEJAM.PCC new file mode 100644 index 0000000000000000000000000000000000000000..470d9f65631da0174d163793be7dfe612528426e GIT binary patch literal 1820 zcmeH{zityj5XQejLPCHu3xolqCL<(J-$*Iu%^-f-Y0wL?tk6(lvu64 z_LMUA7&mqjv`V=hMO0W7QE6`?8rmYFk-ds&Z1bO>31{TUm@_JktPgI3bEFL}!u*i= z)Ka9Q2)bdRv{G$Lz+HKtpmoAZVMApGWCwb%Z|Q;iQK&t&8-t9rrp&o-Us>GGgZP5D zb1C%qlG?Zd-aaGSuxdr(JXP^KB1ro=Ed&COL$ zbN~TK)cwSXhCx3BPv!J3KnDT61T9q9QWFs0p}MgWE0SCXuGb{f)M+g{=GcD7Vu^V| z*87aFkyAOEBOkCCu$I~jB-d$R#xKApIY%SpD>h{)k{6}WmiQapYf}E8XTf7@Ge*9e z63vLH_WXmM>j2Vb$eFgxIKA(2)D%_n654Wwv_4g15=ZX^(X8$EP ze{{_gY@Xyz9`&F73vk%E_$Sz@(^~bNN4KSCtyb&S-5a~RdU{{aFB<+zf5OK6kS^OL K1OJNwZvJ<;a-E|9 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTELOOP.PCC b/CONTENT/BT/GAUGE/BTELOOP.PCC new file mode 100644 index 0000000000000000000000000000000000000000..2902f51984fc62cfe17a03a75121100d8ab1c651 GIT binary patch literal 2210 zcmeH{JB|}U5QeLfkPsjd5RgH@5eNu;fDH&a0EZwT*aV4S142R$!5!9~mpz`bJ>$oM z7n2hbqvrd2X7FfX<=u^U%QhQ+t2shhypa_USO-X44s9`S*PG~_6zn?bVks^#^Da~ zJ;G*cBNsu5od!y6icX_DMIJ*PX2ZGmi49xoW2Bq#4#{KgJ_&v{?Oyh?)`!;eGe?#} z9Y(QXD<)Wt+7MU6z+<@755OX#^Dj)%>%1xYB`!`m(|Oo7*7F0c{!}{K zfKeV*N_$^@%!YV1dQm8)b8uNpmtofUQLHmt;_tBj5+5pv#_rWHH9o2yMrA9!-X^ZQ zHF@2?U%9L=VD$DeXDWT=M(xype}#O7Ol>sgJrnj?cWsiiE!)SaWmVY9rLbkY*7#A| zC+!HCQyZ$MMn_|z852!|)M0F_!Ou7^7%3VdlFhh>#*O-N4xjbLl4J#ad4_Dk_^P0B z52w+$MYe?Njv9mBy#2O^jMnQ-WB^CqJWk4Hb>xSbd-m>$*~h_P@aV;Z<6}E{ZJ#>D XtMCsPX5wG-!|(0yHUc+{fcJj@DF($5 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTEMODE.PCC b/CONTENT/BT/GAUGE/BTEMODE.PCC new file mode 100644 index 0000000000000000000000000000000000000000..02e53b4c9dab19def3bff400583652be070fc610 GIT binary patch literal 2989 zcmeHJy>1gh5FT3_DG(&CK{}8qu0mHPLP*zuh^Ve~huhG(bm??NRDOl<25ESNyYufk zHWGmVk$4Fn;P}3sJzruc#&(_c?d{IbH#;-Cv*(99wOv7bFP~(uwpZiaw&UaDq9{&J zPrKdj$;nBl(~+~YcDvnbwT{r5wlx}3YnF(u#zL-SlRlHwj3qHSdLm!VKn7+ei`<^% z=KKbCWHFiP13!@|C_Kv4aSXu-J-q$HI3iH_WP#rd61jA(ZGnC7jRf ze6@4}ou1qQRbhfu+-7*SG?(!mxEv|$->{gvDCs=cx-PA9z|CP;)F791l|H2uTS}|U zm(l_Dp=bAk5v8!jO)K?>G6I#LbCb!XM?)M0CUI&H#3n~-TV3m5YEKkT)mSp?2p!kd zfH6X+uy@WFo<;L2W>`dvnKqZTGkZZm#9JUmWmAp!fJ_Vzbzf}l zTqCa}L?uueL(o00ii<)O!QJSri z(oB}rHv92t{tsi#KPL^eIIh<|$8j7*X?(~Qzj^rr{N=DzQFUh$y5;{{*p ZMe*yZ`>`ng){77Ix&QZ*`wVQ6fq(X8bbkN< literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTEPFAIL.PCC b/CONTENT/BT/GAUGE/BTEPFAIL.PCC new file mode 100644 index 0000000000000000000000000000000000000000..96003f6076e8d7ae84c285bd7b6b62fd36e2d895 GIT binary patch literal 2192 zcmeHIJ5B>J5S>9nLV!d`Nyz~ybATLx!%(C_qM)GUM)rQ<%|CDe3WN}(;0DWk_FAhA zn65b|g#6hGpCiNpH50cQoL1Xp&uzwyFz8{W zYckM^65Y2k#DujmI3G08Jfx)I-(k)}qD_d0HZl6#?{C@yLj%Q4Ho% v1)#h9`gThTx{I50k%vyFb9Qyo>&gAKJT4oqo8N&Le**iq&%l3W0G0m@WOh2T literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTESFAIL.PCC b/CONTENT/BT/GAUGE/BTESFAIL.PCC new file mode 100644 index 0000000000000000000000000000000000000000..60e41fdac7629cd4207863fcf29b7baf313fe1cc GIT binary patch literal 2185 zcmeH{Jx;?w5QS%vkPskIQc`jN${ZjE;4l@wxh6)K$peQ6D-~i^m z87~fz6Y(c1tZZg&&o?vscD$SGZbNY0%f1}1-8xK5T=@UoPu!UJx33b3N_o)#pV&u< z-3!8=G!tE@5(w`Ave;S# zLKK2eFRHgW?lDcx&|`q9uigeW*5w*&2^fPcJ-JwzW_XI)sh5XSiaB*lBvm~vjRh&H zXH>0+VX0@*!4D}}Q)Ui+ z#Hnt625VcHsif>ZlBC!SY&D}&cPBI5eD<_8VS!g&H|C literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTESLEV.PCC b/CONTENT/BT/GAUGE/BTESLEV.PCC new file mode 100644 index 0000000000000000000000000000000000000000..817e0a93cd30e0df4c644c903c8e0687b992278b GIT binary patch literal 1312 zcmeHFIS#@=478DuxFkwS9zmH0@Bn^*_ya{6Bnk>jezdtZfr2JIKMCVKq9j5HD5zq^ zt2iFdjvY^iJR;bZ#&j4w7_Su!=VuS`PRf5aMKMRDnF@|cab_H$GNB|CmxMz(7eoq= z;2Lf#9NdN_J`0)43RP?&O2MKyr3|fT!xl>`8Q*D!AN$=tpkUqI ohIJKHR4w-lqH_=g^VKvA>9nCs7x*qdf*4ELTR(w+O#qw!1lhIAVgLXD literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTESRNGE.PCC b/CONTENT/BT/GAUGE/BTESRNGE.PCC new file mode 100644 index 0000000000000000000000000000000000000000..649d9c29e4fbc3cf1efaf2904c322416bae0cb5a GIT binary patch literal 1711 zcmeHHJ5B^K40Vu@5FkNE$ss7`0DAxqL$M7K1qCISKpZ2P?9A>d5H%7)h+j3lXFFtA ziEpvhj-1#|?B`FC+1?CWg6~T9<#gjFKpgO4{vAoUru)CY0fFu?ewuG3hE_t7C@tnb zK+hNnYL*N>3k!_S*KIGurw{iMB8k?RC~$O=uw8Xv!@zX%x$86VJhClzPY$af1Oj!M zor=D~L_pMf=Pisl2n3=9^D#UKEwg0Q4uzF$EsHO(%nTmP`56QC0#;*at8~e_#i*Xt zxXRKAPl{ndbF}YK9ZHsLux~OYii&3KFIGfxD@Z&fYHxN5QRoRWtgIZWXGO~e204$9 zJfag|1^yMXc3(|Cuo$PVINZ2M%C%56u8;^q`g}!bpF9P-9;LMLi2~M3D%Q!pUa;l3 zqvK%EdULHVySZ%vGLsI@eRvShdKd5PZ_g7BljX-b84@1c;mLu>Mbk8UM?2H0oFB{O Vvf+378G!MRSbysdtf~XJ`R@%YTA}~| literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTEUNJM.PCC b/CONTENT/BT/GAUGE/BTEUNJM.PCC new file mode 100644 index 0000000000000000000000000000000000000000..444551b4b39657dc2429ababcbdb65c871e8c0c8 GIT binary patch literal 1485 zcmeH`O-=(b425l^N`+Qp*(HZyIS1$gxB=o0EV@Br!Ga|>iZjEg;tUX$QpL zf>onroY?*x$H`pGd~RsBc5V-6?~dt!hVRe1`5o~;x8$uQN2hqj$os){Yo4t44pYjo zR#Fx~A?FbactnAczX?j-Lk7lST+33C49yFfP3lV0%q%LcM43TJw2;{m;1h5QFK#JF z2do@r9Y|Mx*ke2*>>7 p4>8zqb-yxuZkp!uda>Eq(~Z4M9lu&XA~61-Q#)1Qzbb&2zXO(91yKM1 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTJOY.PCC b/CONTENT/BT/GAUGE/BTJOY.PCC new file mode 100644 index 0000000000000000000000000000000000000000..5a83f51bc9f15c9152e769ca7aade00e591402ce GIT binary patch literal 2740 zcmeH|>uwV<5QWD`NC@##<$ZVuo^3;#w%JQUp+LD6D2e)qH-PY+8QZ(z(uki(t48trv^OzIU(mLQ% z{|_c{Qfn>P(wfv{8nJ1xC3pvZoXG~>+nFd0dVs_TQ)gn^U~9lVL4UYgZzrZB)~0~I z*YVEC9XIe%A1uA$Mi$`g>fC2A41B=Y0cL4s_}~e|WI{<4aav?PSzul(BOXM_;9UD! zJd|c{=|ZM6=8}W8A7!j0TtS`-fK%ukUgzc^=TzmDB|M1##-FlqC<``Wh&j~P7>JJn zBF+i6H^O<#+Y1cCRhCj|#+h8DA$BY2#*50az1U~xCMSVwhik@#D%FeXoZX>7fZ{1I zstAZYvAw~mK0$iK4t$lDMSl#kP`cVKRp4*NDXs)g1-zDM?lcxl~XI53nEK3Ed*l18qI*qKo|8gzJIu!r4NK-=;m2_xq$`NNmo{y?i zzC)-hK9se{?cbGA=%O+iPLq`iMEJ`Hk!eE>Xd2V^n!^M2ku=m62?jZnU8B3ro7LR1 xWxEHL;sl%{|6I?fsAAS ad4ML7OGvN_HCVzy1O(R4)RKx7t8Royk)d)A?!h_u(8Iv%8?Egm!iBV>`R2{e zym|WGH;;Mu!pJ+|b`KvQ`_}%5nG>+eebo$XVrCjMjrbQMGQ+^|6eHi6BmcW?p=(u! zumwD~wuS(*$m&>sS!F!4w$ZU__>FDjWTlQhtBzk8b?eZo@?IGgj@)L1HvHZ`+pV%k zn^8Nl=6l12RAgm;<7KWG>w<6^j%EGVkMMomzK!%eX0Jm^v~;4PWnMe? zHCFn_Ht|IsNgo~Ed7>Zt+Ry5Rq)tdJ9qm95#5qmCZon?V-hllOb`JIuY!7w@b_(_! z>?q!r=n}ocMoX<7t(hhIeKecM=T8ZxF+0nI5>K>T*UlpiU*m2c3r)=Dk?@TSrGX4t za+3oYE)g!U65LM-y@8@Hx^z&aZa^)M>MoTe6&zXx{eXikc5b4OL@E} zfg({r*Ct(uOeKVh3Uy1UKqw^wC2lDZHLD*BV!Z literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTPLOOP.PCC b/CONTENT/BT/GAUGE/BTPLOOP.PCC new file mode 100644 index 0000000000000000000000000000000000000000..631b02644282997c2273d7d14a77ae0ee313091a GIT binary patch literal 1579 zcmbVMO=ufO6#m?8*is6;w3l4EU~=&s6bQN4hs-4xyC6d%Y-E9SDS}{#Kn*Fyu!6?4 z#0C3O2-U*o5)$k}4VG{a0fBxzsik7MitVkEREEljhJbVMp@)IjH)|WYC2o`M&NuUR z=9@R)dow%lpBZ=${A}VQLL1os(>I}~`teatQtNAMc%(=cuIa1A5VsHkw?6ArA|pRmTAYi6}D$IqG2X4}O1 zoblwyZuBSgl^Z2pCbX?}-h=-j2ceup&t`&&(X7&6;dRLgm~ohA6Zpv>YJbapUsPcI z#J*LSQnSOxZiahrM$FzBe?hq8X7B%bN=`XV=9J;z&*BH>jK9sVvA@6H?RMMkcC}hv zU0q#TTFU41^Yinr>t?grbUHmTF)=naHZn32i9`km2if;N@H?;rG=MU&0^A4kz#QNL zSs)Ee0Z~A*mQIICCGvf8T}mcNN^%@_q8}vm9jU)@^cUz&qnSeCD!fmjb)fY_tv#)0 z^q&cRAoYQx56}zHtfBA&JP)^SAv2B1tB?{cov3M9(9T_rg&uNEd|p7xL!g64`k|-2 zoSsSPgw)c}4s@8D;{fai>@w^X*!N-QVb8&KVP|2dVNb!1;$4Xj(FrwLYVByvD$(nq z*+ijmEGUD?NfwlNq~)@99%y(P-}W%m#B>1(&!nLorXfekRG5ZygfpB8F2{o2AfvB3 zv{#~zPc4_$lT?;ebZ8OuJ@#_gxPf8{{y1hYBXbe)AxPo?N<==9OOzy%L=Inww2QrU zY!p%S;m>0BIx=y@CG%f&X}3k4I&GC{W0~srsO(c|ftGW0FGGIn)pyAk^YQNOSSvTa z?ncXBjutbQ7q7{?pI!1(!wboax8vt?*L;VN-OMTD9X>T97^4EIMRzEWa>xqQ|C E1yQSwb^rhX literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTSPAL.PCC b/CONTENT/BT/GAUGE/BTSPAL.PCC new file mode 100644 index 0000000000000000000000000000000000000000..ba2bc01c7fbb95ea33405774a9215e3c00b90718 GIT binary patch literal 916 zcmd;LW#nK00#+bwV0yp^WPS$YvAQ2E+%)ro$gg~~9g3%D5atQqY G{~rK3x>W=K literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/BTWARN.PCC b/CONTENT/BT/GAUGE/BTWARN.PCC new file mode 100644 index 0000000000000000000000000000000000000000..1e71f8f2146dad73109edbd9a8d657e8a3d5447e GIT binary patch literal 1441 zcmeHHJxE(o6#h~wuarWkE-pS07w-_Exaigz_y5 zu3zx=8xblf2THdrr9kbczLH~@82maUklMi`zcGhe*kB*MY<#Ils z-`w2HWHRY=+P3XfDwRkiB9X}G=;+|!U@#c$?(WvH&wy{hSKt6B0^7hEkO7te8%O~O zU=j!cQe$Z}xKLovW7}rSVky})br4#Q(FaLyO?rve6smD#$KgH!QJrXq$R(Pi?=iZN zbYap3T6I(_$bN$BVtyXUDNKw*O4KM;A(F;II{M)6m1{&`jul3FtQ%J#X+yfg2vzY~HuH zC^={H2KXaR930Ld7l${7g<&N75$%O!oj`%vW44(sX31>oGQ`I?*~eiHIS<|f7N(Jm zA}Y22X_Jp@+}PtUMLyi(y;UxHTv+BUhgXyA#n0bcr|D>OF4$X@-ZoMg}@%U*|yZQLp*%SEWx0p+Z8<3groHbKlmxApsGy8UTcJ|GKx!v7$ z3wqqsGk)Ww%fo0P1*B4*(@VgE0dKIL0cOv&7Y)&Mzy0KYT^S`Vqrm(4s;$699BM1@ z7ktxJU{u-jWwr}!mpyz5^-giAeX3#m?m8D&6J4h6eAM~4L!?9OPP?*yP^8srH5!eh zqoZQ6n9XLlwziVVWFnEUZ95i=MIw=@sj2bt@!{cNpU>CZ+smHb_zC;~4uL$d18e|E zUVLNpDShf#xhKVWcPFJOrrpa6*tTqv^;CUKh2gh{0N4pL= zaas&hNRl+k1ZhHl3NQ{~!+}5rYwdF$2Son-X>AD{M#-nM9f;noU$H zNT)l5qL`l6ghG2Hx5?ZjID~giELJd^M#%AG$hT#PvlVX3(8uW3Y_1TxhN9D+o@n;P_sd2r;-}7AE=F&RnUCyoYcAVFv?1swWZPaN3({L8US zbTsu$u00)b!$Ygq;Bs&vKH;19_s@;>S<(!QJRBS9kpn$Lz6bs0-M@975<>ZfS`f+= uN(onq1tt96=_8>mp;m;-iY+B;NCWeL10;bsFa`tx32?Q_ z`8<0bI}Y16OUag{i_mJ6-b#99(KFP?QH~)y0{0<^PKdUMT%u|E9;Hi3mlj>3eu8od z+4pc=%*-G$j?ocFi3&waB(r2K5fWPvoHUk#Xt zFbgm@V6MPS!<>idz)Zr7!yJPd#C3@(^A$EEi7X<`67@RDWn{B0LJ5qHYC_R%lIvux z5?sRTI;P7Q&m!vjG8CFJq}Yx%W$0wIX*O2~{e_|zRX)pe)#Hl82R0WZ=Pb^E-{CBU zqeU68CB$TNG)4ztZHnJxXK`4nddILaaC!JEbG1QHQMq|QID@o9yt zd;F!qN9(+|%mt70i@cuV#Kk*AC@wm97Z)u=s38&qFG~p&!9XgOBD_GA7A@#f zD9wZCB1%%IU_vAaA&q*erX*BKLzW1Qi%T3FIvhB?FOb%y(DokA4~KIO-}$)bW_Q;O z=yyj;;@WAK7o&v~kV<(*yMPx4yvJGs%${jG9ir=QyXAk)ArANuMc&6Jtwk>3SZk3# z;4?&{mkogBsQLXxAYpK?@NIOOhs;APwmE0>&|n0*oCP zn=q0vR$$mL;xM8xreXMTU82r>1r13elSrdPvx#yUnM?;z3{z7YP z=7S9`xSU_(?F4Vc*o|DgvCdaRjpaZ!F>z%33(v>0vC-5Mx&C;>jSQ_>gUg|T#Ds6o z-#OS0E5*X=!2q z6XF~271#yxz$&l^q<|T~0TMtA7zToX1h`V+T#h}D9fxh3rDV&}i_lVp-b;F8(F@c@ zP>v!q0QWJ74vE%@T%rm39-(td=N6r#c8GEjnU8Q?Oim&`f}sIOiG7L`NoL5JC(PB5 zEaQ0wQ5T1FxIybKxk;LcQbdxp$O36XzXh1PF!L~1VJ^Zi2$9;*}DE Jx>x@+egGU%2FCyZ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/COMTRUCK.GIM b/CONTENT/BT/GAUGE/COMTRUCK.GIM new file mode 100644 index 0000000..4f7c011 --- /dev/null +++ b/CONTENT/BT/GAUGE/COMTRUCK.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-2, 0, -4.5 +v1=2, 0, -4.5 +v2=2, 0, 4 +v3=-2, 0, 4 + +[level0] +linelist=a_vehicle v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/COOLANT.GIM b/CONTENT/BT/GAUGE/COOLANT.GIM new file mode 100644 index 0000000..662d42d --- /dev/null +++ b/CONTENT/BT/GAUGE/COOLANT.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-2.5, 0, -7 +v1=2.5, 0, -7 +v2=2.5, 0, 8 +v3=-2.5, 0, 8 + +[level0] +linelist=a_vehicle v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/DISH_GA.GIM b/CONTENT/BT/GAUGE/DISH_GA.GIM new file mode 100644 index 0000000..6f9b929 --- /dev/null +++ b/CONTENT/BT/GAUGE/DISH_GA.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-3.5, 0, -2 +v1=3.5, 0, -2 +v2=3.5, 0, 3.25 +v3=-3.5, 0, 3.25 + +[level0] +linelist=a_dish v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/DOZER.GIM b/CONTENT/BT/GAUGE/DOZER.GIM new file mode 100644 index 0000000..f5b3e11 --- /dev/null +++ b/CONTENT/BT/GAUGE/DOZER.GIM @@ -0,0 +1,15 @@ +[object] +gatfile=gauge.gat + +[lods] +level0=10000 + +[vertices] +v0=-2, 0, -3.5 +v1=2, 0, -3.5 +v2=2, 0, 4.5 +v3=-2, 0, 4.5 + +[level0] +linelist=a_vehicle v0 v1 v2 v3 v0 + diff --git a/CONTENT/BT/GAUGE/EAFC10.PCC b/CONTENT/BT/GAUGE/EAFC10.PCC new file mode 100644 index 0000000000000000000000000000000000000000..465b8b183975ce64e6252e64d85018fe8963e443 GIT binary patch literal 2193 zcmeH{J8s)R5Qb+B7%&W9z;%iMv4LDMoeq!#q{vOUE0Pi=TTKche#C`)9l#0wfBT?m znGOO~DNJ!Rqn(+5p4#I>cVv1#xl{Xc@XI0h)=xbjzkZNzHk*C^cGk=0y9~|TdGx_= zpGP?Hv$fWOYi;FfYg{??!)dV2t!*ytGHY+GvD!7}-Ad8PQt=2`S0QtJMVr>*nk~G@TKThR1H<%+phjbdav42 z&UYhyCqM75V@*MF7+W^diY#adxRctIl0F}0)o7L1I(GkOIV{5MwCLo03tSh!>%{LLZmSmIVpbSE@UW1mV_ZwK#f>59S#^7 zF2pzDyPy$>$?9E*)=AX&Gi(a}0=Db`uw}jpnoP(UOyn$z0lz9g>%m|y2s*WcpLUUL zXV<8WnbfiNf}QggCVQO+Mo@B(r$es>QvuNrW>WqT1fWkWJwa09<3a}Sg4|`Je+#tM zb}h9oRou=$@=YCTa}$O!O4Dh_@_fkvk%dhejFP`pxvRK>b0w`SrhqcKC=Z6xZ= zLwNYl%DqTlq&qnUOZS#HimUO};s#sIc T^aZ@nt^4lt-huzI1KRp0jv6(i literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EAFC100.PCC b/CONTENT/BT/GAUGE/EAFC100.PCC new file mode 100644 index 0000000000000000000000000000000000000000..c5ae0af31b06cd45db2c085bcaa33f9f97be7a20 GIT binary patch literal 2372 zcmeHI%Wd006dWD`1VIja&CTZ^2bSPcT#8F@2`RxP*jkdJD9WOo+?)jNz}tZ`^LE!{ z2uXo`@W~P%_VeD(yw83oy4c8|lo2Hv&UxCV{;iG^FSZ7Ff}J+i(+=XPe>(zZ?d9ct8W z$@Lz++oEE>bFz)=hotwer(I3`8cW)E+Ke*VE*xEux;LoGbtlXP!A~CclojPJjWxGO z{XHJAB4`AbMn2c{vFDt|*`JnuOidN9;Hw#EM9s(XS{Sqf=B%_Ls(Qh~5lD z)!XDTNG+{Q8agOH794wuLfM(lA{JoMHk?HyP+b2bkgp;c3A8HainSt{Vi`$f`C{M`k1Jk41eY8%CoSt=f&>Lg2R3}Tv6c()-9XQo+7=yt;5KG&YwQu3~qvywf2 zSx?&~5-3@m%8nmErvqjJnh8(L`J^7_P`UVtR0~wbTt&6_X?_|;Cc1sn6%p5MxLpVK z$16ht90VVafxxXi&uJ2+4vN~_r+5#jf5&A0dt?3PtTtv&i0&huT2*&`at|R6T>FC< z;~n{DhA8Bk+0Td?=Q?@b7nYKE-5tA-N9|``{x5nn&h)(SEA4r?Lb%b}auaZ6uSzN1 R^!Mt=<$d9M2Hqe8e*p-&lUV=& literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EAFC25.PCC b/CONTENT/BT/GAUGE/EAFC25.PCC new file mode 100644 index 0000000000000000000000000000000000000000..7c018d31e1597f65c06a1a0dc765830f7dca1eef GIT binary patch literal 2243 zcmeH{L2lGQ5JkTiND*SuTXtC^7Cu6blB47ZIRZz>5fZ!Yu|1y2AhALrWWxf2l;#BH z|0+A_V3TCt=zrRun=_`VM(y2C3BtTKLl#YOg6-rY6={zZ8-Rgxh@&s4_Yg(U9jsE!pi36 zP-E}mUNJO@JLqoZ~y>(5kbhmI87krtMW%}$BdMji!w zPhHxqh#f_BbjeZF&Vm!l{FO321y4u^pn6g=IgFdIp{BA{xDzZ4FE9Y}7mfDh{V*dm8?XQKeg;b jb$33wb@x-GbG7#Kgi~wkx#s4-XZQ9O$CnKJhYb7%vn^jF literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EAFC5.PCC b/CONTENT/BT/GAUGE/EAFC5.PCC new file mode 100644 index 0000000000000000000000000000000000000000..febf3c68910db23fad9b3134ce7ffff2aecf137c GIT binary patch literal 2212 zcmeH{O>WyT6oelO1PF>=AnPs)GzD_S?tFk8Ad8+vqAbgnTYKeQif)sj2yy~;KK|IU zBO6FoU0C)5De}FU;gI6T3wLRHzPc;>{^5_KA1sVLUv58ZZZetN++7Fd{7|Bq`xa}c zd(R`B_0ftt;Wzn#Y^YJ!q^`RH2c_RHNy4uEGhgej^UT>m5|a)LkotTW6o) zCHAp!ajifFcukBU9;yUXyOq+^pcAItAUVN8+bL+V9;xHdu^2Y}=Zas-R`Uuu$*95* zxokU3@D|}nLVPmikRf`}4kyWYj>Ts6S$1G%?B`Vpu9ID zO6x!l5ErSe<$&CoH;=;^a^Afu-h$tU;t2aI50~$18MZX%G zu%S&Dw|yIJHT4aBVpwwzNux^R(9SO|onKthv^6>EnXASsR0JDW%|%UY%kxWlPn`I3RN6M0 zwA@3MivMeh&|fJW&SaLB7C5O6kxAEdIVAP-L~fHwg%OdFZ-xJcU>ad=Afkv_-T&qlm_(%y|0R*EUUld zN4CVaV}@=i9c93;KiHI9F=RHqVx3V*(@V7idi!~<8P3-CY`p)}uaDK*IZA8o=SY|8 Z>z4`V*3nDZ4!;*S_E*Q(4E%=-{02eAVLbo< literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EDESTRYD.PCC b/CONTENT/BT/GAUGE/EDESTRYD.PCC new file mode 100644 index 0000000000000000000000000000000000000000..9176f1d54d1628f9be7e5635bf2fe0d114249ffd GIT binary patch literal 1795 zcmeHHJ5B>J5S>9nLV!d`NlQG0mD z!|rg7;vug(Xb(g=`HUnh0#PG-8Gv-K>9dW9JwRIMD17%@9hua5$QnYtEBZygB zP-cPX6=cdL$Jq2iwwDcdV>+DagG^ed&~FD_pZ(Hbi6%fZMob3(n=+}ZnH_wEjBInI z3X2xW45+PT^_3O1$vL$ZqJgeH*9<3bh}rV8To_G&usY0ZjE)&Hig$>yh-4>Nk(xDD zW0x+_n)w?$@Ll(bw(i$V>-;!jv}utxs3p&wQ;#X+gq5jnwB1(Q(53nX$*JAfJ*n-S z_M%7ZYUUif+PNz&ErB|asy+3e!xY`K(&g*;DzKb`Mk7~h@4I#l4lDuBuV1Qy$x Ao&W#< literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EDMG.PCC b/CONTENT/BT/GAUGE/EDMG.PCC new file mode 100644 index 0000000000000000000000000000000000000000..1ffeb6a6a2d4885c0cf2976185e6de5c8a50e21d GIT binary patch literal 2840 zcmeH}$!^p@5QeLfkPskoL!H_YkxA5W)^_?32O z?x(pUbNlA@%(dng=H}*_Fluvg%*@46nH!J#F90(ua1=;(FI+i-D1-j&ATAGMNXx)2 zt#m)kyQLy+#qWu)t#-$nz1Hu;TnBxrwYQf+;@vlSz-ug$Xjh_I{1?qh^j54F|5}tp zEPIr%!aR_m5WNu1wFcs|W=+_>3EO)2N<3ys+(UeqAVU!TJlfP&xlfS=<(Rk@Fht24d;&`CY*ec4s>}Isu-1MG*g0nkqWJs(zEud zN9oexI-Zwnl^Lou6LI_ETu64$ElkXbTLTY*Wel(e&7VPCSJONAmE1 z0isajMJTQ{*PaFqX+;brNfC~po1zCORTEAa`=SXR>j6l)483;YHN^Xl2E6^x-vM&i xo_+^xcZJ>(_a5Cfd$zT;b?3pYogI7n(4J2X&sskbus%kvo~sO8RtEF|d;)A&21oz^ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EERLLAS.PCC b/CONTENT/BT/GAUGE/EERLLAS.PCC new file mode 100644 index 0000000000000000000000000000000000000000..06253c33fb8a3607625902c72635206a66daf5ad GIT binary patch literal 2558 zcmeH|J5n4m5QcjLSGimclsY4JIoKm`6pq3XID(JB5!iX{i`fTu-~e3QV08ohe`;xl z)%BRM+wp0w2TAj#S#ndYL zxyEggOwhut1XkQ5pkHbOdy`x$Zr!FF!c4qGv{W0IYnz8k!_G_+$CMT3T{5dQH&^;b z%&o>7(b76OjE9x_wHlm1)$~HGml={iJHX&ec&tEb*24Jwoow*tnBB)7v6C@Y>4@D+ z3HDCeBljLdtu(B~h(aHJYur=P>DxIC_33q5X^4;#JJGc{_s`iWZJ1V41HQ@Z_+E>K zIlZ{8cdhhOxRuZhJrlr9((1mH5VmrClL)=&z}$%nb7;V8h`$W5uB#Lb3oz((>UKjB zF@+uOkR}>BaFzn|T~ueSMZ)JugmNMFlw0VN;(1MH+)E^hqQD1CMjc;t(&PE>h=^kZ zS?U~k3O9=>N_+~B)05vzSIOhC&$_n$ n>9#xJV$?fL7vqJ+D{jTBXcy@|oHF zjHM7!6fCkrXy~!J=k@E)^wEdnqu@C$KFO}w71)+#sUmtJdMx)oK~s$8pl zR=HHUP&tQPamF)metPjgO|qA%-CkzBfQb$651M3EU=G|?jbXs@?OEFmp?e!8d_~9BhVwh&4E;5MVUipw6)nx#huaU zn>=cuHpZjEK4Q^=S)j{!R90O;Qc(wQy>2FkZ)`Y~W)k`aN)_fj5@B zG4P$;+n>*YPPZnVrOx1%>870R|HWsJz5Fu#_7FNJ0B?~O?C+cO6fNIP=Jg9A>*eR@?yDyC35Pn~(uVq#=nW_OjmnkH@{+po^X8HM Le(*g5{~-g9N$zs~ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EERSLAS.PCC b/CONTENT/BT/GAUGE/EERSLAS.PCC new file mode 100644 index 0000000000000000000000000000000000000000..390e47eaabaf4ebd4719c2265d8d61de357ff289 GIT binary patch literal 2461 zcmeH|J#rf{427X0Gnq^Zw&`4FQs@XiijU$W_y{?Ik6`V;v|d?BCcTo>vUmgMec)1B z#U9VtMJlgIaR~zN0U)^i@NV|r^n9Luvh8d;)9ZXbk7n`A;tC;fH#!_s)_Wls}`^5E@&B zVbogcy>YD}p!IvyT07pYw7y#%T4C3&wRWvv(kjDRtDRM$P_Naqb~Davt!Evuw+E}G zRtmSqPdJL8){LS`BZjCwZ}?3bYA|)`Q^TDt<#(Z8I&iHxYDEhuvf8?X4>_9TR~3G0 z{QzCLFWH}+Ck$AEE<-7rQnJ=sjr1ujY0F7!6=oSWZc|9!D)i&}PV!2a^hT}{3W+V% zNfrER<#E6RQoY!N!iM#}t%-pEd#$Indzs#c;_(#yHuRK`5DXc>D^js*&Fs5KKL7rz4bP`GD1f$=Q zCI(6@?I0*m5>!qO0lAk;HSpbyW^nz(w{|Riu6)l2=SW<9rH<>lSVxQ_&-64T_i~(YlOD#! z{s_exxD_23WVzIwv%);5kAlrOe8xD8D@+kGfS}bQzs-Z>i1w-nz1Q!=-f-?aHsKIcwAB)wkB0;adj& HLk9i=x)jY( literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ELBX10.PCC b/CONTENT/BT/GAUGE/ELBX10.PCC new file mode 100644 index 0000000000000000000000000000000000000000..465b8b183975ce64e6252e64d85018fe8963e443 GIT binary patch literal 2193 zcmeH{J8s)R5Qb+B7%&W9z;%iMv4LDMoeq!#q{vOUE0Pi=TTKche#C`)9l#0wfBT?m znGOO~DNJ!Rqn(+5p4#I>cVv1#xl{Xc@XI0h)=xbjzkZNzHk*C^cGk=0y9~|TdGx_= zpGP?Hv$fWOYi;FfYg{??!)dV2t!*ytGHY+GvD!7}-Ad8PQt=2`S0QtJMVr>*nk~G@TKThR1H<%+phjbdav42 z&UYhyCqM75V@*MF7+W^diY#adxRctIl0F}0)o7L1I(GkOIV{5MwCLo03tSh!>%{LLZmSmIVpbSE@UW1mV_ZwK#f>59S#^7 zF2pzDyPy$>$?9E*)=AX&Gi(a}0=Db`uw}jpnoP(UOyn$z0lz9g>%m|y2s*WcpLUUL zXV<8WnbfiNf}QggCVQO+Mo@B(r$es>QvuNrW>WqT1fWkWJwa09<3a}Sg4|`Je+#tM zb}h9oRou=$@=YCTa}$O!O4Dh_@_fkvk%dhejFP`pxvRK>b0w`SrhqcKC=Z6xZ= zLwNYl%DqTlq&qnUOZS#HimUO};s#sIc T^aZ@nt^4lt-huzI1KRp0jv6(i literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ELBX100.PCC b/CONTENT/BT/GAUGE/ELBX100.PCC new file mode 100644 index 0000000000000000000000000000000000000000..c5ae0af31b06cd45db2c085bcaa33f9f97be7a20 GIT binary patch literal 2372 zcmeHI%Wd006dWD`1VIja&CTZ^2bSPcT#8F@2`RxP*jkdJD9WOo+?)jNz}tZ`^LE!{ z2uXo`@W~P%_VeD(yw83oy4c8|lo2Hv&UxCV{;iG^FSZ7Ff}J+i(+=XPe>(zZ?d9ct8W z$@Lz++oEE>bFz)=hotwer(I3`8cW)E+Ke*VE*xEux;LoGbtlXP!A~CclojPJjWxGO z{XHJAB4`AbMn2c{vFDt|*`JnuOidN9;Hw#EM9s(XS{Sqf=B%_Ls(Qh~5lD z)!XDTNG+{Q8agOH794wuLfM(lA{JoMHk?HyP+b2bkgp;c3A8HainSt{Vi`$f`C{M`k1Jk41eY8%CoSt=f&>Lg2R3}Tv6c()-9XQo+7=yt;5KG&YwQu3~qvywf2 zSx?&~5-3@m%8nmErvqjJnh8(L`J^7_P`UVtR0~wbTt&6_X?_|;Cc1sn6%p5MxLpVK z$16ht90VVafxxXi&uJ2+4vN~_r+5#jf5&A0dt?3PtTtv&i0&huT2*&`at|R6T>FC< z;~n{DhA8Bk+0Td?=Q?@b7nYKE-5tA-N9|``{x5nn&h)(SEA4r?Lb%b}auaZ6uSzN1 R^!Mt=<$d9M2Hqe8e*p-&lUV=& literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ELBX25.PCC b/CONTENT/BT/GAUGE/ELBX25.PCC new file mode 100644 index 0000000000000000000000000000000000000000..7c018d31e1597f65c06a1a0dc765830f7dca1eef GIT binary patch literal 2243 zcmeH{L2lGQ5JkTiND*SuTXtC^7Cu6blB47ZIRZz>5fZ!Yu|1y2AhALrWWxf2l;#BH z|0+A_V3TCt=zrRun=_`VM(y2C3BtTKLl#YOg6-rY6={zZ8-Rgxh@&s4_Yg(U9jsE!pi36 zP-E}mUNJO@JLqoZ~y>(5kbhmI87krtMW%}$BdMji!w zPhHxqh#f_BbjeZF&Vm!l{FO321y4u^pn6g=IgFdIp{BA{xDzZ4FE9Y}7mfDh{V*dm8?XQKeg;b jb$33wb@x-GbG7#Kgi~wkx#s4-XZQ9O$CnKJhYb7%vn^jF literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ELBX5.PCC b/CONTENT/BT/GAUGE/ELBX5.PCC new file mode 100644 index 0000000000000000000000000000000000000000..febf3c68910db23fad9b3134ce7ffff2aecf137c GIT binary patch literal 2212 zcmeH{O>WyT6oelO1PF>=AnPs)GzD_S?tFk8Ad8+vqAbgnTYKeQif)sj2yy~;KK|IU zBO6FoU0C)5De}FU;gI6T3wLRHzPc;>{^5_KA1sVLUv58ZZZetN++7Fd{7|Bq`xa}c zd(R`B_0ftt;Wzn#Y^YJ!q^`RH2c_RHNy4uEGhgej^UT>m5|a)LkotTW6o) zCHAp!ajifFcukBU9;yUXyOq+^pcAItAUVN8+bL+V9;xHdu^2Y}=Zas-R`Uuu$*95* zxokU3@D|}nLVPmikRf`}4kyW6gRz#2;!!N=iRtzAEfXMEooq~k$@BoL{X$L0WC@^ zv>QRpz_<}56)ZHN5`<9G^fpcU5-G)!O$w%nZt9{77YB}K62)!=-{brN#?h119$+q1$Lc{!2Khl99S7{G4O>=SxGsK8@*y`+ z73*_VYHtZ|iLXjN+`zQZVETWuS-7U7Ub%qk<#xVml1`l9O8%X@rG307u%5e zqj62DeH5$7{Ly$5)+dPWRsI?M*=z5A*p`EXgHETjy}ezjR904278e(Dx!nBxyytnD zOeU2|jgOCyj*bow4@V-Afq?-A4uB89d!P=Kfo0%1kOSrb56A#1U=oM|vg6!tbE(8Z zz@Eph%UZMJND+FGpvRgXICLA`DKwHOT!H^Lh<1ry6Zu5b^ff_;nhqU0M0XdBH56XL z_i^tY(o>kY0q713LwK5_S~FHQLNa)Q~1}h(sm2T{Idf6n+RwV`4%CCEk!;BIgCc zCp_$8x`C+z5`Nf*a<2_pc9Xp}oMW62HAe*fMn}K2dB4Q%fLk7Kx?I*=bT|)wg8eL- zH&IL?7{knEq%R^q2+i^UCFX$HV|JM}vm+lP?_pow_#%n{f*H(QM>>wUmi3=Iyw~D( zm3PYAT;l38E(cs%;H4}-OLLI?^2q%>AMeb@TG_EpFIv7cQcPdYU(-*oUJ8;!3+~0) z`1$Nue{ARuZ(QpGK literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ELLAS.PCC b/CONTENT/BT/GAUGE/ELLAS.PCC new file mode 100644 index 0000000000000000000000000000000000000000..efe0112e57dcd5b5d4ea3ec2aa201d4df313f521 GIT binary patch literal 2420 zcmeH|J#yPH5QSGoW-^%+Y}2{Uq|gz36d%P$@DXwZAHgR0BTA+uCrwJp}4oESXn5($`6ND?s?=9xIy{ zefH?oZ``AIkDu<*YvfKIU#u=#&8^*I=^j6_N2Pg{7?KzL+AS1Ijm^}D@w5Y-O zdzXcknv7FWXlX*Hc03`tGZXG*dTQD6gii65vfzNV;;ofYrxpUnAz&Wb5bZbF4zluK z2{`d125=-3ieQ~=uJ@VR)~(d|A>7)1OU-FTfn4|?0Q8kxqmT%t)O(PD121im?HfFh za~yDDK!k<9!9X!I2P!D`@M#QKYD}nO_{Y$V5<}tvz7;%cg?eudj3h&&wi$2`u~(*K zGlnL=dKdKo%~Awp?i!Nw08Q9Iuzb}6o1TR)$nHp&Q|JpJf|Jywa?)k)10WKl#`q6K zE2G9qe;mdcH2T_j1}uJr!B!FlFILFFgRGfn<{UYC4JVSMzO$d^*l!9{q3%Pu(iU=# zRNqqaCBYjqVR1uAiJu@*w(iCf>IKW{AQfQQ6D&YPI7lZ|Dns&(fb`+^`++0X{y|-|MpYr#t41>qyVkucIrAH{3-x(XRX! Tn(}S@d+}xTI`LJ3|DeEc8j!Xg literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ELRM10.PCC b/CONTENT/BT/GAUGE/ELRM10.PCC new file mode 100644 index 0000000000000000000000000000000000000000..4104f1a9bfe262dc1bda5a386d8da9d08461fb5b GIT binary patch literal 2475 zcmeHIOH$)N43!sCMNzZp?d(`nEPMox!cjN^N0=jUgy6pu!ek3!rno_LgYcfzHjd*| z85Xm`ptQSN(vzO#?(-kXnc%rhe#u+%mf$r_Qx(w*(QDBg(Oc1b(T%9eM&(}Rx5}-` zjmkCjk}KML`PqyAX&m=5^|q6TT^=6gF;r598nTfrv{D7P-p2iPDC7Pg$wMPe+<%Gt zPoaQK33-wNewK0nIquV@2zk_5Ne!JGHu;fWi?tkrFiHsCKBvw2swjKeN(-dS(74Jh zN<`OU^Kin<^a7C^j0WHg~FU5Y>2@wAnVR<9L6|HPBt7@4IP*2YS7oEG7lVN5-i7srB_tj{c{uI=~oYOyeQha;0%;`hN^ z*a)YwK!Is@U(QEjrO`za524sE(IqR-LKDW@Xg=K9tft|3{4lFYD7MP1uZiiq;=}F` zjdW0$oF9gN4Xx@)D`Ck4fsHYBD2zRK2hPy5AH)Afp8XhW%ySEr?g;BhW=Gi2IW1E^Jz&% zVZn;P)QM;O-u!GI9b|`s=PWysWwy-ln&-KS=&9(1=%whD=&k5NRAr%Zt8$}qrE;lq z0lVy+YkvK##r`ynYZ-f6$^FW^2YGOn1UG>!q`)|Jw)#2g=Po4ullT$+qbsF?P30b? z9MOAMW8Np5nM`2g6UQ=fc-LUgL*PPy;B9|P`c;8rEg#YVol$VcN6!NyY7haxIZr7e zHN-M7U{6kXXPEFO0QMaaRfH`8Nt*^T1yqf3(n+xeYk>n~3zjK0IfR+m#E)M?3O2zQh55gh z7icXr)(Q!3hUqyHME^z@76AWm zMWSN{ld>)TZZ3o$t=mn~2Nk-Am=z-QjfM}4oMVWUvDW!6w4QDrSB=rx>D2c07b>>M zUb}~7HN*SWCL4XHurq38%{D4eH)fPc3s}j`&!!kV0Jf3alWmCH0FTEC(RySu1aK0$ z0ZV&YwI>#Lcict$9q=m0xI%t(^PKXM!haqwscX?Y-cWZc*YR%3sT)4OzM}pY{%7D1 GGVlrVQMwWU literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ELRM20.PCC b/CONTENT/BT/GAUGE/ELRM20.PCC new file mode 100644 index 0000000000000000000000000000000000000000..f15cb4c839aab4fcb792e57bbffc149a155fce62 GIT binary patch literal 2487 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ENRK5.PCC b/CONTENT/BT/GAUGE/ENRK5.PCC new file mode 100644 index 0000000000000000000000000000000000000000..6e7b6a588f572e00231658ef29da055e780a6167 GIT binary patch literal 2458 zcmeH|O>WyT5QWDD3KT^b+Gdw^(S?qXqvR+)LXMClCLf?dYB9`ZzkV@ta>GJ(gt|&El!WGmGaI#}=ZQxYAv2x?>ebgTldeZ0bF?N zO-xyZwJY^qBaQ3Q2t9ZdmHM>|q+1znEql=5*vd!&c$^XyEd@c8xq|8c!Ul6i$8|MPmyG$`orsu?DtsRa&4)`IeX%gq4yX=26=2&C<#XW_Q<+4M<<4 z2q@bnwt+<+$_f?EPp4!H>{I5?OJ2((!aD*Hocx}hAW3UhfB{#@ifXDyO*p7(; z5-F(SWHZh@zMYwUoSh`6g6Ar^khkP5!E2hPDx#O7GtnE-ThX~_C#uq^%vJ7HZdGnn zX7Ed{8FTRSDgM!3e#*YLjXZ3cP)ZYODZ>yGp>0DhEiCn@9hHTwN9DsNhNa{o${>qS z;J>3j5EDZM8|^N0^LP9E9(xQc_|o3U3ceXeL?RJfvTNAM;CvBDI(K)T40>U z_dG_NH!GHb{Or4Vrn+<7a(}uUFL{sRo7z2kC%WJzx=^{Z>ocWo`W$?V9s`dZ_=gUB E0fap_a{vGU literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ESCND.PCC b/CONTENT/BT/GAUGE/ESCND.PCC new file mode 100644 index 0000000000000000000000000000000000000000..f5b7a46bc1d4b7fc9081fabfe85b4a549e5a0ab3 GIT binary patch literal 1102 zcmeHFI}XAy41GpILVU!?$N)EB%mI1;4#Us|iGhKU8^vvDdJ1k5UK%Qu3%$7T7-N>ZS)Sv($2C3pEwm*8l*KVE4!iYssjW(Ugq08zV+ zoEgW5oGhC|0(^MD0wDS6!|J2y_jUEf9#@YmE!XRHHp>^5FD+kLzP5a8d2cz}KHF`! z@7b=iU1hrzZuJeDH~$V6fB85c?B!Lmw(4!HlBKG%TBEIY)=9Uke)(Q4xt1Jzov^jz zch$kRwy~jV7xsq~SA1t+yJ`K+o7~%;Bc$K{DY!54DqBlwzYj z>}z!hVHG~od(PKYKZT)_C<_=$=FRb(E=dO@=q9ILhQ>bbf{Mz^nRIkSRJ^VTt(A`O zf@k!3$-{nB1G{Lz&U&}ulSz}NK`Q9}M#Da5B{CH>Tbbe-8Vcvjw4mYm(1XxN5=-JI z>1VpYMQ=xu3T>nQW=*2Yj4Q&R|41YQ795@AtzVi^9c~LQ)mAh5$YA({j|#l@ tg8r;0;GbTO3mzH$ulPL- literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ESPEED.PCC b/CONTENT/BT/GAUGE/ESPEED.PCC new file mode 100644 index 0000000000000000000000000000000000000000..11a2c3ffb05946cff73f46c6b0dba32c682cb7fd GIT binary patch literal 2596 zcmeHIJ5Iwu5S>AagaC<>l7<^l<^VYW2ce*#NP|Q{LCKB$$;U|qNdQ5|6$qgLM0jt# z>p1p0N>Wf|<+W$$KW}H`y_)U{)|Z^f)y|uOoMGW@o^!d#XfGl9L-UQ-41s3yE48uc zx9F?rNc2H;Aleu0nI{qLxTh=H77d*Ki-bB9y~oF>hYIBcC+MX%Z5%+YYD9JDTB{aL ztAz4dWtC;bNFtrWVbLhS&C0m=_x zK}Uf;GUb%CAHo5$WsfnwmZZKVomaAQ>|`GA9TEnkG#`-ZEgE%GjtdxB!$l<)zR2;$ zigB+o%1`4ym5h4i#93ngSTw6H>=RN~7~N6Roht&)-BGz?jYwN^49uMm%gU8E1*?lq z7+qfeNW{=8@q!C3m)G?Hg9Ll6C=BS(2FdJ}-W0o#psf{zEy$e%Y-td-p6l<8Zip4R zcC>M;8=hl2vEw-a9b*^AlrzeijP1N~lnZm3js050z+{SxZW)A#Qffbx8f9dJ(lMP- z60*#60wRNLNrC-CCO5$^DUeB^Dit8(O;pGuGYbSGkZwM43Yhc)Glr{*GBG|(gG1uU zF*HoCFoY!`@CqY4m0ls^5TBCp06(|&{)sSX6#s~gS%`}~zC04St=H>^r~A#O+?>f> VQE}P%8jkTB-mWbI|AhcL{|~Scr8WQn literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ESRM2.PCC b/CONTENT/BT/GAUGE/ESRM2.PCC new file mode 100644 index 0000000000000000000000000000000000000000..89f9700e92ef26d0ce227afc798b564844bc8062 GIT binary patch literal 2348 zcmeHIOKub~5UoK%LWqU8?6O8I`Up8njxtBc5jaAQ5bSpMq-Q1!Z~-JhEGYy6cIG`- z+tWQtU=oR4db-B$s`9I^?Wd0yPXy14#dBFc`mn&XX&M#L6VX%AGts5!h3HOHWv6nX z@=9f?a;9<$y~Rtex%ZRAeqZHvI%eKV=T@?DokZ7zwjf*g1qfaSNVYDH(v7S}>1Rl> zEXuVbLI#=t49_}#E7I~y~{Bx z7>u68gwqF)c>odP4G3>eLLI2kfspStCd@Zid8qlk>MevxzJbeZ&#{e1Y{obT&R+#P z0KCnWo`dglKNRp%#u13I-h#{EB7E-AF`?q-@XQ;w+4s?3gRMev*-NYrUaC(WFUV_z zO+E`_DXHq##6N&R1p-h3di*D&2Ms8B%nDQV4w4Rj?;E1DC)1s?9^58p{Ab2rO^sLZ zTFXQ43x1o!qvad$8CsHG5VD#cDWw0*5(aJvOW`~(^~==IE>_#Q4U3qCOY$54Y#F?U z&oO3jvX3*e&1?5Tn1KOj1NY7?2L9Rdv~GKXhtN8^S!~c(($q#*)524S`;!Ge+@pKU z7A?S2pzQj;V>0CtRUqc!8N#+;ijO;P?IcUWia;b8j XZ;ytu>2vQ(zKxetV>AP-O) zO%v8A5%4L*LFXRhsKdPo`xx#Z5h5i_%7EGNnrqrcz`n{IVkjXIUPmBRkY!k6&NT|j zNV@0~C?>=Me++9Nl-MC2qbHsR5`iDF)=GoXg_@4ngwEy+)*Kp!72Yx)`I8CrOWWONR;5O{)?t?k8EPOMe-&bBy@DMh_V8u5b31@goS575je#xtaqQ zJ@^2dL00g+krvc!Bu~aLuriFteP?bQ+VV%2@#`$(+m&em8ND+@7MRK1V^{%Qfk8t; zQUQAW&xHoEME_N$Fh#GiQ^WVMNpiO`^;Ut1-Wu`SDft#W;=_2?`;4EgfyjIS->X_8 zjr5;c!oVg!P*|{<8d}F|yvyMcKLTTH9lSU`$I8HS$v&v?gk){DV-QCXu;d5ZpCP&e z&!f&-D09$P$~1_2n-(5G{9ak${cm=}OlSd~4EYE;jOph}Ync1z3fqDyKJMh5p3Z-9 r-hb+vIOUCkUtu@OmFO+6lUtQ5yGRP|O`k8{CqITi8TjrD^nL#ZS4pKQ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ESRM6.PCC b/CONTENT/BT/GAUGE/ESRM6.PCC new file mode 100644 index 0000000000000000000000000000000000000000..eddcc7a2113aa3341c6710c0c4e1688bc8318cf8 GIT binary patch literal 2371 zcmeHIOK#gR5FHmNP!wHo+g;X07dk?YlB4(tIYN(+BcviFIg;(<2m#t=n`yJ^N_}sJ zlw~(Y(g58>@x(M|_}=_9eE)XwPVjtMe3a#z+Xa?YRjG)ch@Og`i7rJiL~le@Zd5K* zzNjo!&QwlexA@F6FMdYxzkB&QK4+bz4J%oPR+`X3wh%ve2ZUOBXf~nA+KqHs`vY1W zYh)V;(LmO6m6hM2OxUADz^4$i&0y=4?Y_Z|`Us2|t{@R2HICH*s{uj;cjzhW-YkE^ ziw?&-{A%rd1B^aU%RLI&$VxA__@0=v1JSH46AzXF!g(+e@DY0}WFls%C%DdB_J9${ z46a8Izp#;jLt(z@Mx7HvjB5x!mV@bw1}y~X9X-0Q)CaOw~TN@6n23 z?gQJef*k>ptk8$x?(Qg>2}&h17)x{nn*lcPyOR~D*+j&)5Z!MtkVDgNhn@^zI#{Ns zop}HS-8+hPrKd+3dW)XCG=eSv)4GH7=zzuy<_s+~E&Sj0N9k0i-YVdY!Zu?R%Gt8k+YCY&90U528~%r z5|k1?O|&tvT`*4KBck-`Uj%G{WJE_^1%~McoK1uIQ#j~6WsThUyT+kZQo~`y_m;&z ze0O)43GKiEQ3gW6^r`p&%^Z{14cLfzI9}Ky%-r*)@O)B#!0i90E8~Q>3qFWdc5QS@ykPu?wExW7{i#bA$lB3KKas-Z$BLutsGxp462$5jP4QRwR$h@z5 z?D2#o43XGn;!4}y)$hHk>YvvyXRl1ZceA&)c=2tf*ZF)N&Ekp0Q;TO77ZxupZY@UJ zM!SgiA=)C^S+rC6&E7NT$-myx-*@}iAM+lp${O2b!B$yq>#VgRTgn;>*~-ccjGw~F zt<5U;TdUps)$Z50-w*i-rgXQB+O?ocK^2+;Tn3DD@1J+xjICrrh5&*= zQZdRyVw#a>mirLSYjsz$$0uFOLr*O$G-;!jNw>CCU+(>Umr_$oGbzCrgA*M@aHAF- zgO&+wF4(Ucy7jC9Nx;x8Wvw7;waIezC&)Vcw1Xr2RD}M*B{jke!b3tzOeJ~9fr~J} zxsvHA4jLTDzlzf-tq7(#13JOij{ZwysDxpUp87y1QHRj}HJ}%QPs@iTatQxLVh8v_ zORkjdpjZSCAQNCI-L*BlOoLoxTNy%2_20;&*E^yUvZnyOdOA<`*fUi>fOncWlyRuj zR-r&Z>aLwYI7|kXq^qC*bkwp|2&Fqr87hrblD}Uj@K95*2M%htl_>}(X`EoEe`FYI z%fNjk!GVWB29hi7LG+THjgt&txpK!lIa5PgfqtM8iq+k;hElozB-(Efwl6!ew^Srg zRN_KO=|m~L#}Muhn-tYXn!~soS=pUd8(RZRJ%?0(-5sgS1kW+oO->~cVM_(1Wr4IK zTQ#PQkSQNa;qK;U5he7X#X@3+F>#x*z?5a4E*m5^nL#uc4pR+ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ESTRK4.PCC b/CONTENT/BT/GAUGE/ESTRK4.PCC new file mode 100644 index 0000000000000000000000000000000000000000..3e87a613df3c655ae468405c3b02befdf4c4cd8f GIT binary patch literal 2480 zcmeHIOK#gR5FHmNP!wHo+g;W{7dk?YlB4(tIYN(+Bg7&p$yO{YNe|E)g!{ly-W!UP z;>L&*pt~rVP$p;In;*&VUl-p5&-vn~EWi9+;Ik--AQH|bTu8W-u#|8up_dS(4{{yk zcaUX}%ODrfTl}KUho3>>-=nOCQ@)*4rjgD#xiz(H%|@(QLmF|WhY%wGtCWqYRBwxM z(yO6!H`4=*SG5k~7Em5g7A92l8O~wVnRZ6z@cl4qbL|d}C33oBvukuOYL`YzU2-tE zf79R|hIng;RRjIGmo=tJovyIt;eSu@{b@Gf)rz zYiY*J6WyXeqhlWPOdr$10O))~*L2Wtysaib&&;Dp1T73xX;a;Lgv5+6jXgqo0t{`5 zNI__@ejc#Xm-Y>FaL?64Q< zEmPAeMf@(2I?gj)7?@Q8A1MUlR5i3xtoXk)(|+M5=3YrHh0n;u(JM{N>nU{8ffFO@ z;IYeFlkLqta+K=LEfVX?(0SCgvy+J>B3mpSM|K7`ePpY0(ikvzIGf;bm$Q2!xM9-9ia2zWiub5$D^rH^uwcx=L9`F?Z}^B3qNqtyz72C<5h;Y(5vi9!VT}Sn;=(u WgB4txKOerxJ`F!J@V_%K48t>uA=p9y literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/ESTRK6.PCC b/CONTENT/BT/GAUGE/ESTRK6.PCC new file mode 100644 index 0000000000000000000000000000000000000000..9b855ae2c8575bfd99f53fafa04ab1d31deb4387 GIT binary patch literal 2494 zcmeH|Pjb^R6vkheVTNH?Xv?l^hDDChqx2{_LXW@^dW2$IcH%TnC>($jfLH@H-%qj} zH#87B!>+Dh<>)NkNRweax>I^qC_ zSoD_n1`H^Gs$OuzkmQmkk~X>xGWpjs{$tcgT7mdzFeRy_sTIY(X`rIKz-OA=j(eJAq!@x2ImSYx zc!;Ko&^ek+v(=8oV^XwLS4~q^D2?byod#5ZA1R9Bjb>`8RQ=zn_FE=x=aj76VuDU= zj6PDOJfA|jKYmhVoxHBb9h%RYqf~$0E~(yx&%w8zoKutwwp2z&I%T8Wu`_AtoH&AJ zr_&IJyPa-I=#^S#GoX>e>Hs|-!*>Vhu+aFRAD&R07kGBs1u(rNUg_HTr`zg`i%su5 iUTl{ZuDR8&gI&h^Y>saFJo;LDTKJTK|DA!p?|%V43f-~* literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/EVOLT.PCC b/CONTENT/BT/GAUGE/EVOLT.PCC new file mode 100644 index 0000000000000000000000000000000000000000..e9225ff43c46301f5be0bb44472c94639030d70d GIT binary patch literal 1269 zcmd;LW#nK00#1gV3=K>V7=g_HKma6(Lkx^uAnjy>Q;bAI2BK9$%p6sZBW!tqu|--W z12wp#N3r|=!~Yrn%a@BYFmzj6Tk{)pS64H%2Qy4YSBQ__3^W*+(ni5(2+%78fGHmU DX*6hs6ZeP2m}Jbl8TASiis|nsF3{Wr4cHP=38jEm zz%1b8nB0;f$IpnL5P66!L^?thp^QL4 zz#;$>fD0KhV&sTbVr~@kdcqs2V5g#+Nq#O*^TDi8=H+lvs>_YGs`RiL$Dc;}Y35tI z+&R_G-R`}8J*jKI-us80f7p75$~$hnW9c0Wx5?cmb(_R#BIgu3roT)0Q}Z%0ubz2zjH_jkVbFL?x=xzb8I4F)X*ldC3JnG%%Nz;E2Z+7_d;rzi literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/HEATPAL2.PCC b/CONTENT/BT/GAUGE/HEATPAL2.PCC new file mode 100644 index 0000000000000000000000000000000000000000..a60a614f3de2c0bc1cea864b3d96e2ceb65bb46b GIT binary patch literal 915 zcmeH@D{O;c0EDl5Xv?lp(oA%&XC|Qp2^js`a>@&{rdSHH(d1ZJm1S zZg$?TnKq5z?EL-K-*3Eq?H$(Mq4Ex;+ZJw{xozsSiF1sdCtL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/HELV15.PCC b/CONTENT/BT/GAUGE/HELV15.PCC new file mode 100644 index 0000000000000000000000000000000000000000..67b9fee837ed1a491f8f3773972467d8929d0b59 GIT binary patch literal 1546 zcmeHFyH3PF473X*gzi%i-@#A8$L%wS0tyiCrMhdSE<^t7iqAfSvstm?=0!hTg^iTkr|eN zq!E1*$YnDE{hXHFWs`Q0dDoVE;sR4~K8DB$=y0q8Nk8|H8Oc*kYIx6>x~w-6WYAyp z+siX!GnzGG;d+$?kT!6WOwcL%^`FnUAGl;?QQcT6g&5eAU>jZNXRN+h0nx^e)~#Zr zKtV~DO#KgNkHCeG2~FJmXE+bzj# Yt#$^7@PPTeZt}MW`hI)wz)g1G0^$4nX#fBK literal 0 HcmV?d00001 diff --git a/CONTENT/BT/GAUGE/HELV18.PCC b/CONTENT/BT/GAUGE/HELV18.PCC new file mode 100644 index 0000000000000000000000000000000000000000..1dc2f99bcab9ee51d531618757fbb5af0a21791e GIT binary patch literal 1660 zcmeH`O-=(b427Kq5<-ZRAkM)};T$tbrc+q3VZ{ZiE-Uua_r>E*QHxZTNKMCb;ynMo zI(Ike*0f&i!JhTgdYT?l7q0YrA@DqGvdOlVtxs=~Rg>{&3J)9p^|;Dls}l(E|V zs9U$HtE#(Sy(nG=z7NHl@SY#vyXmdnBfsKf@kr!F*c9?_3{9wu-?YzREIRrxv<+x(6A3fEx~*2M_64@-Df#X2+*TQe@fmdG2%Q}_|F zn@~ku6E<)sYz0Q_0vi?UQ}`a{j91ugnOBU5&|-HBZUmRHBiL_XE7mJ~YOy7z22#8E!q+<-74jNeN#4b{l~Gr` zG0?VSF%9i5hceeQN6S8#x*c8kM6U~(Lh(SGf-7C%uccLCh>&}kN|=P5G8xFfn1&-n zrZszOfEYJb<21RtV=Bb$86KVZ2b)=z&7D^CBrTG5F-~oaqd9qy>!rp`ge$sT7@J*c9ivt!?}-ZOT+WJ4Z-hNJrH)Q1fu z`Y}I}xE*urSulb6U|FT8Tp(Bxc|$mZK;WJxfy%b-*jMD1;YB9~95^7H;h`0t^{ply zkSCY%MS_(61bm3Z+sfM}g+VjAyrOlukWI;uT`(@$e3pBL(}6qOoP9Z3IF_+bTam*! z=5wyCEYD~AGLLs}K9>4oVsGypL$Qo&a;F5#bIrPku)DbxJpy{*skIE8=PGmVZ6=$y zeJT^JX#JdRjG8rdIH!;j%NC|F#%5s6yZKzp*TG1snFa#hQ_#*4(b`WAXV icjQyA_h@acAd>O2Hm(7^QnpEEN%dy{0R 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/DIVISION.SAV/RAVINES.BMF b/CONTENT/BT/VIDEO/GEO/DIVISION.SAV/RAVINES.BMF new file mode 100644 index 0000000000000000000000000000000000000000..0af2207422f6f457da6870cefaa1b118e77fb700 GIT binary patch literal 322 zcmZ?q4AXV;j51=_swz*vF7okM}YD6uRvFBPOVKDQ)?L6L!n3CVHF3_Nc?xZ8j9V6#7X zeT$t6gzIk!;c76jf-O;C@Z?Ysgql>El$4W-Y8J#NK(oA0C)j(ltJ^0$x(6}~#NEvb N;R4M9dyAEU0RUp#Tk8M- literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/DIVISION.SAV/SEMIRIGS.BGF b/CONTENT/BT/VIDEO/GEO/DIVISION.SAV/SEMIRIGS.BGF new file mode 100644 index 0000000000000000000000000000000000000000..464f71b3efc5f09e8eeeb766eb183ffb1be369bb GIT binary patch literal 204 zcmZ?q4AXV;j510UhWKm$^VC7U`WGrB?Dq;|DnA@=D?3pvROZ{d$ zX!y4|6f&ro+05M!5?Xye)ZWK@rag$g>Lafs0}^mx$TCx4WN>0gHc${^OiC0OfWKm#Zm*P}lWGrB?Dq;{|5NO`{bHPN1cdea! zn{G^WC}dEnZq`5WS)R#Z^DE~4Ue)>zKMfx_oM*KJtUoO#b?KV?dvUHkIzeFzsJ%mA4;9mS%+a}c0BjCE_nhs$1$NJk4_Ef>Ru9H%m)6R4_M1M*+Mj%?Z|~dE zi&ahE)E0ZMTY>f`%jE12L>FLHGkHRt{Vz^qdtU}e76u?-1Y#y2W(H!A04orK#6W-z zh}nS{ln^+9m((0V5Vw4Tv9iVW&MP{RXMGIBe3(!%)K#*=Cz6xrv~fsi`OI z2-#KU_}uP~gt~*@#e)v9xl4hG5!F3UJ*w=*y&dfH7AM-*T~R6KAGisOw_LVO>0F&pP*+4ztSV z>_N}mKjWnBbAUAiwURqp<{nKxgE9H|F#?khDCsOInC9%{V2`ifQ)295_%jr%Jx{&w z_Mm1VsELT4>U}4M*!QR=*td%*9{6zWI-skl?*L*~%z0$bfCL;E4w@-2GB`2pGEfj^Oe#sMu*ym; zNy^%k+=PmrR|KKS_uzHY#-5Gd5 e&SV8*HX!z8kOWZ-j6lo;#LPg<0>mJBAO-;Y3RF)3 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TRUNK.BGF b/CONTENT/BT/VIDEO/GEO/DIVISION.SAV/TRUNK.BGF new file mode 100644 index 0000000000000000000000000000000000000000..5a9ea40c19b02ec4c1fa9e5c5cc9ac020bfde948 GIT binary patch literal 2350 zcmZ?q4AXV;j51QaN1JGVnHMw^^><@Cq+5a?r23B({cM67@1vm5Tbpm|t z18-^X2ifJ=^aw-E1D`hgV8>+pH8N6QHQ%P|qPPWQZ=Y9X^G){0S6kTsyK=)0WX}B6ycp)NUFo!Mm>ywYaE=3P z&fEqy3^h7WtL(4dEr7eHUF_#R^zey{o@^&@WV>DT#(c0jk>c+A(bfF=8fUk?J=*U0 zE)B36Tds5rH8;yo+I^X0W+&Ps1y<8IRT)E#mEl>t&r4?6`7$W7umTeS8xXStF(^fF z0x=g5a|1CC5c@KSf|M{Y0x=U1GXpUT5IZ@vFd8TbLK96%QE6T_QkuzN>~c_G1f@fu zQU*vmL`@GMzg_hawTG!OeQ$vgCY29w+a-w>+An|MVW)7(-yWNqxM}$yBEKZedJ9B6JG{LP*7roEpnW|!W$GnAOMO3P+WlG45ZG9 z;SeGkiZb)kk+Lqs@-Bu6pui&(FvJ8fF#$tN0Q)isVtCroA%Y25Ab|>_<^vW^qiJh2 zZNUpsSf(RCZCzsorY%sqTJqr;Fl}k$DYy6;yBKavSny*nFlT|QQuHDi#GktVnlZlI zz_dHhK2!9V9lo3wak|4+(e;TPtoXxLOn{1rna1C2@%fy$>M6MRgH``mW~Bj(T(qL? z5sSUrWk-8o21AUT2ND1kCm;YSPC&&ANDRaV6+KQ2GjSI$bzKZO#CVdJz#_(z?%)~; JUR(m*2ml0kb4LIG literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/DOZERS.BGF b/CONTENT/BT/VIDEO/GEO/DOZERS.BGF new file mode 100644 index 0000000000000000000000000000000000000000..23e636f3024f7757748066bb2c20da6917298c74 GIT binary patch literal 268 zcmZ?q4AXV;j510FcWKm$^vEo!bsbyBh z8Hp+RCISe253gf zUkVBe&C3eD$iT;eB52oEhm4^0t({POm;>!Y+1x0j6!V=gwRV9#{J8g=bMH;71_pY3 zfvZP(;^HKZ6M2c>#orJl&UwHg*=+Ynf0(onYaZ`S?We4byRzTb9;;)d%TU#vo=nOl zI+P>ISyfN&^%$yCCI3B&@|r&(*@%zK^-3<=NJP8eKN7wb35Lw~`khFK(CQiTGC)#< z$nbz4JUGT=M~+z@_tOj#b+_`rdeN$z^WbUlImXtEBr0vqM_Df{f{(o;;EJ7xU&St>Uw1t9(|$qTj=E7E02@;~t^N>rwR9W# zdOQKWse^vCH0h&yapH-UKLa-BK)+avp|h<3H`>@A>^5RAWx9pU_HJ9 zZs^Uq!3}+)dvhMsH|J&gihT@ujUTd69s~>ZZ7Sxk&4RV{JpA=|8eENiXL)=PtUIz+ zeFbdh;Jy#%*}X3JUC2_u{Kg*4-}$u<+}w}dqq(1T&%#oMelPQm@c+}{f&Z&d3RwMp m30ykNzK>9s;r}@}?WK8*KW&@Tg?nn_U(hd3yn%iTA%6j_r(ya4 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/ERMLASER.BGF b/CONTENT/BT/VIDEO/GEO/ERMLASER.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ff4b158a482ba1369efb70b627c3068b749fa14c GIT binary patch literal 4176 zcmc&$e@s<%6u%E1@7b5&bKffS<(SKP$p;7cRhXjiT!)roDrC<_-TC3oGYWfXA z&8B@qBL3%0Is2kh5bpP*+lFhKhob%kmi>SIJw#_ z--2a!4mt99aX4GPbisxV9V&;DtE=cw@UskMs&}kLS64%~1KtSAVCRMRL(j3k`Y}va zKdbH`hcjk$!2J`6EDqj{OkJ+LC_AL~z0Ejyrh3lV!{uN<^uC&l!!dqZ2BVP&Se#yb zFZ#6a7Omgvj={RVX8Y_@&v5BR&3W zHOJMTVH}^ic4c%k4%S|y(^K8;kmBl783*I&IoU^Br4RneMvi>PIGm}m6VjRRXbneS zJJsb#YG(Vx)zkCBQdme&!sSr#=#k%d_ea?Kn|a}fdg;mYjjS%rMUOXU=)qz4_i?_u zs_!la@4EDHdJ1Z!rsmz!HmEZg$!$RRA^Z_!2tbgH9E`k&kTTBOCe52xeb~>j>FSHu8~;#UWp$#vX<1 zr!LMHer{wCrt>>k93Qn$%eBjOaWzlMnq>|rSBc!&mAW{b_WaAxu)m1u@lpGPwssq@ z1GXghfopXvi(}(;|GAOd;M&@P`!kVG|x=d$=uPv6w$MiM%Kl@}9|g%+mvA8$V&ei8_0dd0u?uj22N*llHKcSJOO{5D0Yp;q7LoEk7JET)0S zh=!Y}`cR{?xP>zsW=WY9)zF6;zptonepFz*g`cN}Tme#Q07By;c zU+>*L6#72rm3nGxc3!Y^4^^ZW61==7)>CSf50s^w@JT1{VR zVrS@m-2WT)KGaOGclR7wWNTOp;Z>K#`{-H7a$4=dxdaA2Q4M{dYxIFGXxwP=KMg!| zzoHs=XiaTB&^2ah&6s|<40ne0@5NA4_bxMw8Fjr7?2Ek!nlXJZ_Z4|}kTZDS$7E5X zvZ80mdO*mEYUo3auQ{rr4|G8j?I|_%;o0$gI9jY}`lFg?7B!$TOKVuWtz^k)mh-D> z;4x9n{he1ulC)TF0#cCqITz3QwJD5kz;EX?m;vX(1#l6}f;m7BUYzr5O%JYJ23G(* z=rs>IfFAU^3KqaMaNW;uV7%$qZehF)?tn#b7Z|Vv?t%MY8LWT@e*O^Ss$W~fxDFnH P$6y0I0Z+juz&`&2NwJUc literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/EVENING/SKY.BGF b/CONTENT/BT/VIDEO/GEO/EVENING/SKY.BGF new file mode 100644 index 0000000000000000000000000000000000000000..0375eda937b4ca1ee0cf18bbccd9fab69c9b2084 GIT binary patch literal 539 zcmZ?q4AXV;j51|(Z5`vY$y%kIXLWKG*e(?aCF$f=%&B{RpRR8u#nL}fsZk%B(1`#IJ+`Fwasi1!?ST6eB-Z*`9cV8CfXqV``*j2)7I7*F z=nuGgM?iX^V!$v2fnP^JZia|KL_lI7zoCjTFo47$cEI8R5>_BFUj|1OkZxc=GB5!# mGZ2FWSb>-gh}nS{6dRmC%mu{UK+FTgygUzu?H!I0SAZWjAjaq3{DR784VP~7?VoU zDy))JfmC{3@R)PK)@tf!6nEs+{ZCE zM1jH0A&Rky;RwiVm|evgf_5GctAKVkKrur@(!#|DL2g2q1G(`w*P(+iPk3RIJAhB_ z%-w$nzgk*i=mWV06b3a#1{iW6`*7)VXP5xe$_T_vAO;XH12KpX0xUob;)4Jy5QF$2 ozy`!1J_vyHf%qT*V#D-;Xqa9Q4buyvVR}I{OfQHA=?97d0HA7k%>V!Z literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/EVENING/SPOT.BU b/CONTENT/BT/VIDEO/GEO/EVENING/SPOT.BU new file mode 100644 index 0000000000000000000000000000000000000000..ff4260efba21b49bb12caa20bfa4d561d8efd4b1 GIT binary patch literal 522 zcmZ?q4AXV;j51Uzu?H!I0SAZWjAjaq3{DR784VP~7?VoU zDy))JfmC{3@R)PK)@tf!6nEs+{ZCE zM1jH0A&Rky;RwiVm|evgf_5GctAKVkKrur@(!#|DL2g2q1G(`w*P(+iPk3RIJAhB_ z%-w$nzgk*i=mWV06b3a#1{iW6`*7)VXP5xe$_T_vAO;XH12KpX0xUob;)4Jy5QF$2 ozy`!1J_vyHf%qT*V#D-;Xqa9Q4buyvVR}I{OfQHA=?97d0HA7k%>V!Z literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/EXDISK_A.BGF b/CONTENT/BT/VIDEO/GEO/EXDISK_A.BGF new file mode 100644 index 0000000000000000000000000000000000000000..dc2e8a4e429362cf526e7f45baefbfc7bd4c3b41 GIT binary patch literal 2085 zcmai!e@xV69LK+Rc$^2ykBgs*awsB;fxt*i;CY_!#ZWL~K)A+C6lS2~6dN;FlaqyW z;XpWlM3RCc;gF2A!5_+x?@=6WC1k@2Cs<>nU!(~E8O3_ucHcGjO!{uGy+5D(eD=A| z^S~M3@TL>NlD+l9}DmN1Hq~c_ptM*_^lc zNO7*Eq)6fww-nZ(uVAm}%)7(nZyKxFWZP#`%#5yG={6Nkl+4&9{ySJzzbVPS;fFC>(~{sy9&hGwH6UcYioa>$2;+;x6A~(`n+I zK1oCC$JWy?tQ|^hcBb5^s}<%9)m9U^-~fGf-c$Kx`coGBhIp>{_^*lY$zXb^z-Ygh z5+t|#UK8d#j`1TMXA`P`|Ws_(33JyO0Qbh zQjhcxmEl}73-`P&^eDAWbVK(aWU+my!$z^sVsqy6&JoOss(#6SE~JCL_v~HayT+QV z)RHwsrmAi#PrGBWIgL;5*vC=Co^L&*I4lPKk63u0|C%eOO_79PpZn>NJ$qZmh3~?- z9!*{$`43ju3zA2al^b3V=Crg+WUNp^h14*Eamy7oMx9y^-9uZAm;>=A)FIJ*#|B=Ogs&{CtQ^m-~{qWAUAM zd;I&xSU9J(RYP@Iw-R2?Z0<_E(4b7V1qySzXC%sIbtLGQDmIZZqdbl&5PC)iqNw5f zjKrO%JlN{y3gwQ$OX#_k6hPm37)rV_UFBZ?Z^XA5Imi9Z?+0vD$uU&7IG@F2&7+?Au}sC6jvr5poCtwWK! zaojm-9g2JzXE{f$Ly>!MJUL#@9DUv#Bj*{8T8AR{;rMdYIuyAd$Db3x33Mv*6`YkE zwGKrd#975r>rmvYIl&yY4n=O_gmBb46!{v?T8@c>9Ex1^SFJ D&hQ*7 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/EXDISK_B.BGF b/CONTENT/BT/VIDEO/GEO/EXDISK_B.BGF new file mode 100644 index 0000000000000000000000000000000000000000..dc2e8a4e429362cf526e7f45baefbfc7bd4c3b41 GIT binary patch literal 2085 zcmai!e@xV69LK+Rc$^2ykBgs*awsB;fxt*i;CY_!#ZWL~K)A+C6lS2~6dN;FlaqyW z;XpWlM3RCc;gF2A!5_+x?@=6WC1k@2Cs<>nU!(~E8O3_ucHcGjO!{uGy+5D(eD=A| z^S~M3@TL>NlD+l9}DmN1Hq~c_ptM*_^lc zNO7*Eq)6fww-nZ(uVAm}%)7(nZyKxFWZP#`%#5yG={6Nkl+4&9{ySJzzbVPS;fFC>(~{sy9&hGwH6UcYioa>$2;+;x6A~(`n+I zK1oCC$JWy?tQ|^hcBb5^s}<%9)m9U^-~fGf-c$Kx`coGBhIp>{_^*lY$zXb^z-Ygh z5+t|#UK8d#j`1TMXA`P`|Ws_(33JyO0Qbh zQjhcxmEl}73-`P&^eDAWbVK(aWU+my!$z^sVsqy6&JoOss(#6SE~JCL_v~HayT+QV z)RHwsrmAi#PrGBWIgL;5*vC=Co^L&*I4lPKk63u0|C%eOO_79PpZn>NJ$qZmh3~?- z9!*{$`43ju3zA2al^b3V=Crg+WUNp^h14*Eamy7oMx9y^-9uZAm;>=A)FIJ*#|B=Ogs&{CtQ^m-~{qWAUAM zd;I&xSU9J(RYP@Iw-R2?Z0<_E(4b7V1qySzXC%sIbtLGQDmIZZqdbl&5PC)iqNw5f zjKrO%JlN{y3gwQ$OX#_k6hPm37)rV_UFBZ?Z^XA5Imi9Z?+0vD$uU&7IG@F2&7+?Au}sC6jvr5poCtwWK! zaojm-9g2JzXE{f$Ly>!MJUL#@9DUv#Bj*{8T8AR{;rMdYIuyAd$Db3x33Mv*6`YkE zwGKrd#975r>rmvYIl&yY4n=O_gmBb46!{v?T8@c>9Ex1^SFJ D&hQ*7 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/EXDISK_C.BGF b/CONTENT/BT/VIDEO/GEO/EXDISK_C.BGF new file mode 100644 index 0000000000000000000000000000000000000000..b3941bd2018dc0ae05e56d4ff01043dad069e457 GIT binary patch literal 2085 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FD3.BGF b/CONTENT/BT/VIDEO/GEO/FD3.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d4354e7160029521b984aeb2b859ea3e09d03162 GIT binary patch literal 427 zcmZ?q4AXV;j51*rjWGrB?Dq;{|U})H%miEk!f#HBX z@BBK)LIxEE28V+XA%%ks3<{1Ac7P)T5^!+vU^G);WN>tFV02U9fXH~bI5`+H8Yl=e zCY2JC7~8XVY~CfM!DR0gV3fV$Vgp=s?U+o$iuL1IvMD;$h}S8u<& zUdINZPT?R(9Yl-)s+WNwP1n`#+@Dv#plE>G5t+LWYDa?uG)x?md9CdsZh_n32(kkt p=F1?;3JMHHAZ7w$W*}w(VqXSHHjo4x5VHd@D8x8{m*rjWGrB?Dq;{|0D`k;eC$B9fm@Pe zA%hA7gTg_GkitPA+Y!ok1Sx?52ZvxrGX+KlM+a|4Hw6xeu!oD2gAJpBf-qxJNpfjU ziB(d1YM!H6d~Qh&15h!Cn}Zx<2g4nNnGFY)+^@4wOIv1-5K}k^5@TR!0OA7NugX4Ug9uVJwfk6Q7mmJQYP%)VQ92_p? z|F<_bz6>%Cs?Om6NbKyHHDI+cx6HQznGbTG0L+eqme*RrV(tt)ps-*BVkRK=We{Xx g2GT4*%nHO@U@=KH5StB%*?|}oc$`2Ck^_nZ0ORCn^#A|> literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FIRHIP.BGF b/CONTENT/BT/VIDEO/GEO/FIRHIP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..a068036295e70c4fba3defbcbe8cad68f0b8682c GIT binary patch literal 4530 zcmdT{U1%It7`?NbO|zS%$u^>kg)&0XRuPk|7>U`;?6ir5u#|u_RK*n0Z9>$hTO*}t z>c2}xkRl0+pb!4E#is^owZSP!ZK)4}c~Kw4A28NG_9-Am<2`rwjJGp8=~nxo1DDO7 ze0T46&pF?B?`$2~ezP-lcXwP|6*FV8HE}b(p>eFijJ2hbreREp-jZk+^6AXZ=T05o zxNy69!rCJ?7K@Fp5Ifzul_^*LZ54~pTO(ghS_tK1+uPE&nTE*Q9SwtK6W}i@#k^x* z9qTkZjN(LT@8rZIz4G(H?AXJPJ|tvtQ;(T6AJ{)OJ~3sALHie@Y>ylJ_9v`tcD}!P z@Hy*3;@Ugj?(DIM{k-=j_w>sdix?6)cURsWKD5$5Ika2F0bAbGXDtsL%T+O%bZsm! z*TuSlH58`j0x}SH{Qlima?!}$)YT&i@vzskCHI*^tIE&AvL6vkZ)jCbw1B`GzW8iW1+nK}mwQlj3Xam(MTZISKgT{6QaP%`%T!sF70Q`q#peHCDRHV7 zEJ-M(m89ASRME?sO6l!^<#%ODH(yib)k>EtvSjo2I+QBPbnQ&qaqNS2i?~yYm@&Q_ z^G?Gf9aC2KwAZJHcX<5>*yrDSeHs{g?R?9K!qAf?<`TOg=K@17t3i@WjD3r9(a$-T zYXHN#)iqRkpm#GD<_wHEb6p6#n%Mf>Ow#M!SQldB_ZH51XF);K7Kf*5Jt8^wbV!Y; z#yM=1MTLog_@$XY`glbkd3qlKruQ4p#U^;|(h23Yix`A_CH1Vjc1g?^GKlHdE*yq6 za#5I`i%v3gA*S!GAg*h`)dXas6mV6+bp|A}e-%U*LPA#`%t0T+VTM@rHC}=8_K}#Z z3RJ|e_vIYN9tr6X)!J^T>Y(_*y_x3J_f8YjbU2XN5y&s*Y9>~{x8s`8klBH0amt9x zn;s9D9oRoLJLU$>4(xBUcU^WTa_oT+sZr)$FG)SC6Z68sv@)JfU_ItW(tozKtHYVU z2Lj`tB`mx@(8wU4YY@}pbTPGcBaN)D3)8}Uc)%J=N7KTkP0=DEPLrie@V8XH6 z>$Q?t^7bsx8Sk~W^~K9~66RtreZRLT*D&wE+givCog5`ee@n)uD>Os3O&_)xa+0iq+I6 z1CCe>ZY82`h@;+CBE?49_x8@JdpXmtC612iG-z}Eeoqna6dC9deB*{@1(EhU0Cok< GB>oqo$afI{ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FL1.BGF b/CONTENT/BT/VIDEO/GEO/FL1.BGF new file mode 100644 index 0000000000000000000000000000000000000000..71cc45c9252877873f21eb08c318edefe98a6238 GIT binary patch literal 254 zcmZ?q4AXV;j51ONeWGrB?Dq;{|Kmzx&d7TRxR2Ude z9D;~~=o3y*Hk5|&92n-9DKIiPGE8+-;D8AIa&=;8H&75`Oe#q(%_*@;N>9ymG)yn5 zjL$8}VF0S;aAQdCUfFaQ9WS~M>J literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FLAMEBIG.BGF b/CONTENT/BT/VIDEO/GEO/FLAMEBIG.BGF new file mode 100644 index 0000000000000000000000000000000000000000..290a26d1fa2b9d8e6966142da6c1fc146ea2b470 GIT binary patch literal 917 zcmYjPYe-Z<6rR0n`K(o2Hzm^>nyrcW00YfCXYM9zhL18I^dL9G1#Ly$q^1u3f^W;DlDXy9YMIp@sz&Y3w$DLIk4l#{Va zq83C!a8ruPV1>a&6x_qzMTMf2B$$bJO;Z3hT~o_dofh~s#N;v(+H_>xVL2=GYim;b zvu37Q#qDM}*&M^je~YnL$OBpTtDe}vW6$!>dbHRn;lJf;I zdBx=>!oxlEY*o0<0tKxqcs=ck$q0|zRgj+VO^3v2Y4}~Ly|pC(2&sknFe@$b^^uFd zj?$6e$Km_OVY+kTy(C1q_KoGMp{pzw{KHyU?&3?f7&S@byR~4LJxV#G<@nb)0}tHfw(L9_(U=1(YhzUM_$-B=R!N?g0I2pAq5R1)N8FiU`KG@MU_CE>YAO1$ z9^M-zgh7zT?07g5FE2N|rfSV(-ov1GM|>?Q6^CuY2z<*T{wGsxiv- zxLk*nR_6(`tr`eisB>7C{(#@^_)pXuZiAkc#I{ zK~e7teU{=y%Onr`#($Ay(v6`C4uM0tvEz9w#}*FPjUDF>{q7vd(T}?a2iiS1IQm^U zHt%_Hj<#(a$hUJ~JaW8)KIEG@(1slIVt(`^$67Wu)5sndjKMll3w^jy6VGVpwtpqT B1`YrK literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FLAMEBIG.VGF b/CONTENT/BT/VIDEO/GEO/FLAMEBIG.VGF new file mode 100644 index 0000000..28baf2e --- /dev/null +++ b/CONTENT/BT/VIDEO/GEO/FLAMEBIG.VGF @@ -0,0 +1,71 @@ +DIV-VIZ2 +HEADER +( + VERSION=2:08; + DATE=31:1:96; + TIME=9:41; + UNIT=m +) +{ +} + +BOUNDARY +{ + BBOX {-6.7591,-0.5093,-0.7988,7.059,19.0764,2.7726,0,0,0} + SPHERE {0.14995,9.28355,0.9869,12.0483} +} +OBJECT +( +) +{ + LOD (DISTANCE= 0, 1200) + { + GEOGROUP + ( + F_MATERIAL="btfx:firesmoke1_mtl"; + VERTEX=RGB 2D_TEXTURE ; + ) + { + PMESH { + VERTEX_POOL { + {2.4853, 19.0764, 0.9001, 0.561, 0.141, 0.043, -0.2, 0.6, 1} + {0.2835, 9.067, 0.4099, 0.828, 0.402, 0.101, -0.033, 0.579633, 0.697047} + {4.7859, 6.2476, 0.4281, 0.659, 0.204, 0.051, -0.194, 1, 0.5} + {4.2288, 5.4624, 0.0423, 0.624, 0.231, 0.075, -0.2, 1, 0.375} + {0.246, 9.0905, 0.4098, 0.828, 0.401, 0.101, -0.028, 0.576131, 0.698689} + {0.2186, 8.5412, 0.2181, 0.838, 0.416, 0.105, 0.035, 0.599549, 0.625282} + {-3.2767, 9.9605, 0.516, 0.659, 0.165, 0.035, -0.194, 0.2, 0.75} + {-3.7826, 11.6132, 0.3936, 0.655, 0.161, 0.031, -0.2, 0.2, 0.875} + {-0.0403, 8.0209, 0.3118, 0.84, 0.415, 0.104, 0.08, 0.544957, 0.588301} + {-4.0912, 1.976, -0.7231, 0.78, 0.408, 0.125, 0.053, 0.2, 0.25} + {-0.2212, 3.5977, -0.3671, 0.902, 0.62, 0.309, 0.285, 0.572117, 0.308143} + {-0.9121, 3.2437, 2.0354, 0.941, 0.733, 0.502, 0.153, 0.6, 0.25} + {1.0239, -0.4439, 2.7726, 1, 0.988, 0.973, 1.2, 0.6, 0} + {-6.7591, -0.4241, -0.7988, 0.976, 0.8, 0.502, 0.735, 0.2, 0} + {7.059, -0.5093, 0.0944, 0.859, 0.478, 0.137, -0.135, 1, 0} + } + CONNECTION_LIST { + {0, 1, 2} + {3, 2, 1} + {6, 5, 7} + {5, 8, 3} + {9, 8, 6} + {8, 10, 3} + {11, 10, 9} + {4, 7, 5} + {12, 9, 13} + {12, 14, 3} + {12, 11, 9} + {12, 3, 11} + {11, 3, 10} + {8, 9, 10} + {5, 6, 8} + } + CONNECTION_LIST (PCOUNT=4){ + {3, 1, 4, 5} + {0, 7, 4, 1} + } + } + } + } +} diff --git a/CONTENT/BT/VIDEO/GEO/FLAMESML.BGF b/CONTENT/BT/VIDEO/GEO/FLAMESML.BGF new file mode 100644 index 0000000000000000000000000000000000000000..15bffa49e05cb3e67cf2b3fd9eddd7de7c8acc85 GIT binary patch literal 153 zcmZ?q4AXV;j510ObU{PRV6ysE2WGrB?Dq;{|Km&ygDrh2Dxeg5G sW(tf9P7DSH3c`#@C218_#RZ8)*+r=-@wp{A3?NAl24PQ33s@N#05-)A*#H0l literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FLAMESML.VGF b/CONTENT/BT/VIDEO/GEO/FLAMESML.VGF new file mode 100644 index 0000000..81d7edc --- /dev/null +++ b/CONTENT/BT/VIDEO/GEO/FLAMESML.VGF @@ -0,0 +1,30 @@ +DIV-VIZ2 +HEADER +( + VERSION=2:08; + DATE=17:2:96; + TIME=1:22; + UNIT=m +) +{ +} + +BOUNDARY +{ + BBOX {0,0,0,0,0,0,0,0,0} + SPHERE {0,0,0,0} +} +OBJECT +( +) +{ + GEOGROUP + ( + F_MATERIAL="btfx:sparkred_mtl"; + ) + { + SPHERELIST { + {0, 0, 0, 0} + } + } +} diff --git a/CONTENT/BT/VIDEO/GEO/FP0_LP.BGF b/CONTENT/BT/VIDEO/GEO/FP0_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..c3593a7027ff3a7f2e1b562b1d9dd135dae3b11c GIT binary patch literal 300 zcmZ?q4AXV;j51fAAEM!obdZqYafohk-6{$Z5r%zbvcxKBBhdD}592t;+1H&mZ1x5xZhIj)7A;zSV zv?oAd)9c^E$= M2*QV{XJudj05p(XC;$Ke literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FP1D.BGF b/CONTENT/BT/VIDEO/GEO/FP1D.BGF new file mode 100644 index 0000000000000000000000000000000000000000..109277ea7fde277ddf5321a3437447a423801305 GIT binary patch literal 1811 zcmb`Ie`r%z6vyvN+M3QT#u2B^bv(A#GO>`kX|T9=?#r^*rdX!7$lRQ!MO&pcO@A=U zrjP|?K^m0F)=?;nGhIWdP@z(?)#f@}mccAIDU%soAWk|qHQgWk;ShH2doQu=GR9zm z11}%GIrqGCzW2oG+F9*zy|%$ftOn6wFd0RoV00IW24X4|1;I;dx{1ZR<{dcM7?z@Q zW_oX`PVOQVgrpfEK8X-=DWzECr$&;}Okb^x-}4_z$4WMd0Gor z7!K+Z3e@6hdsqvt5&|TP#W2)kV#e;59gy1YHe)wzIt#H$>9lloU=Ue4p3@b7Ke4GfOGOq<7IM_geGTOz1iuj(R+KjG`Q&cp21J;-b-3q5g9`olU7pIRZGk29W6W7Z;mPIP@gdoXFxGeST0X z9!GXcXEc87m>XJIC9+74!CBD@!@oO`rFG_$hLjU<;#3VX#`AN~(9-kg>S-TN_(# ze<1zTDe&J?41SrI$JzzU?mUCfB+n{)YZo!bI6G5)7AkT6yFW3hEWNtMWa0Cn3{#Y-uNj2o73KkPfx z28`1m8ig&BOZm{z2z=<2T`isf^YuIU%yPO*`~n!q54~7uGtJ*Zi;Zo;!y3qn;zGkk G2mA$f#wKt8 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FP1D_FR.BGF b/CONTENT/BT/VIDEO/GEO/FP1D_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..62ba1234ddf6b257f106bedf2fbd08efd4f04708 GIT binary patch literal 3671 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FP2.BGF b/CONTENT/BT/VIDEO/GEO/FP2.BGF new file mode 100644 index 0000000000000000000000000000000000000000..15f1b2d2f05bf70f573f705d981425b71adab3ba GIT binary patch literal 1171 zcmd^7%_~Gv6hHU9!7!;=ARn8n6r0h|q>P$(%m`ChPO-sg7HYn|$X8idOeqUxVX{!H z#NS}9Xf|wRD@E8$mLkqI^XAQ@%vQPetK09M-}&A1G2{<8y#A?P6&e(-C{~rLOr5cC z1+2B4u{gMsUM8$7u!4GC(wD6WaNEgtUnH(m;%DtC;6Z-+}G> zg4Xnq`KsPzJ|m6`8JFjbeEd6~Z6zi>itUrWk{gE}3(#Q%g`g57QAMaG)DUD7YYBA( z8^H@tPTpK><$|7^kB1hP!%Jo}A)A5&(+|W+e;3|-o|g0oL}qspCxR|4?OXJ42Pa+i z#F>A6eGcI5h$gkgIhb0b&QcG9mOFs literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FP2_LP.BGF b/CONTENT/BT/VIDEO/GEO/FP2_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..df37deb74a8f7a290876c7ad3fa8695815b27064 GIT binary patch literal 152 zcmZ?q4AXV;j51nF1q&6NA2if)Ha;Nm_+fPG(7JQEEzjZb=RUNX~;n*b~!y HRt5$DXJ{m1 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FP3.BGF b/CONTENT/BT/VIDEO/GEO/FP3.BGF new file mode 100644 index 0000000000000000000000000000000000000000..17177716493cb243a50bcecaa3b539d304a7f6cb GIT binary patch literal 4187 zcmb_fYiv|S6rSC?)GhWwE40<}xKu5IF)3PVta0bwYLHjk5JCk)N^MdMrY~D0B_XvK zqro45(O`L`Dm2Cyl8|W7!roq~M&b`OM8GHsF`z~WK`Ba&8qYU(rgQJGN&Vp_vomwP zJ&!pv=bPC_7B}2evv|$D7MmKkNZK-NM#3HkeHzI1Dx zd07>9ajbb`XGiPfUDfR!8@gLMy4s&u*S4{hkwW%DCz-X)=}V+5#?pad=8sklq__2S z!y&6We>(N+zSUggwrk>xM&>z$r$YKErGKP*Oz8hra=;sHebyn9{@&7hZ{g-5VZZX& zQ3JPK6NmjhyH9v~b}ttClpBxih|gn;;>|tjWgfGp}!=ji_O>2Y66iVI2Cn+yZiA{sJn_w`6gK zFF!?oCXV%ioYneYsBGl3oqxpo6?tl$`6e#o=PLei@rCtO{3b5rA1CK<@ns@s6Ni47 z+!C=y@7mQMevn@jw_Ov*`b%?%dF|DJoUw0e{|?@lC&)wN(ftJu`zHCR{Q-GK@#y|$ zBG>T#C~^&xr-{RUm>k3V1Mlg>(}@4F9yzw_`mAU z6^Bpb%r|lAUlu>}$v%Hj`d2S+yv!AOnK=B;EIt$&J}5>Mn<_w6Z0f~=VpD||E;dzwC@{#?s{=0*^~ylO zp}1UUEJnqH!Wq2sRCMFLKA;;@2IeUp+7i$8fU(V2ZzVK;qc(FD3-=y PQ3pq{b@;#lql5M@HIZ!R literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FP3D.BGF b/CONTENT/BT/VIDEO/GEO/FP3D.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f5c3776be5de6bdb5a976f88b79388786c79303f GIT binary patch literal 4939 zcmd6rc~lig7Ki)sSd~?RvM8dWCKwh{gppMnH*)1daOwE+dgh zTmcz02on_-#3)@)BQ8-R8iR=E+gKET>Q2b(3)3Qgy?Hqz+mn`GX;Dro;n zER<`O!RFE+rLW7nELdNy2YugENJtD<`pPDEq~ZPpA!lgb{{@7t;yH8s< z@7GG{^RTluE(uyqlA=6d?d7h3e>dre$E>oSBaEAN0;ZJb%YXJ=U~Yl;iA~R9&?YQb z`l27#!s{Dr$%6?=kk;lqKY%KdI`x1)ZO-Qn$_3n3zBCE!9A zdTxRPW8Glw@2QYSnktK5@X$=>UY1S@lRqSyay==oiwCoVd!hPkb69aO#dN=JS&JCn zZ{ROgBs%G#GRJQY)qQ4#`9W>>4W#Rl>B{;=xs4Cnzic?TKiN#y`3_O~aIDq75M^xc zf-cHht-8L4zLQ-^YGRtf2kW0JeTMd5(96|ZN!f)i;F##Etkt7|d9>%1B;xy7OK=`{ zN%^~TamQ#x?rt)B_cIbK+1l}>u;=E$Elkpx^NXb6X2wm+4LdBjS#q=D=E%*7TQhFX z++O46!mT;C7Tm%l7YocZ8*WXwHRWc@O;4jOUzl_@2HMXunO2xfaXN+zUbFbV@zDWW zw$3k<#Y|sJj$J4x??Dc1%Wg|C?)Pg8CdS+3_ks@QCyB$xJcb`)Qol;$nSh=wW>`x$ zG5;&_Y2pzQkedNNB%A<@&oE46Vtn<@c98CSg&5y0VUkn>OGaHWUJ0MXeg4KHE|H$g z_YwMKI(YBT28>5Pew&H$n%Guw)$@`vKki1Hf2%_zyR|KikX>j0GC#&~elf1jzf*e) zzH__J-@g*>7e>fSt|!3osi%rIx^)7NN6X;GxX+aMhMSw9U33~L_Kb(qx9y0(l{=VU zO@$LTzGOH)ztTb{jxRi3Oop5qMYIVm=)}m`(An39W*+Uu0={*Hfw~>C`{C}ecHts; zbm@YO@uF*zuBe+63z`%R-#ki^FJAkZ?3uNIG=J(t>&{m}RIV*G8xYBK2h+%!f)d$! zbs+eEv5-HXjS=Vfu+!=a1MdVqDW3~LwUI$(zL~_hE1s-7kVf$S0V##B^{g$>ZlSQh zViECiwt_B^DbQ+^7sc;W*|aHL6I6jUbW`6gS4Lg`#12Nt;*%u1FUIv{`rpS2zPNOxtRY#q`<%WUj<|dQ* z-nGPg?mRMi_Zt+yuT_mbEeVc8gsoE0I=uiO^K*oU&T)r;lx>4V^|$B$&J)pmmUyL;AMqZp5M zvj)esE%5Cd^OX1R=&+k*y;il>9{HiW-(iu6e}6wq$$R!KZ>` zypscQ^Szb%C(LzY-8YORbq^Cjns%zFG@>_1F(*k@|8$1$=l5%+@o(FEz^Nv!;84%6 z~|@Rt4EGoH2a9>3u4UHQ|%^T1wKr;g{sYNkyc6 z>kJsc_A1ZM>_;;({&|cSB-WKF^KU8YL~(v`{l)n)j`NFgb^c&F8UbsfEH;p|NL-P+ z*oWjr0*e&JJ|r;`xglw>jnqZrB6-nA!mAXH7vlxXW@A*hS&+ zy_zlWnivaX_6Ly0gkudCmWNze`cF9BM->iH7(Uq*$Xd*^hnTu!$VB#+F6}gJc#Vh{M#~(5lxvW;b$W>%6GE-%2Lk1&bF|M*#tgO*Th9Yal z>KT1xELPJE`HEasd8#rNugFa7M?)W(idSST`e^9m{m{@yR_kfL=7k{S$G%mXBuX`} z`k3~rkCFfH$G(3%R<%*`3ljjW&e#=}1t{w8& zkmbX{tN$}10=2Q~yD>1URkT>8s+Fk-SQRP=WfiI_NW}_Pty;sR@Rue*!)gvmB2uJb zm8PfGFW%8M2I*F^WE6$}VSIvoY}3b(JN~xmL@A!gDt*$(dEa;_&9yU~$nbwn8F_u+ zfljLv<5sp=#P!iMA{GwY7N0A6d*mGGzSdB5vHrv<76v5+gw5{g1i#$fZ7K|c2DM?s hEK;G&AnC;T$~o7`MyJIjOlo`s@#RrA6K*7Ke*k!h3M~Kt literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FT1D_FR.BGF b/CONTENT/BT/VIDEO/GEO/FT1D_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..9048dd4ea9eb4b98c6d598bda3f45bfebc127e42 GIT binary patch literal 1428 zcmZ`(e@t6N9KYAnQp&^;x^8N953C^@nv@@Q4Ac95DYP3ZhK;dALgGqoVUy9?b-Kiu z%}LUl5GBK~&|x%#j7+vAn7NS|dCwork}<#_W10SeVVND#r6y*{663sk^6GPQmwa<~ zpS$nx&s}ZZ&S%_p&1HIG(TO^pNiXVchFw{r&SJ?C1tCnTB4qW2zV!I7vH^D#r)mA< zl>2pJ-zq&NKi+)(%Z0%#xx9Q1c5HtSPn||2nt@nqaEbz{CO)rd;s-Z8@ zH5xonwI>j5?eO_udu4C5gYc_f;ygs`m#1DFPxL3hW;4~S$N8S)+|(AbicbO)9g}LD z$YM^ogQ4_|8aJ-eImEThOE}cwi&S-ncJB*>BAsoDr_u+Wuoz5UoE75OE>yO4OA~)Z z=*Y}G{j6&!7NBswU5;5} z$jfszJnFJdPr-$2R{6%67`A+%lWXr*&`Sf;Fm0o)P$=cQf6)(}P9t7s@rZw-n6r_387f}L=xQ-;OVvGpEUwt&nCe5t>WMFlbuiOPJzI0Yz(F?n z-pC}I31?Bx%G%84+!c&-;UOk@Ode*kdS%b?d?s!ZbBNXq9sHqAe8rn_&^4~J%elUv0e4JY9qOy-#V%3-FH(UrL_$LdM`eVMtjS#XH!GNJ5? zMs|n)rRF~b+$6+FT5IuoogKSd1s;vW(jhEDdAMjjrsuv_Jg;E5b#5CtFaM(4Q=_g7 z2jQKZKeU<1iF7VD9LeLlpxSGhG@>k(xwJki*W96hM$c;P$vwsS;2o8<_ORV-fUb=b z3Z}-gcx{nZ-5UE3*7BGQQ)5etUp2mjyAVxHW~e9C_f<>f!M*+G+~8-N8~pjJTyPUf z+h^t3w|4B;^!ejBInY;=OHY`MaIOpSSkE-wkXnY}RMK_AT!u&Qrr`L7OLXwLStwa& zkjmaH#do*egg1tJY2Nd*a5i~++|5`Xl%c gz6=Y4Hnf~+gDp+j@YU%rScZiU%#eR%e6Y;^1_?^SQvd(} literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FT1_FR.BGF b/CONTENT/BT/VIDEO/GEO/FT1_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..45cbbfabc16245b9d388eb685ec745bbca7abea9 GIT binary patch literal 1625 zcmaJ>Ur19?7(e&U>855$tE_~sF$jY|T$n7p_v{ucqk$3iAc8sBHFLQ&7xWiqXsr;E z2*N?(gB3pX5Ec01b_<+;*oYE(h#rhWBSA)l6!_5h-R*2Qbzb;(?|#4Yo$q(f_dDlk zpi$O2J zp-xg4BGzQ$WHd4~^$y;m?mLSA5yz>Hky3nd5Ilr~-ZMfGEHILqKO)mnzDC#%Rs240 zTfpA!>+JEky_Z=bvy+DTyOi*ep`Fs#YZg&a=A$@Y`U%CR#XsUz`dC8#?M#s)AD>Jl zG(MRql?Vwzq@QI|wRGamD+zg=e*-?M1M5i|Kwte?qW!{_wJv33Y^Q3vXu zte(;7U!RA0V^|;isHJK@q1cUIgW~8&0Q8r}GQC}whkX%|SCreJEw}#RiJ#(1{Jw;I zdVllrajkwPKfAuxn_n8z`Ejj&KA!0ZYm9^RkR~5=p#J3HXIcIEco*p{z#Qfy1AHT3 z%wX^$g%Cv$h#`k#&~u0(ht@Vj6ho9ipfNW=AckBS#AXP@ki#)J7BS>xvapd?O-?cy zCc}ECF?Z?R$s7ygvW{Uc%8iR>ouTg>>z2OT%mIp$>j3Kt8;85fcG^X%^6n(tL7Cjq zue9CQ-5&4+J?vD%N;|@&3GWtAjGm;afhF4cgPf4pV6*23lTac5@RWTPa z7b#z(Os36TjZl%jAbNsfpX|$@x;%&qvP}8>PPe6B@>}%zd5{?Mq|-VJ*8W>5s8*T3x0uB3DtBXj)f6TwaZ;Qs)5wB#ZH literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FT1_LP.BGF b/CONTENT/BT/VIDEO/GEO/FT1_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..9951b4090d4a705edd06ef84393204abde054551 GIT binary patch literal 334 zcmZ?q4AXV;j51YGAM|D2-|;h@(+hCh77hK8$gb}oVCS)VYU5!5Fg!yqSO>L6P9n{ c*$?t2$jcxd>o-dRz0KixPmvewZB_;b07-3SP5=M^ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FT2D.BGF b/CONTENT/BT/VIDEO/GEO/FT2D.BGF new file mode 100644 index 0000000000000000000000000000000000000000..194d04b9424ffa74c69f1ea10b1f86a4e249fb44 GIT binary patch literal 4686 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FT2D_FR.BGF b/CONTENT/BT/VIDEO/GEO/FT2D_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..1b304bd4d85c9ef1f2cdf557c309737e606d5756 GIT binary patch literal 1336 zcmZ{je@K&S6vv-;n>J1QxysORa!sN#wUy;??>U>HMUL!BrP8fU?`G!iW^+N@=m!f_ zDlq8hcDXm4MN!^JDriN%FZEBiR7#4vb-6_JV?=+9esa-T&slA47kuFGzR%}<&U4QD zJ?AW2v9`dpqJE*0X%t$8Lao#)vr{Z8twN(o(+WZ>)4SQEL*+FvIB*Q7k90^6=MS5< zusp_4W_&# z4nE&5FtcJ+qD)G@A&|n2q@$I}Z5%hMP#QNAmT>K6Bx~n#+kXBg-dJD0syD*bd;H%E z$?prI(fdkT(_$2F?JE=a2hZ}_1#!8QD=UX4z{D5NG7O;l2$X z{h7n>!f5uyio$u&ba`H!k?*=tAsXIfL2PV^>9@_sjO|bP-CswUd>?N7AU2NAjpss4 zpHhh4l+#IZYqyr-kn>a2H^UX2vo5Fs3jaNbJLO zzNgWqJ{`}^#5xj3y3yrqblW_(@6xiSPF5XLj56POG6L!UoZ~(AT}5K!EV`u3f48qm SV&qGVe5nU`@T7Y4>G=XDC8dP` literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FT2_FR.BGF b/CONTENT/BT/VIDEO/GEO/FT2_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..e97d23f6c2421c30dff8e9e9b58467e420bbfd8f GIT binary patch literal 1209 zcmaJ`$81>cH%K`^}p--}`2c^bhZq z`$zXVL3BtChsP;7JKPg4$svkfNe~JUF2a^q)p(>V-sXC>+Na)Fl`lX5fa_pbLSL94 z;bl>ZhC+kf#LO?}!>(RQfG8wml83Nz&!Q~DU{Km7D5c4n@L9E_WRt0L zO2te;%@=cNyObx!4+wKmBl4IJM1D=|V~?Pn+ZaGXzx;SV*Sco0?g$TsokwefZ>_l++Y5LcblS8?z{0H zkyKk}oeN=McQ>DP-*2jWdio$=$^9~NZGK~S7_0p3GV0>f&=UIBkL^r3(ZL5G>LSDz z&WU>h+~_Unt=2!S)H5%-51mA&oHleBt^}p+b#YVqT&k#+)OBegJqHO}F=Br4-f!mn z@Q~RUF(RyWBGknE=HyTlM!AGh?f`84i@D4**ynXBxqN0yRkG7I6>p3m6RvWDIaHRP z;yC$re1T=!bKJ1Z=UYeurxR!RUvb2Z88;I(Y@ccIYeCvGiqrijx@lZ*h*Mp|tlE^X zQ+*RPcs0fGN3-~I^9+5BI?UprS^PJR|F7-TRx-Q&Gzz3NjRv)yMuB1*+P+b1Pt0h0 sqf+6(5L1r#7;4$-p7Hxwi@Iub!hZ3C*X4+HuKo%-cT%~uY1@(EAN6k`UjP6A literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/FT2_LP.BGF b/CONTENT/BT/VIDEO/GEO/FT2_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f6cffd14844bc0e770df91341ae7eeaf4c7246bd GIT binary patch literal 413 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/GD4.BGF b/CONTENT/BT/VIDEO/GEO/GD4.BGF new file mode 100644 index 0000000000000000000000000000000000000000..e3421315245b0008e4f3cb13a0cddb5db42c070e GIT binary patch literal 3223 zcma)83s6*L6u!F)x~RNlK~TvR5wIjptWezl+(jWFQPO8huSx(@>vmAFFZDa6hZTkSk4IEd?EE+-A#Kx|v?9?N?0CMTb!L z4GW>}g9(jPfBdHF`OU#jX`SM(wYwXVY5|@t7>jhf5N{paMeaHaeOX|kRf#*5@#9*kW@d{^Y5P@tl-4FbPT8o;Uv!Tu zw)-e?Dc42UomNqku%BwnzYw%?D;<3=jIPZOA;*U$lu z)%RIk2!YeoidJeqI#$8^aK<*P+^>C5Bpg+565hwjydX7htJ_Ug_Cz(VYyF>UTv_od zaU$k5HE!O4K$X9jZ#U4?`~(I3osV}5@HeNzAjaQ+oxq>#VIYC4=u=mybMPnyTqSL9 zQ8|4vbCYeu+!X{)*NqNV`RmHLz?{ucz~6~|e+ckbb}7mk8=6AkuQEP>z*SEAS+Yb; zQ@~Zp`KHI5lK<(MsTl-L51kF5%J?0&b^C+l_rJ}eNMWD`XCOJMtEvVbx5#p4I+e%# zEBto_P}YGc7y3V9L^5rT=@H`|`qRSBOqUktbabn6*zc8PW_iq7hq~X4A%iLLH@B^H z?EtwwWeu$eG1AIS!9?dq3hZa*{eEgO681yff!c7n7!-o02eW^sv73;1FoVjfniR^{n zC^)mSxK7~Nc6#>1vtd7Qpv8d$#GyvX>`h{8(f4YN^Z}PehFoFr!PFZVMuy1)*jVuO z0Cqn{e+Fd2kAWOq@L_ELV<2M?!=Hf|#KI0>U>!chz=ki-1K5Z|ZV)4wF_;nJu`T=? z>hZx2V+`^5V23jzJiej)i#?D#jDfY`j7SDzo?;*dYa=}OSVtWEun~hbC#bzy~{;F_r-z>`{z(27Iui7|$}`gN+*F81TVHUDSdPHfm-_ zY5l+>I0Wx_H+WwL2F{P?04LxHJc0`=1N)%{>f$UopIvS+slqSYCF!6&S-xm`g76

lO41vD&;L2lu@-3^wwR4{g#k zP17=HlQzFtgFe9r8(Iflf)6%wpiS_>1~JHm4>riM%kz!uY#-#=zA!aeo^E`?Y{wc4 zyz1i0LljH3i>&=s1|Le`7-XA2rKNfm(hkot*(bwyLz1h+Gn0wp*-0S?7 z)E3lQ6fKDs)LIU0l_3@TppCVeKx=BPjy$xw*790=qt&%f1op%|_C-s=51-cF@S`Pr Sw{!0{#u;#rU&J7mYyJoPfW;XA literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/GD5.BGF b/CONTENT/BT/VIDEO/GEO/GD5.BGF new file mode 100644 index 0000000000000000000000000000000000000000..a6603d4ad5299470aa9aad8ffff7447064f20b07 GIT binary patch literal 1778 zcmd6nKWG#|6vp4|-dz%ndd3+47E@T*h?1aU@b+d_i3W0Dl|qoiSP4ncb3?GxCPW); zFE&?N*@&GH?4s{--2@H~v~l5Mhu^$;GjHEFdwF*LR62WoGN$oJ zM^Q1>@zFxPprg^_BU-6DG~J-`c00dF)G|bcS3f?q%w0M$Hudri@iWEmcAh6h+A`yJ z?=j{{>6}(%&2}`Shy6s$rsiFAMo*}P?AFR+Hob6rIkSzGds%%cTO^Jjo-xm(b@NG; z+jA~oJD=P9^&+l5I{7o1Zys^`f^FRYp7fZuA@gfJleHVorpt#judWrV&yIafJkvI0 zz8+uOmm5PaPHIHlPDX^f!6qA}s>Fp%_65Vfh?9LoM)bhdhCLp?|CZob=-F(OedFJy8lW&T(_@>C`nYJO5d^j`Kq7KOyGN}U$XGWaV5waS+ zEx;6t6|rKL1D$b^-=z-2c!&iTfnhwt+QkCHcsC2VMp=7U$hnt=7|iWsVXn;D&qB-? z3o)2Gz{1=(>mUm;6D-7F?hp%eU>GCDnycR1Ez4IRP0fWt-agFUeyaL;Onky=2|nRh z*C!zpkNu4oeZRc7rT@avn?Lo{$L;iv^cv?wuW@GSbw7qXia6X`xdULRSJ>wHwX-2Z zK4E>uF$)z3=2TlhFDd7#;+?s4pYvQmw1{&NeYEocGS Ngcg8dj23YFegnJ&zApd( literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/GNR_LP.BGF b/CONTENT/BT/VIDEO/GEO/GNR_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..c04838c1469c7e811860b983a43a381cb10a095f GIT binary patch literal 218 zcmZ?q4AXV;j51p33K>+IeP#D_Ze0Nul5v)?SMomuW-}lG2ZjnW1x5xZ27LnsA;zSVvdom~>TMx2PL%Yll<{S{8m4N{OhLSVG literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/GREEBEAM.BGF b/CONTENT/BT/VIDEO/GEO/GREEBEAM.BGF new file mode 100644 index 0000000000000000000000000000000000000000..a53564b3e30a694216157c42bb4d7cee3be2deb5 GIT binary patch literal 2301 zcmds%!An$86vpp+Gp0^u);MJg;RO+aRMudG<+~3NMVM%nS`n5oGX|L^1DQ}tt7_k3 zW+4$GZQHeJP?Fk=L2YWCh;2%Oa3N%!@6NsNy*u~OAJD*I&U=3R&UfxN-rj-16Fmc0 z&%{`Z?bvpG%!wr%N8*m%+}7w=)+FniV$IC|%&b^!ruQy8%Ggr5BePg$Y!zFUT_cW~rE7Az9FJew zP?|SUelV-#`>9Bc&cUpHpOXR1wYr9x7?ICAK`~I zItTj1mo0ZB*gcYSA>bejgHtLV=I=i%j>on^H1J| zvM@ETCN^p`<}Bn@ou#rcIllr;fWT8Jubx0O^Fu^vi zlKfOQd&js+81rx=Ax2y!?!x2)UMd#p2pNCz-Qmx7X6bra!n62qgTgn~v}aO{34k`5>>Pn5D8XIfDTwGB0qDSCu33 ziu8Qn_pCBC{UERE?kWq@&+ykyK3d&NW@>VfmtEaUW?^zt0q382f%89HC3MC81=jh{ AZU6uP literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HARASS.BGF b/CONTENT/BT/VIDEO/GEO/HARASS.BGF new file mode 100644 index 0000000000000000000000000000000000000000..114b0e535ddee6bae7c459165df4a0170e9a205b GIT binary patch literal 268 zcmZ?q4AXV;j510FcWKm$^vEo!E(heZDnN6qz0}^mxSY@Wb$l%1V*g!#uF)6V)waltG zBQYhvJU+K1hXEw##?aotkf69B$sS}t?$ICzm+l-eyTOCo0Vuv7B)Uxmx%^(ihllfU_b&64wB4f3XBYn42fa%bQHQH(&$1jLRGYngzSfGk+@;hD3O!#pMf1#zG)WvLlfK%AMJlWLe=ln1kk z!_A?Fsl(v`qXvKX-WOTf_8^ZGJ+QUc&-!i)@|;d;rM=(9pZoV;)Ut2(<+c0HcHb7{ zNss+Y?dLu&vUQ*E$WBytroG7`0f*aNt@dfzcWp~zAJ_$X%G!Verf^NO{kF9%4y)&{ zx2~vawSUWNXDj?k(OzXPr$c+_H!Dz}y_!17zO3-QgNi`7{oFY#?M^;bcDPzG(H<0# zMpK;a7pbg4v18k{UVD%o$ZnCH-fjv{X6}?jlG`KaZTU$aZWr zd=It**)4sinH@lGK@PuyEm{ts@I!XXn!7(R-15v`-vQ(n8ff$rFIf0l9h`E6nl(Kk% z7?ij`KnRHWff%F~q(=;h#eo>42Bg-P!H|s)NQ2A;sR5}K0AfKP2H7JF#3Dc}3dA6@ IKxP2N0l57x_y7O^ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HC1_LP.BGF b/CONTENT/BT/VIDEO/GEO/HC1_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..bff68a45296e394936055d3bea9d022fcd63591a GIT binary patch literal 252 zcmZ?q4AXV;j51rfM|@ zJGUN(LI#zrdl&bIHBGg*tK6`E;g65@H#vA5m}XsaU_b&6471D>7#W-x{0$U@7?VoU zDy(ucOHzwcQ{r<=au`5z9t_5w385jVA7Dr70 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HC2D_FR.BGF b/CONTENT/BT/VIDEO/GEO/HC2D_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..c049f3efab5dcb586e2423cbf71093c5df4bc4e0 GIT binary patch literal 1144 zcmZvbK}Zx~6vw}rS#vc_%ds^xcS;Syg4Ki2mh*kPE-PXkLJ;bpxw4bxYATC}5Ny#x z_q^mOa}Nelr#kA;sbV+0#9r!PK?ru(i^qlDUwX?ZE&P~oe|+!#--DUh(CC%u(4AgG zn7XCwe#0`_s_yzM-85?~O`8+p1<|N#i~WWC4Y_x#MGeQkMCV0kc5lZOLS%~TCAYY~ zs|xwN+*yuA$W?wyHT(K3O+>^*-10-`O3px3jD)NvEs=JX!Vi+^L~3GkdVD6G61W-{ zeHqb7S(~dbK7FL8?KyAaKRj9uiaI1)UrcuFgq=| z--rExd~!;0*YvH)|e;MeH@HxJm*RfdcX;vXA%_e&)bfkd$8kKyu0zt$aw!_^vF4+Gl@G(9Gei|}jHo8? zE!GgV#Bl;&Qay2kXdoJilf)^ai7<&~;xrK;T8J}5D{+=+BhC@+M3AtE^TY+B#V~6MKEFE;W zC^!}}s02@&d7y;-q5Z;Zj}8FY4#kT~9gaBpIf9hJfCIxBGX+KlCx&#sykemmDvnPW?(NF#ZAOouR=k5n-1{n_Gf4dwF*ML;V+)*#s-?8zX&qH)m@=3tN=P7L}et}04RLDTU~{-R}wY!uvEtPBhQ DjIvdL literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HILLA.BGF b/CONTENT/BT/VIDEO/GEO/HILLA.BGF new file mode 100644 index 0000000000000000000000000000000000000000..a2f255d227d761526e3b5f104902f791fe7b38d3 GIT binary patch literal 3374 zcmbtWX;2hL6yDigxm=LT3qe-VD54mIh%qs5dPEdaLs^RP4y(pe!4)N#7(hURik4S6 zL`k%il&Fye@Tgcsm{mMtJmZCyiIsx#h*3PM5~I=dH}0hP(Lbn4SAE;x`}+0to9TY9 zHzqD|fD$)lkjdb0v>J_WCabBVlw`IVy(8VNlC;P$bg{wPFfjZ`LGUBl;Jdl5^5_^P z)zHhYT6P$COKEu5abO}T1;MFoY)qsAO>eS%+A`QG8JK*>CD!T&d1a#aa7Au(dD9vo z+0qu-lam$?T{LfDni4l_&WMzGX){yOk_~*0Tdcg_WtIGmDLP>Ld&!@8u(eaG)&5~Q zl(oBrvVt}c9)`8E47s#Aw2F>wv#8Lz&y8@@R@-T|TuG zXlr;KF{!skSJE+MH4WQZ!&-KEvdgy*lkG|gy|X8a>i&7{_cXJNN%Jd7DV|JY4n=8m z2QKW*N&>&7q05p9-yHAOE-FrDm#Qc|`ZL-zZKxIt_Th`;YpLaWZ;Fg8*0f%etcv7U zNIlmMqzfA}*;K{C&X%rbg?<}peew*lOGfQ^_MB%->9K=y8yJP|>#S+ZpZ~;C_U)qP zu(9-h_wDsqcj}`sC4R|L>b5nMG9G^?LtEw=t=!4Yr$c{)kjK@X!{R40FakTSJDE(qg(=>CRXvMPBMw@Sj@bBWI&NH~Pzy)Q$^ZR~p+QyPoexePb6> z%-(?tR6Hb~$e9bo1<*<#~#}-l1 zoaL{-OL4g4iIhZzEBDcs(ueiUN$uH#j6G_X>5HjsS25XJBz5qa@hp6URc`W5C0kww zxz3y*cPX06njhE5?@=CwhNRO;*Ul_v-Z(bS)>m#?Q9z?(GAQ(Pn5LN%y~yR-8j4V| zY1Z=T+T8eix%H*9^C-vsIla8JrygsZ-29~O$D`@wb0U{q&zAmxoKMWGtSxECrozT- z8Yvr0*bj-r2*Mi#*l1=B*zGu6I9#0oM|A+;106jYxI2dj2j&5~)}C_yoUyW zV-A4%&^mBC}OqYFn@C%`cez&P{(j&2-* zPL3Y)0DU}&^X?qMPQV|Um7@m-#=v`W=(au{!nIx;y`2DuA7JHxj{SIpqmL8dm?<>(=C%O|wwO@2ci0&8B zeI=^jqS`OIOGGtJR0~D5RaApTwOaK5K~zUYcf|FrBOH924eLG*svnXcNP{P@X!AWJ zs==bWU0hqUC9I1dopd2RnH@69vsLui<6^=4}e_5xF?4f2WlO- zUMIozItq?D3O{hH2^%#OIj+}1)JG_&|rf@WAbx}=Qi>>G?(SI&cZi{kERF6g)D)^WE?^xpq>)Q*CqYWE9 twhp}YvBp-z#`f!54~}D`A7!KpxUT8PT|WvK18^)b27j!h>)`O^_!mWp1*iZ3 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HILLB.BGF b/CONTENT/BT/VIDEO/GEO/HILLB.BGF new file mode 100644 index 0000000000000000000000000000000000000000..9bb9a1518823adef08cb236c09b046807175ba26 GIT binary patch literal 3102 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 z zllIUbNO%7`b~7!NeQ?cJ^}7zf6-c#I z2XcUz5gRz{$>TGVUewxqMQc27L}pn^)%MdXVziY~wPs~?2R#?pz}`4?o;g0pjkB}q z(*6I6-5oLV&9oWp#Exba=BLrQwC3jTXui3QnclBsr{yrKBhTvwJtet~qgC6-$vjkH zx!*r5j+kqWp;Q~Zf@(&OS^(RJd3pVIA^mb*hFM_+CxJ?(us^10v&4;ehc6}ant>-_vT z)#Q;rg<=Z+&EpV+&H)ou7@uk7WL^>doA+*ScMjETSVaj!J!mvsw7oOR7i&Cjl%BFi z8DNi+z>Gag9s}h89Bg5SfxS|?;0G3E2#m7Fi~)NLa6>R)%cSW&B^F@jy_1)ixxW${ z!AtC~n(rPNWpMO-YV}QFP{-?(awU_#DUY%qY_Dfu{Ot&HOmoZ6)9Cb=Q=;TM)CQi6 z{4mbfmuG7AQu^4(KMtRDz(iz`#SwGe6hnh|uA?6(?2_>57m>Bn>WHcS-!I~!yLzhZ zG|1YhQnu-Cl`5WjhFK)sd4ZJA$?iQNA35?2YH_2Q%S-z8)wZma{(i2E$Id50+ zy&&$(qGSE$=is>m{qihsY3nzKn|80|Wtfj}G+eY?lrmDv3?-qI8gw|vzziFd9A*WN Sa)J%8C^_iSxp3ZF#{UPlW@P37 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HN1D_FR.BGF b/CONTENT/BT/VIDEO/GEO/HN1D_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d3ee556457a5611735e62351338520457aad9330 GIT binary patch literal 2716 zcmb`JdrVwK6vk&?us~ZVuXYQq7YZ$CHQ*+Fpk-#43bbVnwb3+$6e%u+iaa;9L}Njz zss0Cx)VQ#+WLAe zP_a?oaOWHP(&z3+1S>B;DxaLatTMl^A7)2kX1#EF!UmGkbOq& zBR9Ye0uv|%6biys76u9jMSyUPtOTtBMS`M0t3lDA7?7RZ&XD5OWl~mCT~_aOImLQ3 z=aNgUWDplS&NLW2&rhsoH_Kjx?@@ep5F*J1txjsX@+yp2VYn%fT_2bRrg)K|S1`zh z7ef}_8L<;Lk%9;ttXoM16LpbcU5rzhBqPJR4w8A-%wR6E~ zo5%I!oTno0+}E!xVPm0ohO8pFn2zRUGK|v~cF>8%voyIYiFN#Wg?m3+SWj&SSZm1I zcrVCG>*jggz>AA}FAW*s_h8SMPxP#f8_hWh-lh2_uNKk>_eGDW@zAm6`Pf^3U*_y|Loc2AtBo@;r^s-;=oJjT$Q-2kuKoXC zPQzGeC=L`4S_4`OvVhisQbC(Qn?Y%ybkO~v2S8gu4zkmPP2kyrmkEUDO#&zpv>vnp zbRS3pC4rJb8$l@`J6i#7?0-9RlsB{XoGsp)A9%h|Hb}$&kRW>|!UFRb{F5?%;0zNC z=MT?gWXc)}p5^`RBTMq(`HoES25VU6o($v*p83d>e8Drn^S3FLiT;p@UXa1XX1_Y3 z_AH+7s;Dn`FWNJIS9h|?6ssg7)AolwkEVXFG9{nFu)knF;?dSn@&$VdzLO;Rz2tV@ RbI_|WW&QpCZ)R9O{{VObT%7;_ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HN1_FR.BGF b/CONTENT/BT/VIDEO/GEO/HN1_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d290b3964c3d499d82c11637b4aab8b5006c121c GIT binary patch literal 2004 zcmaKsTSydP6vw~a^|Gbadg)^LFp-3Uk+so9aQ2%utjGns5EMe$va6M?x`{jb0KPkKNw5iIxV%3q11sYcMGG*C-{fW8KlSwI?Fo$J$%MCy$)! zZWmB(5L4LY0-s34nyR;YIL~_N3r)tlipQ_(qqEQ_T_M_pZ`o3+(Vnc%iIy1HfV_WtC z#y&U}Fgq4AX0Z8UzP#sZz>L|<1A2PifebVAU}olP=LTCaXMC_lZp@G`^uR)5P0nHh z1tjRml8oSeDakUDkf_R~ht(_(z2}es=8@!+U_KU+1m$LTjZ$WHt|!uVJlr1fx5i^e z?=~**jV6ftIzxTE?g&FIy zZMmXk*&=2z!Q}EKVP6%Z%%ST7hw`oO)bS=XuWD;FoQYM@VRB`Mf=!J3l-( zKGH8DDJCf)35ha{%e-?Glr1zjE3CN*cf`W+NO#0>;ibD@zMu>L&1fz**Q!2Ejla?B zoZAenZrgyx$e(mFE~stmGn$L@QkA>pb>loAEdg^of|=);dO|3q=grb%#(K7`H_O)a zVcKHrnz1O!>HMw6d0?=`d0;rt))NUZcfm>c^ef!xU} zbUEyN!G1g#CuY|aw#FgCGFIvH%iU>g!e|CEGw>R)skL?r+K literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HN1_LP.BGF b/CONTENT/BT/VIDEO/GEO/HN1_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ca0bc0e513270c1789bebc3640a1abb25e050cf0 GIT binary patch literal 220 zcmZ?q4AXV;j51*7bQAY8rAj*pCq^B-cJ!`8MA$ipeu=O97?6MiLzS5VBZCuzp@D)3V^T?4 zg;i2fW=U!e5Xa}19_Js5;N83aH^fQ*9~;lyBXpdbX%15#d;nu4T5*^@y5cLn0;%S%RGymG&|JSdcDih+B}wxTr8?*`|(VF*?t=ulMzpWic_nLtBC)F2rW^-l#!dShysq|?=qtU40i>wJiLr&3sX z`EQ;`$2n^)Ng-t3L*O!-+hp%lp~X8j#Na1Ny%>8m{6R@aEaXUz6pDE0TDi?iDl?=Q z-NA;^I=iDZ>tNNhCC@cf5eN*;A$wZMHt$sac(3#91bk-id+ByI8Z~TO!?H0B?>}iF z6hCvxGW^hi^dJlKhCyj8J9O=5o0X;LGo)2eyQaFTv@Xk0U0H9hu5%pX9c1414)2Z4 z>sr~Hx?{hFSbCi%sN5*8yY(G?`AgTsf|ZvamXFU~P?>kC59Ul^X`ACH#vv2lrR?e( zXDG6LV?j{E$>UDed+2mjtdA*mk!kBgywWF-g-eA|P)AOxl0Ji|nG#K1R#$(v^vKQfdG+!NrNOFFwof@US#MM407SckcD?fY{#voAi@S}ms7z+U1V4n;}j;z$gpk!$-HA`Fqd|A@VA&H z+%#6!8I&QJ)S(}?S5%f&+0BRQ9KJnr_j}4N$q#B}E$|RLo{!GP)6*>$IidLv8a-iy zF?;xY%~ouc^Jc%NK?@sHmTO3m+qb=^vX=e=`pTsh^47T5X~XWv)Ht*GsC+DyG2zV& zCG3RvfIM8Cz-~o#^SB<{87ksVfBR|x8x65CWEIK9bR;*EVVu6OgN`qrqRCxJtmChX z-225sBE4SG5l|PsqAt!gdS?uSoN2w8FKlAy9jb}2%>5b1Yj_rm>BmP0ITK!Fm=EIw z6JyhQkqPflr9aS0QYg=T7|u!#baLCE44oQXL_hT}!A zVCY3wK$`E^|NrGQTnP=uf#N}{K&wF}&>B!GXd`G7C=HYjx(9SGXfvpQY&T*Pc(&kW z1mSs;09p%51g!(D2T7nLP%>x(CpGWP;)R;dzWqSwsG_ysv#YARnIZ$P}-?hH36`Uq1htk4(wuKl3|(pH!LX z51Hr%8C-1kn`hLX#q*7f{)+daJ@a>TC#y`cN-{ESf7tU#>W?Z@@+l1a^XDUOZ4D)# bzZd^INs>QEZs$Gwy$Vy--~az+hV}Cgo|#}U literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HOTBOX.BGF b/CONTENT/BT/VIDEO/GEO/HOTBOX.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d7b5c21148b8b76460569e62fe0bb5206df54321 GIT binary patch literal 284 zcmZ?q4AXV;j51j7cSF6;>IgDd|P2sd@3aB{>X0 zNhWgz9))nvAXm2_M_*S31~-QGCWZn`0~_oi1~=G)EJd{pLk{dHn0gouH503xFM}Wp RNF5^(GXXI(5VJBc005{KO`HG# literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HUMMS.BGF b/CONTENT/BT/VIDEO/GEO/HUMMS.BGF new file mode 100644 index 0000000000000000000000000000000000000000..75f63f135fb9c14d679421c8188ea88dce8a9bac GIT binary patch literal 204 zcmZ?q4AXV;j510FcWKm$^vEo!Y20ssI2 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HUTD.BGF b/CONTENT/BT/VIDEO/GEO/HUTD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..7118eeb23b172651cb3c1eefd3c97cecdc64f9a0 GIT binary patch literal 4893 zcmb`L3se==8pr1x9->wr4NQ{92~#m6F-R0Wv-ds_hC$adwMZf4AuW-o_zDGs1W_bY zGZBqUutLd90STBnzEABFHxGXb4^G9iQzfne=;Ab=#SzuuBi@{T#jtKcn;3T8K=m+*e zMh7(BVvRMM=^A@)<3qX`bCMF{BUAhn5?@P=NlZzY88LfKyfE@#UV-QiLG&g2Tir7x#16GlmcUDrg3$@12ivyTF^XMXep?MW)TW;D_oP9Dln`qhoPtVb3q}$}q7jf+U_p^w3 z$Zm3XXA5UlZt={uU(4iT$=yrxi!YMcXB8YWhs_v(tXE^}-g&QA>JQ-(U%)GswkP4w7|mIrI6e zu?t|k=58RP>oyT%)DVVtvDZeiV|_j#N$b~l^u^ zDC68ar>>JS4XebW(hMB;JqI#vj(J`V7QRmRWKwHR1i4h~L4K?( z5V4jCudkNAbl*pQyPGMV5Ki$qSXfd{qvvLl%grW|v-KO!d^dkcZ@s;UA;BsaC2|@s~q;4Qrt2dFh z!)|;{ZtN?vX$70e>7yG6`sPM`BWit}Q-6@otnMMYZH+TM7gQ^5JY6mx3$$a%UQ6_1 zClU+DjP_LobF>}aCu(zKjX1;W`#NY4jW91FVb%6zrTs37^HN{Em~C$Qg|xfxC9PS? z9*k~Wz>EiHlm_wUaWubz_7SC86NDs0B;i20T z)C<%bbYI8k{qXrf$N%`*2V?;C1@!|x2yz5Df%=0U0uAW+A3vQz4}%7RTtKcMH;_BX z2zmtM0U8SO1Puc{1{wkK28{$g3GxGt28{vvgF=M`_EH)$(BM9RU0zpd> z27`uxFh1rP4tgBq1$qL6IWU(G$QSe!XcTBHXdK7{f`uRu5Ct*XpocbvEozJPyxB}^ z^nbifW$JUO1Kb6JrD<$AWHHFEn5U5P>L=j)fKKLIAJV}D%fk9JsKOwh8U0!Zv&t$n z?n>!kYCKPd@vc^{gz8m0Plk31Q{#CujHfU)uP4L23RB|6#-0~3UeUfdop^_hA-#y=GT3_0?fkcKe(EE1__&%37JJcAJTq~y=mck zXL--Z+e{D4S}bL>tTz3$KAP0LJV^XNR|VrXP#>RmNqhbIYqQC|pkUD}pqeIcn+a=U zDNAmR6mRxkAbnLp@%#YlJl*h=!;=C} zIy1fdC${Q7*s9)oZF)7Oc1Y?lCR-}#kXCm-%(OAe(EfJp5PdT}otJLDJdc-qCG0wE z-v!+6h^*MDtZ;o6L*_ELo)kZPO&->e4bz&%N*5<|VK|k@aQc2&aX}^r=kV!&%xxZ@ z@_Q_YA^Y-N12HUIDsR8J0_<|wT5F()EG&Ap>=FMC&v9hZ5E1jn_uM1fPO0GWN=6o% z@D^6IACR9tB=MSEtYb`=cU0L*`I)mt+;_#BBf0Nte~X-KI>_xFt&HV%v9Yo8ltry{ zL_)i?cXNv9GAJ0f_X2s)gsYszoPC9}rpEnp-VTYgqLx4t+6h9HZ0%pcS=+$(I8)>K z_uO13@Odwhxyv8_n07La~8I#o~Q?7Q=^NF2cvC) zd*@-!Ms?a-(cyL&YwL%UER^8eOs)Fy+^gZN#2CSxo+xhOzWk!7T zOyA%AMc?%b{G#t@E_jb3UtCG=?u=m(C!^{bt@DU}Ppip$`A1^<=a0aBmEqLDw+@1E zBSe(ecn>EB4lf#ar_hI9xLwKD!h?~C+}~icw(jffRN`zr&i(1cqwuI_mGL_IH#LSx z(8M67AfP{9@77$@#)3`8Owa1Pjr}`cS41TyM5V;ciQ#W6ly?%cE|oB zyKL!XUvg*o2ntWF7A>nP^MmW^+Z367*Sy4p41JY1EDG!HJMJq_Vrsr-(&j++TjFpy zh1I;p@^OzuitJuqg`uyOE!3sZuC*8~4`k#u z*SGR{xfjo9ad8+()$yutnUJaVsqxSkS*Y;*e_Y@ARDd^6Jz~2b)!mO-ID-EH3q-pp literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HUT_FR.BGF b/CONTENT/BT/VIDEO/GEO/HUT_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..7799d7065cfc00bf879d502c2c5b1b3a0caa8c73 GIT binary patch literal 1020 zcmZ{jPiPZC6vp4~wwm~-rWo{6a1On-)zs7~!6vh-q!g?uf{KUQB&LCyHZepIPZbnx z!HcAa_UuJOC?0GPO}Cyrw58&~i-(;21A<;Wh}inROm-d61RnG9e*3*Q^D%RB=zNbe zbm_1~VN;l9z!FwR>u8HG!{MMXj3UKK6r#1&mxGmYNmP^T6C2Jo>Ld~?N4_l$V2wr( z*fR^C7`rxUKPl&|eqoSJsiX)1Jo^68ap+t`>^0Kmv752+Y&o4zWv*VHDCY^ECaHgl zI@eZDRp;m4yyi8o1gDaArQRf?taS8{!Y z(qyhaskbTNJp_~TqB$+m)s-^~i;}z3*AK@NU*2{nkZ;aMW$(M^oGZTdENkn$HvKrR zc*yQ+zYzz2@oF@2touhCdhm|GPu44rn$FQ*@gmQMtwaw;D)C>|b$|X;*ImvPM}M88 ze}lW4zN+iTPA8zR^M>B%&^LH}{{Q;BvnKDW`Ti7lxxeqt+jKk#8X+k)BN6|*=;p|w%tg|=~Q z=fLd_a_r#P$$=Ue?&xlgHjX_U4&950eg3t~6ecsJY&q-Q|3H#*_vs8Cl=ryW?mUp2 lU56xT4-U1ZCr8;C?-9Co?fvZm)c$H!4ccL9|K}upia&r)KyUy6 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HUT_LP.BGF b/CONTENT/BT/VIDEO/GEO/HUT_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..20b627714f3dd7ff9d6ef23c53cf69843affbbc9 GIT binary patch literal 200 zcmZ?q4AXV;j51%!jFm@mU!d01O*7ga7~l literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HWZD_FR.BGF b/CONTENT/BT/VIDEO/GEO/HWZD_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ebe2f0f8fce34e7ff8d6e4483e9c7d3edc1a005f GIT binary patch literal 3383 zcmaJ@4Nz3q6@I(?2m)0B5q}almA@n_f;eJ;z2~t+V2P`Nssn@u1!4JztQZ662-q=; ziB>S7g=vUN$dJ^=L=!6z_pOdWiD~>-DC%Si!4OkJ0yIWSr{}zI>0496%s21uch9-s zcOUnhcb_(_U#vHzE_D#R)f%#!2p$*n15WPQ2r;1SKXIuR6?|{F;?S3>{~j}PFMq`-jyRr6+&76UfO97fmxGtvCLoS$ z5cmD`O~5rMckpJsj&nShIAt#BhWb~_UbqJ5lwOEqDIe%KN4lJ&eJFFuOX6xzk?(`z zNS8Ps_y6`rar9pJez^vJSIYhJciQkovJ@|Ehtak}@Yp~Y6 zP@MB{IC+*e$a5%a)b5b?W~WQJ`U{_5B&$N6nCt`%m!EL;Kr%#u;6Y6qd4oEc~X!e z1{$he?KIA$)x&GI4l|{f2fuv{_N_KDrN&t59x$5bFy(r?7n>k=w@o*^@Uo8faq;O& zX;txaa3FkC_oqWU+2d(Pphde`DtRvt{!r@23O~7RrFSseHjh33-70uxSsA{U|K%D+ zlHmDKM>u%DmObTj-y=?FIjbtj6UIS<6I5Hk?eOlKiH5nc#y z#B78QVh+L=F&8lpF(0u2@d)Bk#6pAy@fhOQh(!oLg#W}i0H1*q9F2nzk56zk4nc%Y za7JOa(-Syef>??OLo7oWg}KheKZ(#H79)ZY6sH$&seiGny2gqf>Kaj0Q^oR1oNkJg zGOv6Zb)%qhl)1zp9W_dj;KidPj#g)>j$SkQ~QB%jYuluYqMHLWq{VdcUb%%SY z4`3{!M0%&UO}A!RIdsRxS{k}PN^OhU6a5vnGz3kH? zza4+)Lc8^iz5C(E?#1lEKiA0mRRN#VJanCJj6i+%)Q(5_&zyb z^fHLat^P2->7q@a+N?u=fc~thOX?tFxQ0!&zlAsU!i#%$P3bSXJsCU=$q;8AggHG; zU>we~TmN`oI?Vfb3QVOxUVRJVGXAKWD&JkbAF9gYu^&g%DVRJS%6?2ogpSKpeVKYT zCF_M(LNxR2FNjMwne!F@Z%Pdke2QCHaKC4W4-c?9L-clna?a!S6 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/HWZ_FR.BGF b/CONTENT/BT/VIDEO/GEO/HWZ_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..1b7e22b25cadecf078b63dffded844921c0b6c16 GIT binary patch literal 2938 zcmZ`*dr*{B9Q}5AizY7-U-+3QYCd2=K$7oXRwc18*9W6m3L>n^vvpIz8Z{f)%u)Np z6jCEg)A2!Nlo0N2rf!xER*vJC&N%r_8xbb6X`1PGu6uEJMP|<2%b9zA=iK|<$4<`9 z9b?SSGx#Y{dR4Cv_EY@^2ITvz`lzT7Ri~>|(k)7uLVt17X7M$j71*uGZN}G>xJy}$ z&X$WCw0Y}KIH}L8cKpCiC0}t2m4BS~4NXyXN~Thfr3Qmtm3+u(RAwcpk-A0J;;Qsz zMb<^71%)LG%dDjehGr=#Ym~U3&b(x=ulxQuwVFrYj{m`<)C)>aG&+KwkjW49AQKpT z(tcx-kp~4OsC~(0MbVOU!qURhqC~T$Tsj43@#}#$UKLO`YOZ6d<4yKg^KLfe#x?fg z?X6n;@qNy3;(IepDB5;P%epgFaG0>V2`Z!ts87B%hIeEJJd`0@t#T*-Mz@+M{hua{Ag^LJLl6!QC~bG33Lz z#9?mf&R|HSi+&GQ{$)>duXgg-TG z>>ocG&y&Mb94!}GwY!Ee1}><53-8=C%USTBi|q^xWLp~2?CZvDa@mdAdY?=)R>vABCDH1gGaeW{-2TW`R)%i8+9Bz``3 zqGNF9Dt0)0Bm;M4M+lEPyiITorEVH=IdMYQahEp6UL)#3452pxFHSfi zf)GiFBJ?3d6Z#Tj2>sms{?ra|a|5XzM2IB}Ca8oVgl7pu32_9~-5*BnZ~{2=;|UlG z4t;1w5JnP45uPKACX6ABC5&_T6R1sebLblgNp22(XfPIBGGRO+g^)_fAmDW3baO(E zV#1Piy=s2c_a}r9dJsYhc=mb`(g+g>>4fJA6A76FBViI@GGU7N|J?+&zxPXMSZpaV zTdE&FhKkvy%(!bhDn4E6JKs8@llHQRWy7_bgBl(9oZuSv1$%KA4{qSXm2@pW(xQbH zT#gcs@Lsbq^8LC5HQF6#xz)0?vZ%sRZhjnv+jKV0btn|G^_&LdtU5DSM+9}5fV*O@ z)j-069X`0SH0UfRMDCH$e&$mE2fjlR&S z-6?;CgF_Z@#f68oj(a9API`E1WfsYKW|s9l=jO?IddS6>S&%_;GBY^2R&s7RO6C)b z4+8tk^T>6#wd650@?82@QSOgbUa@p}k=L%_sXCj|e!0otUSM$XjM2xPRbT$hYRf(l zuT_ofJC2`+dm4UawY#?quI!|Z8`~B*AB1jVerIMdXyuD@dhkZJs~{Jg=35V(?>KBN z{OnYJaX6{Vlq*hp)gEWrT-l-R9osB8sRcLFX%<=P>o)VY;yFV5aC?d1WWB##ZOo9i f%WK?@qz&xagZZ?rpT4qs3Zf%CZH2M=?yvAaZqEUE literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/JAX1.BGF b/CONTENT/BT/VIDEO/GEO/JAX1.BGF new file mode 100644 index 0000000000000000000000000000000000000000..8288e934a0801f6953ea5e99837e7ee2102b5d84 GIT binary patch literal 2554 zcmcIlXHZmE7=7EMNEA^K73C>q1vFv_BC_|pu7IwJ6-#Usmm;nUA_$7(AVkFydo&V> zBv$GqYLtn_har|&C+b*Yi3L&2=%^`1Bbx7Ca#z;;&YL;2Z_a%8o^$Uz-?!nW@jZ;D zNxd~v8?~%fJ8EQ&N)xM<)smBwtWu>(q3M#VgpbSmd%%7lYs2Vl$tPm)9p&_6lVP$^ zU5)QBdS*Pucgjk{L+K``U|A*glU?P3;o+ue)A)#(;UmMx%F;kOS{*4nvdaAG5TlVA z)j@I_ReVNTswFNxbWU=dIW;S0R)$5w4IKN)9`fLbkx>!RV@#7Gx-%ep%c||U4Zm|PO3v-F!&L!%of7lY})?Gz9 zO)?W!7w_spFO}y&>g9YQ_VcTCpqn&{p@(k`(HGbAy3)L5%9U>^%$m>_ZhRBYH5m8u z35CRK^)?NrYYyE&n6B85`5SfjbHe-?V-pTC-OJmg>cT;Dq2sU++kWGMPAb)Br$XIB z4G3Mw^3%%0ebXTL!62xfyoR5*Fl!5F%QMNf1~(Y^^c3gr|80W!p5>(GSwE=Uf0A?a zgJ&vzcJ+g{o+;2jB8hWhBfeHjQpP~cfoRlNt1vG=-rK4Se=`&YygEZ1Voq>ws7s!b zqZnYw_4PLHbwU;ds5X;ir*wn0Z!WJ}(Xa!ydLLO3H>Eh}h_h?06WWAAL83*tRQ3q(rXZ(Mlg+mRPTVHVu9NJ zByo_D&csl8ybV=G`i!)MIrA)UgB3}KV0vz;Sc2W!w4<%#@?mbndAP823}xK?m0@)5 zttsSa-BQS0wT$YHE`_UxII8R01v>9?rp`s5a4xQ90Ck9|g5usmv|)P+TdS=1@Bv(V zc&+{htp3;njQhP|3!sK_%XJ-eo&6keKc$T50oN+`^lc4igO77=_|D}9)KJv9UU1pN zg>ynRoZ1!Ed{c@g{!JtwfyShKmCX?cwe%!OT=P$0Lkjw7;yo&JmRY*C^?_jZOkS8M+ zlC7my&WUE7_GKk}ILczz)Y~Rj!joToI42rzo@N2@3)R~-VV~Ps_1rilUgTFmFC+J28z!-5 zDxh%BOgk@^c4v{>E>=6wx@*}a>A*$<8!%!JMg3I)C%miv_0p*EDzySit{>u_g_oC` zGRWFR`|z*r$p1b}Jn&xHBRU{DB0LeD5S_N>7IX literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/JAX1D_FR.BGF b/CONTENT/BT/VIDEO/GEO/JAX1D_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..e493aa4503dcdee0bedf9c895d666b99ca8fa1e6 GIT binary patch literal 2511 zcmai#c~DbV6vkh|j(`XWNM#AiB6|Rf8q7UU0@8@o5sM40?2AGaOevMtjY%7AsY<{WtHlkq>Zl{&pjL5hT?VI?p8F(Bp8dnj{N~+!@1A?ky?4Iz!j*IU z!jy4A28>835eiKWBnFN~iG~uPNMt4v2yz&inz0^T*+&KyG4P{!3;6?n4_nH(k^Ift zD#eJSzeNpdZzmbCMR6BlR+b0L=>1q$Wfme4FjJYNX%bWVV&{`|MHn+%DzOzL=cX@{ zWv1mOtCCW(5*FvG7&>(t6SA6dJ9BzQYqjR&aeNZJaVz~#b-Gj}V?iGRM2Jjf88b{m z6YP9)M-j%ZHkL~4FiTFhDoHI%$zGD8PRmWxB{H4HCK#8nBBP9OFOr^qheWE|p`i0q z(&1P^sMh1RK}I!!)`Lis50kHMnP{oDuB91XH3L~SBa72$EY;+RMWmtKjnH$U^JJS$ z*u0+QuxmO4RHO5#cCfSe_e=%NBvC@;@UwC)kLCB zu7}AM{_x9FDeTxJBM&V}=nlaYasUQMc)bsoa=yhCb9Xqkl5bUCWe^pjMV2Sh*bCG&m~a@L9$ z`^bZZ!3yW0*b`t@8UXIgQs8jDg43#8YeCdl-1@3|GL+99!^;tyA%-6;`icI274jN# zdF~#fzqbSNw@HN8DNdu_K5@exo*s6Et@d?+&lBq}s)*)@ zU1+tYL0cKIk>tJVBBuKaA;Bvubi$|*ZSVN`Bw(=w8n3Pgi}D6}c7aHHsxg&x-SvUC z2hK2Z>p1Y3E!I}HbP+=*FSt~F8RWhq@Oe?Ey>tJr{9>>YtY&@(pR5;>m&Suy-wo5{ z=iN;qwtXHb{Rau{og2FXiLcTa<`*@=Sk*%C4BV!5=u9QfWsy)=`!$3mreS^ew3?kY z^5zQ+PqUnz0o}o`h<=V@hdfwoV#uq->Uuof?2O>;<5}A{crEq@{r&!V%@Z8IbcRS~ z^n2J+#~_YFPp6@AG}CT~!{N4TfMY5cA;yRaLOZ<~VvdX$8dHt-YfHom8HrdUqYxX! z7NHt_Cql%C9b%7+MjQ}2m&Q0FE{FtiMaClI5I4jfp|whpK!nym5t)QcMr24dlV;?B zPfuh#;)Qr4K8P>khxj7_NDvZ?OhDd8LXc2|YV;jllde4lks|~Fghj&G#X_mXe)t=t zPFAI=voh5AdLN-EVF}wK&~Ne`u@0wcY+9&PHu><*iGtW$WP?)dv ztF!B0m1hqU1I5F+j#>NT7Ok_-3dpf#+`j7bB&#v nmAbtzgCPq@KP)_%fozZfD-g2*F*^{0qL34axqz4(h=Fndd(O1i literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/JAX2.BGF b/CONTENT/BT/VIDEO/GEO/JAX2.BGF new file mode 100644 index 0000000000000000000000000000000000000000..5c39c47aafcbaad667313b9fb0ab1dae1395eca3 GIT binary patch literal 2554 zcmcIlXHZmE7=7D92~j{q#KKd`ifCMwfD-q9*A>uJv0{mh;!=cVK}5k4MW-PL3s z*Fz(Dsb#g=StDyyns}|OmRww9l`2b$$d=qCeB9RD0rvYq+lNk-0;2lgQcgZF8^@c} z)%Xs>(-SGaQ&u7#O4qrB$to#ac9;7`Mw(;Iqod*m4~-ltOMU5Zb+qivD)Xy*nM~BA zHppJ8#GI^5YeII!wA2JkW^P3&zDVjQ~ z3+PIfXTAaIV6&0TOoj7R+u(Vz4&3WoDU2(xmq$l65q=&m!p5MMc_; zvk+F7=og0YYhVr0m(=sR(gjPDi{DVl7!wLt_e63H#??Qh zkbJq`uEBII5o-z475g!N!)|{;m_Ji|(tf6UVUtu{)Ncl~8PvEv>wC-i-Ef^&DDnjx`UIjLy~hswRjIX5dT zUFo?k99p(bgWgdooa-~>Yh_2;2#DJkiyEsG=H>f48RiQ^YCm80QAMEl_4F zMi_8qjh%a*lnaAY>q)9hw$T{G``!Hkkr z2sJ{3&>~zAt_W7k3f@M#im>rx|XDC&8BaKXoo zb3$XJE|4zVYh${K@KR$@)3fc?ab4lrSFym8{AHXIXB%F!4@wt|;hu$tZ3%^9Pl;)O z@Z#<_mKueQ}Gy6X0#MyqVY=AvCC%}B|dy4vik$$`Aj55x$7*3=trT9T4 zHWf}66e*u;TJkSUXeV<9uiNF;noW=D`bX!Wt@9{Wrvy*%1KbaWg*G?l zJvhXN51Tl+A8c*b5keF#(*=87=~eKqN#b?8+|~n|Mj35a!HTQ~h>;Rl(EgLWHxnw7 z$P)Nw>fTJ87uK{ycq3XNOmv6VAbZ>6HaXKaIXfvQ$v(xRX@RzYR%>1l!f!vPffQjS zuLrBD)(Xp0%K1f$k9li)AO^17Au!%ne;6EQ<7-7Y2CWW(!aQDQ4{G-FY*^lv?`IF- z)16shw4{;OgL*zX7`7bbUKA0IA;o$q?VrXp>_J`Vk_o2!DQvC1L4J*$3Tv;GanB-b z-`xv_N5M_HA}~Z}g=^|5d_SQvrZ50Hzu;c%P3T_|1QE399O7)Q&26wTs~l$eS{)kX;gGpx zMX8N*qFE<>SqUEuvpO{Orm>Z9{dxfBM8nP0%ppM$dWR>xkSxLYg(!scebE47XCQc_Q8-iYXZW62F8RUD=HOX(Igh05D>SkJBL-2--xYAozv`uzCXHvA6>$8@0q$9N`Da}Y zSv7w*{wcY+9&PHu><*iGtW$WP?)dv ztF!B0m1hqU1I5F+j#>NT7Ok_-3dpf#+`j7bB&#v nmAbtzgCPq@KP)_%fozZfD-g2*F*^{0qL34axqz4(h=Fndd(O1i literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/JAX2_FR.BGF b/CONTENT/BT/VIDEO/GEO/JAX2_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..5714cee652225e34be99a7c986fdca09dc1abf35 GIT binary patch literal 575 zcmZ?q4AXV;j51wcY+9&PHu><*iGtW$WP?)dv ztF!B0m1hqU1I5F+j#>NT7Ok_-3dpf#+`j7bB&#v nmAbtzgCPq@KP)_%fozZfD-g2*F*^{0qL34axqz4(h=Fndd(O1i literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LDBR.BGF b/CONTENT/BT/VIDEO/GEO/LDBR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..93b7c099d0e84017d153513d1e1a4dedb36fbf04 GIT binary patch literal 1549 zcmZux4NOy47`<&Nw1WynD#C!3jey31f=Udb_q$Y5F;b(=Y$h?nfbtVS2G$A81%D9A zFbpB;WHC6|jQpv|a7Dqsi`xw994HPXifn>zbxaqQFvbM;Zo^wz*h@~nd(Zvuc`x^z zcjGr2!ZjO{q9n*itP+c55|usOTyN~X`VTn&tw+enu5LV|EX0gk zzQYqPN~-K!kH%!@`XBv-zb?CG=a$v`+PR=5H?8cW*xn%j0d;4Xg%k9)Ro3GxydL8O zJ;pIT#tC|iV|t7e^ceT4-+;RRQ6kCCN2FgD1&zV(aHHk{UKFk;tpO$6KesZdkJ~VfgD<#2Xka8HyPbutIVF%Qub^X@qqw|aB|OaP;j+;u@ZIb|`pt{u zc(6MhQ2yUs-&d7f@w;Vo@ueeJsgHoP=e58N{Qe(fP?|G>kEUDk{pBN z23rY;yF}d`L=48}U%8nF!+6I{BOLYINmops;D3NlTCj)WdkGfEGgMIF54c+0p}wH8 z0v&IrA(!_-QHc>6VrKE>X*oPQ7ELSfMnDI7%+)m7uwrRC#7_rPFWX+O=?hnyF|-@s z*_#it)^+rCMIX22Wj(z=;g8MUXJL0%6K&~La@K|<7$2&`GuiG==1-q^8)lt0h#^uipc8vt!KqgclyJ{L2lE>l!FSz#%C61y+8*y-rnZRgZC-q-?s z&iNPrmun3PnwPQF4jGGdx{e%I?AH+*HKTS*YA@H?w$$oka3xbY)zCR$fY!Dt?kU8B zyY@Et1ysWLUnUq*AEJ+KU&4w>UsC+mCK!o21l6wPbT~w7H8!UZl{Nu-QntZ?V-<8& z;(7R}Z#_}AXu+f{15-#T?K0I_N28~q=hWkAQu=@X^4|RmlJXJP literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LLASER.BGF b/CONTENT/BT/VIDEO/GEO/LLASER.BGF new file mode 100644 index 0000000000000000000000000000000000000000..2ff1c3803d8ac24005de2976b1e315e9faa841a7 GIT binary patch literal 4177 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOKDMSL.BGF b/CONTENT/BT/VIDEO/GEO/LOKDMSL.BGF new file mode 100644 index 0000000000000000000000000000000000000000..56b2b56d28739c490443774103d010469905c004 GIT binary patch literal 3116 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOKDRGUN.BGF b/CONTENT/BT/VIDEO/GEO/LOKDRGUN.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ed183b7043464c8d29fb2c072f3a8e6ffee5ef58 GIT binary patch literal 2315 zcma);e^69a6vy8#zY&)eP!as`Oi)$>K@t>s_q<(K6k)|*gOr0Sv;rXu3BgEeX6OW3 z3Z|qEC@5p*WSByt!h0yrDyV4w7%~wMC-VoEe;7`r)je-~%z}=#GvApvpL@@}_ndpq zxvP(i_18tdH_3+aP_jy;gAHq=QZBV+m2P94ScT$4CM=Ut8+X`(`s@SYS@&SFBlQxj zV0;o5x(N+eZ;G>Sdx;M_iy@~Y8Z52LfU)}V`~k-hR>6d_YF4Y)M=p$vonefQ(Jx>b zEg!CkU>$LCUVV*L$NMV+*^!F0jOAI&KS&QVC79pONXy7Hnm#sWCTFJ`%^#&PL2sHs z_i_wno!J*gEEB=BO{#_$lDPJIf~;whNqm~UG(4x{8ks^F+6Fmx2|AJ@gf+I2<^~NIm>^pW zgn~**WkZF)j>?|OfeOcv;Wy6FGM8xhFm!qKQ*=7!R3OXtMlX3;dax;Td2(iMzxcgz z$}1w6oX^a?cp+Md49F0p9+ZgduW11`cN1g{rd?u8`?wfml;_Ow^$==mk zvhwO7iCx=e5n3bixL+xoF}{l!m_aXjtmSWDMxZ+tkCUeB_@*~!#LLI!w<+>@USa#2 zi%@W7Np01;f7V%Ut%kX$O`z{FbG-X)&eA$rDCpV*@t(O*-=%^hrIkY43TLh%>3hiA z7yzjTcks2>in>clq;p#(91^b+&7*;W%-oN!mKfUpAa>P_XtV>g&CUsczt5+07cYEA zjwS9Pi~raJqg-}S&$tL)%5Yr$Dsm*D2?P>?;doXCFVS__7~?RQf6RA+d9)U8$jhk zHSmS-TSetcWneUzp|4F_EN~|(Ex+5AUM^m2Qmk69h-U|%~~^ChQfbAv5Ye7IvfPZR5TiT=B}S*Oku>wTNs zD>#qKXNZqqF%&%tC#@-gu;BhUZty>~1kVz-b%L0`Aq<}PIKlKg8tE+RxOHNOf8mLU z-^)qVT_1^kU1$`?F4$1#rz#^2r4s@Bt!(S6`;_e2{BNK2yyiIdGTC2b!TUQ1+R6-V zWtOP+6l`Og1!VJGYDo3|sbps6UtDWSy|CrmDAMdzK~``FX@+ER*yoqp2a}&a*(Z1lO||N{O$1Iq^T@57D7hq5R2Y!g%i>Yr+1~U09=to0KC7H>r?4Rh^kMU>Sr{(^PRe{BWeHxP=i$zT} zh|2B7H!^oB530dbL#Vu|hEt88LXP8Dh;k9(dbqE3QDQL~m|^y4Ka|RoY8aIl6|Se_ zeQ6u*Q%vu?uG0DrzFcY2gWBy^LL7{T#fMqjh0m0uAo=PD2q-M8151@yvUi`*K3@gO zgi)~bWN|qDM_8L$D<}%w;NA@%a4k7X$_g%vDMt?qX2odGCco9^zLe_+KuFHOK6PP^ jo6yVT8bB6z_qvojGDBNr|K~xav5_8Fyfh3dy|n)TtgjJk literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOK_HIP.BGF b/CONTENT/BT/VIDEO/GEO/LOK_HIP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d822a748c55f7a630ee7eb44bf9cc16d15fcad88 GIT binary patch literal 4166 zcmb7HeN5D49RJ-ND5N5Ypob|(;%f@ZiGml;^W$_lm0LPrgBqrFz95FwbhCU&u@oC4ON{6huati6D(>Yw^(uNUB8nz{HP$Hb({0Ege)n>PsNAj=$N^UvlgeNJbsT=dUxqT}kK>H_A9KCfSlC>617IZsWWRIo+BhNuT22 z)5Z74%hJY9lD;c$jBSN{clCIAY;vq1eTsuGTjylR@9LE=L0QDn60b@%^l7mv4*HOn zmUx3UI9ITNT){@-_H=blw+oK*!sj?Ix-9#LIB-sn1Mz~><3(P;>3Jc2KIS-ox-V0F zDYEpGPvr&Y;4`@MtCp#IV=m8IBbY<(aSj}0;RDX$PWj&O9USU~?^mybwsOF^s;;uD zl0WUwl|OZB5?j`13g+;+$KE6suWSG((Hh`3UQChKmp|Yjd+7HRSyG-Eyz}a+D!F?8 zM44*eDc61FlD|e~kZhIQOx%r26_WKqHvaBNx%b?%AO{=$j-D6bxc*4impQXSgzEe9 zey04isX`_kb@|vv{H`AbIOu`Tuwni4f|z-0Y0w6^`sryB9OnxDo&Eb;v9@ZB2-TPV zTB^|FfL(BWzmUy2nfWh})7u%`%H(fw-RjEF z_K*dK5=Hxg!?~9eCkD%w&wOW>$1 zf-QM@-bY#es~fYpRPcGI^Hl-PV`M*6Dkv9}4VMhc2H&}KLa)GW&Y@H%w0hoNe~Mf? zolajwRv}tY)Yje*`%4-qPh9qP*~fZa?AmshVhKEh9XHwKTvxr~uI(*XvXuvO#W?o` zCClf+8guLT9P6XcI@U*aCEMMU9wlLy^eK*H#fSxQiX(mMN$I!4E-x(XCgBU|Q5^F7 zUQ~1|4mOx$S@N%rW!uU%rM1oWX>UQ(X6D(Y?U5*KK^!GKoo_N?Q(3o-9euOwg_-&b@&2~ zw=i(X!JQBDTWw~{VFQ5;oI`BbkWQQnY(wDS3pS}Z+OCjO)`u5<3vFS#UA*w6R~~Fq zkcC}+lVXmyCbp~j9L%#G8{hBs8Kt~!1kderk5=1@9tSvVD!PA=1?MqVJ~VcC+&pT` zguYn(Qa$Pg2z|l$_2QSyZQKrNoyR{A#)&dx2L%%>kh0WSYX0hl4}MTo9&))UK{lky4ULsj?J{j zm}eTBZH+_Hr$#u9O)+J{)m9@M{mLW!X-EASwO0g}9vYTvvSLBeOAFt*#IjANm8K~s zsdsAhXt!A&x-&dsn&w-|% zYxRzKT<7ch4p;)6uiK5ee?WD#3a^<4L+K-HYNSP3;*8B(zL{#`G&){ z|9{SZ{^x&_!+(_D$^eI7_{0$oo2^VqTc?D2J|5@%D6Ta;)0`D?bwaUxG;Lk@Y==#8X~98r9K-R= zQ=X$Px3k>Hxw(RG(6Q2>|oNN%+Vb7 zD(zwbjw*YjQtmu)Uf*4*w}Fig%M1iN=OvW51M7j_OVIm(|~o zcZs@~6$S^nSwET8)%DB>Lk_y%oEw*(`h(?At1Gnp4Ei%N;WH?m97VcePkw zcvdysGrLVjJy0g5zq3(X%{Xt^^4#`D>B&tJXLmm+{uuseLvB;!NKb>at;=l>6yMqq zp8=b5U;A7>?Q-ayP5)FwZu=R!!`pr#w+5uhV;9QR-(EjxaFBcSqsR3#D?c#ga4u{v z%d^Y37Bs538{3>$7c2Ky?^0nixD!zylCM(4$}`^>MQbPDj1LWvz?x zun&UD)*HUE-eX_z_q|+sPP6WMv0KI64qPb|bAEPG-uvJdS-Z-IGV=0*pn zc;m*puPwmIpnb4oafBkfGtxiel0(Xu9uT<9dy1Qvsd-y%7-1Gd>nYU zeSc{g&rjb2VL05zJh(e`ymftGyL+k zSko_4F6T?c_sD89zP#W13+8?K+~*7Was%i3>cW4%XTZE)_!gapr4A3;79N$fCwZEBiIR0#0KE-9c1x)5CJ+^2NOmT zz(EJPqY0seaKc@L2*MZwWFrZq2++YgiV#8ohc!O11swLkUeSaY!rg?igjhmcKd>H0 z7*Buy~1`W*NFzuh>jGROTjfwgWS!3Q~O zCva|aFXFf$&yoAcX?*9>UI?V;AfAHzd)Bz!TCTq}Y(skv-s4}TCHc9o_l=lQ3%AIZ z-s*cor0v=vSDid5TdpU|m}fVuIXhcba2N>z%i8ts-oB?FbTK+|n$PPAd-|S|;LjNTz$S;#I5KsIHXn2fk+WDdy(i~_^E&{N{)4p{7%uBJJmZuzWr{E z${faQX?VSisBdv%1oFA@hr0Eh@Ao|+@btsEc#-qDHE$OhPmOCKs@Fc|oL#0aIGoWr z#ykTY>{}c-(Q6BHydUi2C+F%{%)3F(*Qb!f)4&=xJav8JmS?XOzP`tPzP^W?Z+s!= z8{aHtBf2X(FtV4sEm9mje#dwC$=Qs|<_t!+<|&B@hUtXP&C?DXz#M*J!r}XD#r1zH z3H$M+g)Y{Z0MN%i)D?%pp8r;1uniLglNe73p6G6^=nlGKs;x@tfd@Gg=B;QIXb8wQ z&Oq@-xtBwBAX85fhXw;(&X`)#1!t{>%mocb^W^MB=6B3*P)oyas?bFxA+tJb5(GGF zMprzOU^H24w#5*K2F>TPE}AS?5}yGMwr~|bp50(H_x}|lZgRe^=Wt*EA--;<>yC!- z_DW@?)!*y`R3`ff6>jyv^{%`|h4Ot74_@Q$*-HEurXb(XrRjduoY9!qEDOzaYsp_e zdz8*^F(=2#aTbddn~2S(egIXbvN&lMxdn8SYHhVl}DS2+eZxK-EpjG<(ZTiJX^6_8b_Bw6oeO(3g%*1%;eVS_T78u@4t1m!fH1pJV>w@Wr4J|QmcWc zX-Z0PqdtHr*7!h^@}ovk{@NNf+XzUETjkFfA5>@%6A}`h&}d>j-&_uzU1+3_#7(~J z=G$}5%$)h=n^{@Ec5$Ts=_LUXvK`x=6mSAl>=a=3ppCgYp9G7(grG)WO>TtmmjwNclyj?`ZbzEE_21N{l46sGjhS92idu1Uw8~~ zyf!m8dkk}JvCw=yKX4c$bmUdp7IyXgz;RFeKYmi~-tT(oL3W(kKduK3x!5B!7jyY4 z{EDo&yiBjn?CBS~OEkwlHRG5gNe*#bOza3kcNW1W1PCB<2;lGmhyQX3lWqgQA=o@Z zKB0i{5aD6M6v9+OA)$ycgD{;ilQ4@=LYPJ28TMR7b2hrY9SXj!i0z# zu_~Q88E50!|2`bOR#GX8g#ododgC&(?iY_Y9Ng<)cVuu7_;lia-q+`GE)K#f$}Q;i zITls&V5i%>eW5-a%zfE*(qoPV#2nYdxSVSWXw9)sH}|ts8DiPme$oTS8;Q;R@kFOP z`pAHeV_}@2xNNTIY=>N2J3}9Gj*Gq<&)^`8&xzaYRqF$dIO=)#%al9nR?C=(k1G}y z2a5s%LNJR1LcxF8BB@nx!295P2W}=J5%rNhaqrtk-gjAVFMD6bp}V~=b$-nIy5OQys*HzxLsE5Gr)isi^M%$6T}6w4Dn1P?aT;78!h&3f?tXqrua1TRXgEnFE<3A%44`W9PaCB;p)54`$X>-=X3 zI9%!LE~e%FBmQ$>?4=lA_Sl>L^^IEzaiMc#aePztTVwS$FYuo$cx7^~Iquc|%qJUi z+rRgpY~~o{WQ}+Nn)B;D=sy9?F*w(pGmlZHFZg@DBw}KIF#Cew6UQerBHo+$#V$4_ zMT5EEPv~m?X>XrrPSATNE}vRaEzO1Go#~L*h%=kIg|7N*Z}oXGQFNEj&~^4N54Yip literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOK_LGUN.BGF b/CONTENT/BT/VIDEO/GEO/LOK_LGUN.BGF new file mode 100644 index 0000000000000000000000000000000000000000..4b048376c3c07d38485cce65eb52da13763b33f5 GIT binary patch literal 4020 zcmcJS3s6*57{~AKg5s(HW`g)=6(6O7tdiiuJ?FB%n?WU#)Kq*R)QFEX3`GlLutkay zb0(9f$1#i2(T|QU zHZBfQv{#e?r$Vv}*QPRK<>mOQANB{R%{TJdw_8VXMfzx3O7JL$MM=``b{Ovn!Y>6? zhmzb{WMGUV!jipo(TYVcFL7lpTrwg(V|99VR?d?2#jj>7!V?tdusd3rLm98#4)AC{ z+irHfr2jdq(0ENRH-6Dd*x6~W1f_J2G0WlfGCkU(5<77?zUqQCEfI{o#Ndt1KbYX} zB}Q@Zy5}|~2F5y#gYz5o=6-doXCG&RTDH(2HZCiQ-)dzaPtIqE1FLD;#NZ_cFBrVU zMqa69F$Gt=Y(`iduUH;oGV&7JIWEIzJa~zr7Q|6~ve!Q^;;25F2Qkb;o^M+@P#^Nj zUaFZG)_~^r{Eq`wtn-Z(`_-kxi`d1_r>ZI6mFe@U%Z$+%3iV?@RkMoT3mCEAzAra& zI=DC(dBI)?ba8+0fr3D8DYEm7gkXclTfee}$qZg%at`v!ETa2<)}i*EO5?!`cD;DJ z`o;Pz^Iikn-WbDzrteCW>jMit;bIg=^Szxj#>b0!To6pof%#61o6m^Rx`0s*jMr8U zszvrv%``WRM{}e7adv5gerH)7qdjx}+7O+XRzHv-4vh8!81{#M9PJtMVmykIz1V}L zuO~2yQ|(!d7{!4lYZglY+J!~PDr6HfLF@NG@wbCeMV&!gnZ z3+l;C=4jH0B=>Y&|)%xRy`h@EUKHyS&;I2d`~yjpJ5*E?JO=BS!ZD7`&91;)wZs5$B(Syp$JSQLBDtXD}mnAT*s3 zqa0vL=_Nh#*#aZvdbv>&S;7u=)Wt*EeMVj|nlIKld~k_R%`%&ygv%{lZr#aBWxM;Y zz2kw71RNJQHXi0Uz|nvs0>^@*^)HSO90_zxU>rIsaE#DV@n74ze3>dIJNcXi6F4nD zmUUZj8lN~K)!a68Ilrt~ZN|}3BMz*8aThLMlG!O~yy$GRx&3h)Ar3hZ_dm3Cy1Q`K z zrDvvvjCE^YSst~mZ?SkZ&4QPw-NpA`q_&q%Nvx>I<;3tpWgXU+gV76DTMRE@;-ltOBs9jsl929r1@FLrAe1{oF%yT4)gUNZ z`|RIx{8KIaW=v!LHRqmR!Q_`pc!|k5;7wLi9_RshT*M<6evr>%|6X7bzvJWo$mmwy zf8cYs@tuZ_q}k=}lHbADEk% F&)-y2>M;NS literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOK_LIGH.BGF b/CONTENT/BT/VIDEO/GEO/LOK_LIGH.BGF new file mode 100644 index 0000000000000000000000000000000000000000..29780dcd102cc53f3bfe490fd37ffa6c403fd062 GIT binary patch literal 1620 zcmZ?q4AXV;j51`*n;?%^V#sypk5Ah1wjQ= zDFp^M2Y1E}h7T}nK~88r|Ie;mK-(VVERa*MiGiHAa*w7xNF7Wsx){t$AoC8V9k2tb z1Bt=Zfy7{52Z>$w)3rapa1V;Q>cwSnF<7vG#IC&KhPw}@7bb>oFR~pVH-qf;We8*e z1|b6@5HkTWGZ2FXplntk%?8BmKnx0OP9Ww2Vvrh;95)by^n%1dY>*jF49n4@!jz<_ zU`X#^2!Od36zXp;{j;0My$u{nu$Tae@gCKLhdM~zf=fZxFfo|#L1G}iz6^pGK7}SC zPy$-=AT9|+fmefyLL4=a}VR@R;@&H@v N$KujKnoofx4FHQyHlF|h literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOK_LULE.BGF b/CONTENT/BT/VIDEO/GEO/LOK_LULE.BGF new file mode 100644 index 0000000000000000000000000000000000000000..e12208d3436f5d55e5be78370cb6d6c0982aa98d GIT binary patch literal 4312 zcmbVPdvJ_b6#sS?5kV7@h?TMi4O&eYl#u)FZcTy_N!m1~jiU8zHjTz(7#RuiN)_?w z7?DonS^mMjnR6yXd5k|!RYyY-=5vOOEEHYCdqHlx#!$_f9L%6 z4jGow%Q@`5J{Be1Y%`mKEH+DP^SCB9bDJ)~Hk0WSC4QO`T644G;563(twmxlZCl@V z_FSdw(iQ32xhd&2{l+wE^^4wBN8KzI@5EVEMf$PZXNLB-nG}az1SQ&<W)ucAD{ zz&JJ#%W>t2leLFMx0z-YvDnVB!9BbfZxLAf^b10+rQm*+j>)m84>|Va8S9-l`)UD( z^)kwQH6xaD@ZKDSW_5eN&Naauu4)J8Rf+3Oi$(j3Q*`X~wcT1m(or2NxZhX}zm$$X zKb!%u=o>yi$F1?&!Y|7;oWb~RE5xF8rTTt>@qU4Ej`O+0s}sJsr{_R@?1%bNw^tZ@ zBO0KVF;vTi`VWn>Ck%NR+jD)q_Ox2O>yckVX}NZ4YJt|+s!mKp4o~dDRw*LrTZ@V_ zkTDzW!+m75UJG(m#-xZOx}!kM8;kp(`oj8;(B|Y`^sBjSun$X8(pwT`gUMQvwI+Ls z%uEI@wIE7KpQLe~On|C@;LH>Yj8qULGyS39GMO?YED`kKDqGd0OLM@5+ST`;W%U z^`#D|Ot60cijdp>u4SzNrjHR%t4(RTRv=a%bA*AmydL|3-s}gATf@7a)K+;haf9U? zh^?f%yy6bh&jsy*9P|EkiOg~zhV%2Dm8Y#R3LJagV#5-vnxwRpshq5Q@J#B1?%Yn? zax(4FQlK%n8dD#12Hl;?sQ@PTeI}EYvLa=+er`1OF{XFii&Zx+PBHfGk&%l0d>xbJ zX6ca}^_R{0Dq?w@*HJ7m`Cc>T=Br^*A%6FobvIVWl9kR+JQU0a{Gj(8_AbpxL7|>o z>L)p!_D(OLpf{*pru0A7rQ?Z<8^opo}eu zFceviO(P5{$jX@dAWBie+=d75_;S>4?5CoI zcSc*)PftXNRVAfj|Jpb$GRsiBAFeGD!8=OzZwF|Ryzr~qtU^O+(dxj4Uf8Xj8)hi2 zo`c!}*gnFbc+2VxMLy8Z7c1w@Y8#>s+EL+E)xRAnV$^O!$@Fuf^%lgA(A?7vHDavz zvM&ecZRqav<1yA_v~N9mZx2bOZ50)wCNoa^s?@FR*pjc6yjmx^|Kn3t#6Ie3C@8Bw z>YFmUxvro|N)%d>TM@s}j!?p6W&RVH`!pp(YeV(GZYYu5&a7HcCA2ki$nA~)S8F(P9Xb zsk)Ms?^v<_@n>ev6MN@Q8zf&-d1O!Z{?E+@$!%B_WvGZu=?OvQx{Ap3c%9S%O2G60 zEtm8#lm!@5I<||UEHYJ>jMQ{xk=MJj$1S!lwyKPQmf5u5>wAJ!&H)N`yXg{(Bn)|@ zZn#7&#mcnYHNa37IhN~_bMQW73UYnPO4{a%LIzXsK=#m{nr@v`bKDe zVz&KA7^FkrFkzTQ4F!gD$TREhT0=VI3+cZ)RF?$#;xgtN((!*X0n&3rIqXd=BomN` zNg1I-oXYxu7I+RRoLr=&as%LXVyFGor#({f$m0j!s>BF2OM`P*e{k2J~Uy*bd3 z9NrpYFAr}ew2%&7S;M2KiRZz`vB0*HOhW$Tycc(UrpLHtuW7#1-ha6KFcb=G+$!TW$On#C qVDiS_YH>u&4tdSXB^)>~+uTcj2if3s_+dCSV2FKMAMo>u4(2~xaWwq^ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOK_MSL.BGF b/CONTENT/BT/VIDEO/GEO/LOK_MSL.BGF new file mode 100644 index 0000000000000000000000000000000000000000..4d859e65c614dfc866366d87d11ce5079388ef74 GIT binary patch literal 2017 zcmb_cOGuPa7`^}hYd)H6G_B06KWY^OCDB8sxp$@+L1Gp)U{HZsDTw2vY!NnCG!O=X z3n8Li5j7i)D54_LHi4U5)~YrkWYB}KhzR=5G-tRCLLdqUFK6y|zsEV>A8T#f7HvJ! zlUH?Ss!}WK&zRw|UB06t=9bsum*bbr)Z<9hjCtGrMkm$ZGuYGJ*DU|L zcebAzYVYkH987h#_nu8D2`k_22mAu-s}^(28!;E%7ulGeo#@oaJa>LR{ClcbgUh}= z5GHr$#$KJgR;^j#rhBi$(T7`g{Ec6z`s0G3B@yM4UYAZtDk5paL9pJaID$BN6x;-K6no~$nhRI z^u~J)Px}7p7kR<4U*7u=Ocyx52M&Euee`B?_C4x`_o$m4%lX-PIcMsDSn9#v$U!&G z1swIY=S&|^Bi4dgyFT=R8IWTi;1cR)39MWySSBbFz}ppqO2P6xa1IDoP&@ C8o)OI literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOK_RDLE.BGF b/CONTENT/BT/VIDEO/GEO/LOK_RDLE.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f372408f5667e00e6c3e249ce7eb50620c30a53b GIT binary patch literal 4821 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOK_RULE.BGF b/CONTENT/BT/VIDEO/GEO/LOK_RULE.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f398244982234026939f015c9ccb1f282685d0e0 GIT binary patch literal 4312 zcmbVPdvHu=6u-Mk1R+8qVx=tF#p51Rl%h;JSclWp7`Of1z=lt$B zG`N1?zqI5z7|!HJ~rF@uz^;Sl4ujb!>mp5&+@|u674ou zKwoPIQ&x^+uH&QZxam`~V<%-UnlxvA*3{{fX3fh|NU7*RYlen( zr?30g9SSmQ*zbbbw;wR9Yu3T1`$mIF;}BOxgs3OxJrr06Y;5td%6A9d6Tq+z`ymzO zv=06y6m1Y#SJmC39{oI9oM>`UU&s4ppX=qtSQpr+NmXKt>9HO!bZ-SMeF|e6T|P5x z>tOGq>M(% znn=tf0VIJWL7v}X^lVK699SEYaFPfT)H=SmBZ=||a9}CQy1*v%3?{*TSlf)GIY|gf z3zC*3_=J+QBEcH0g)QvSmL!q{YoP-i_F)hIw*BG#7)xkPi8=L=W5e+w-vb&Kn15A~zv z<9TwwSiE0f?LBUkXr~9o;>@@mer;cSaE}+`@vwlfuc=Js@v!E1hlq4qR4yOvx1wUO z7*3cxGB(yZ#1|1UDwinQpdzs^tF9tz@OxsVqcHJkBTYja7fy@`)s6R_652!tHLg0JYr;BX4QDX1WtIcMjd7qm?L+jS}n%u$cPQI);9N z%eb6m(&Y&kFAfdZ4G-0^F7C3pz+j}aE>iH8hprfdZm5T@SQmEFM?KbcW&aqH?XoUo zvJKXieMwRJJ(WHH|2JptN`0g3K7afvRZeBI>{K`nzw@cS*K`C9Z1TD?Z-RjJ`_18p sAs}GTl>>UG`Hx~@NH4#-d1z1c!;nZ|)+JZGy1<|d?7#XzP6mDd7c9{!ZvX%Q literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOX_COP.BGF b/CONTENT/BT/VIDEO/GEO/LOX_COP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ef8ae3f30abce1e99d55fa0e9941ef60c70490c1 GIT binary patch literal 3104 zcmeH}e@qis9Kf#y`C&y1!W0pEDmoQWq*xHzyJsnd0;Me~8o~sBp$J$CIGh@TQzua~ zoO7a}iyP|PWxllosSKi<@6Kub{MGS85$8mQON&icub+5*C`x!~~3*~F>>}?CVxFVmrcf=P%T^(yJujONy3IW}vx=31qRe|+ybRV3x617@Q;dcI#C)38crNv~Wb$A&FNm&RT?Tg{+(hn=TQC>m zmj=5ejXFn&ABSTEduCF1>R=c5PLU03O7HEWZzZ=sJ&iPt=ttv1v(|HXzvHt9QCG65 zjf?izgR63ia|x@y;dU@CbwB?tz_>GTF4V;rr*jQstT-;sS8=S9Tiv52Rn5z3+~u|y z?n+29X=+HIaq{qu+PZB)xHzU3YBK4ipIS*X*Va^960u5Y>hP z>U=lla5+1Z$&#ZJsJqsMX*a*jmthJ$fwjN6ayyN)2Y8(LvoM7i zx9^}X!?b7GnovSg27FFkXT;XH#fGT__rJIvwZHDsDH@|l&8}V4<=Z2<0A@p<3EOuG4Vo; zQ(9;1vnN9Mqg1jZK|$ks4l^!(b}Gre{UhC{leRLh&CgBbY4<(q*y#?Zv{s27#ZGBW zi!!eX(mh$X?Wy3`X(PAx*V24yb*XT4m4+BL7t&fqBQLPlx~I zWa@COr7pWl-=}X?^IyX0_9RlDG?MmJZMY}Yl*f|nDmis9p6g8xpZEKULunl5lRjg! ztD5^bUH{pA96lSQeec_voa}-Wl9xA@j)6`(7wju_NlfGj_+NwpDqu`+I~H2D_Z(dc zFcX*sn3>N!`$6jkcmf`PH-N8HU!Xsr00sblz(8OSpalGZ0AMf>2m}Fd0YiZyz;GZG zz&YW3SYRZ8*Vv8%M)#hx(7p|f1CoGbzy#o2&5RAF$jAUWfOEvT;uttqFfa@V0a5|% zp9YwL^xkXq7QhN%ZZmVr3u}S384pYV!hwkZ&I#uh0ZalW1ChWKAPP_e(ZEzd)7!>C z8w*SW@Lh%;uhHYXQVZw+4#0IK0OrD+(*ZqzJ^?TQiGUFx0M-C&VFNON833-Ikz~m# zneXu%iCvI|UlO`yQFHn7!7Utqt%#1jSj<~~XyKNcAHt`W#r>rGDsds-z2+MC>i5-< z_p|xy_0{ga;y2gjFgxF|Xs0`lyEBy}-+aoQ&olG)^Bdf8qFd{m%b#HnyT=f}-Hx}| z_#<_9X9Kbj{&|wU=m=kw8USkaAM2CIx9CPCD=>D%RR`9>7F68|OX(Y?1 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LOX_TOR.BGF b/CONTENT/BT/VIDEO/GEO/LOX_TOR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..71ce1ec88dcc8ebe98c6e16bd6156d0f0fcbe984 GIT binary patch literal 1131 zcmZ?q4AXV;j51|BO5%`{z9`_5<1WJLCc#LLNW02PuUC2L}!oGX+KlM+XKLHw6xma9Wsv zi<5&Rqk)1fV@`fWadu{&RZf0(reSxdM*@TvUO<&4G)t zgJFx!UL*T+tHd4Zv+nG3<(+3|SmR*twoTc7)=W(Yh2*@w54@JyEs77e2dM)&D#Fsm z9;EKe-x_=M1)SFW+>#EztuE}#+4|qE;e(_7sl!J5VdlmDG_VJmXK%XCPU^sJu;<*L zoVL?m$P5zO2NS!)D`gK71L=j?0n!VyLu;k-ewbStuIbo=+~Uq)1M)m05Ho=oK)?*d zAU+EavjZ_GbUXG6=GO_#nUv#B4z9#4s0Y7#3j-Lx?Ca3>nfp7y>}? zwd$jv!`U-FcGjLOHsPDA>_KAI_oW@4txMex5}WtR#s2>$Yq;1%^_g}sF_>PE7)US3 zeIU2N{0DM3F8AeNbst0&$$k4_cHDheYY(ym=oYw`d5$q$4CZE#7|4B~bO{p!=>>^l zci&d@@G}ObK|`xCLhQa?vjL0k^6ar^U2L@9o2AKa zZ_!pekX}%}xi@*g{h3Qn_JaRP!D1luK>4S-EyNyVo-czaD5_Dy6cor#4A|XGC|sfL fhKC`NyTM|}c7wtiiyQZ2@e4exVSdKtZlGrXDJ6u2 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/LRMS.BGF b/CONTENT/BT/VIDEO/GEO/LRMS.BGF new file mode 100644 index 0000000000000000000000000000000000000000..c24ea4d2be5a38ff190ddb7c08b1f0d9d08cfc4e GIT binary patch literal 344 zcmZ?q4AXV;j510FcWKm$^vEo!@Ky@7%dV^U&qYME7W zMq)~Sd3 zz%2KwUg;n`PYEo}YO>cM{i-lnFUTQ4^uw)bUFWC8hu6^Pk@m>q~YfS41Axqz4(hp%1kwY< E08cw~CIA2c literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MADDLARM.BGF b/CONTENT/BT/VIDEO/GEO/MADDLARM.BGF new file mode 100644 index 0000000000000000000000000000000000000000..9fb8bf2afc843a45a8fc9436c52a93eb378d25f1 GIT binary patch literal 2709 zcmbW33rv$&6vw}|ysZ=*3RHp5$J9xPC{ZlPy=_HYN6|2_fDf?aCA39`&Ib|&MXheZ z7qac7ThVO!Xh)>_yr-yS3Zn&Gj*W$!WJYre6-q$K9fb65H0$Ny7+iQs=+ip%Q!1O zMHF<}1F{6s3kI(}ds3&@Zj(idqReK_S!^jNipkF{ipnXm|-$|=pVnoDe1wk1|! z!oLq;>v=_sKH}dtQAp56%j`mD0Y4L=e` z$$hLzGm>z|y}-El$-P9nRi&oy6b(WPP8Xn=`D1Wzy_s%n885LZZ|hOz-VkgF&!gS@ z1F6-!J0^Wt5xP-56x-TX(w=z{5{v9kKnq*^@r}cC=xKwJCSLMHe$y+^!B0dS=aWVb zwO@(@R{Y`sd~<+BVrWG=0;Y@(l9=b!0;*1aLV#UsuR_)b!8l3Kxj}SgOmZd#699K6 zVDRx^@?-)A|3NyunS7WAFzK|T6f8-Qpo5)xdc9UHj}+C8Nt)=Ap6C48PhwhRcI`r$ z)!UmkH8+u;Z!JaVkq&>|)qpz6DEVWW56uW%hN@z9_*7Ia3R@RW&dwFdEbVq=zLkbe zr;eh`#5&@0y*4&z^mbHtCk-!Ic^O@=6=~~;9>&k1j^mlQGN&H>Q0hiYF9y@mKb}Ls z9m~XvAMSEm<6d?yu3WnVIqv17yj&b`$Z>eJOqD;IUW1jFFQZevhotAI{&hX!&k_HokyVnM?(%9NA#bGPuI%GTb7CQVko_5H9nnA@ zEltOUubQ0ZOSzkg^D91f+H-ANCO$Fy0Gc5Lxh5EXL$aS&EWAjRY}`O5C=l@ZGO3vS znEaXa!tXA{5#>}I&*opaXczX!jJ!)~hWny!)kbo@%pKPq%Ez3g*X=+@Y62y;vtdZX zlU2=#v$98vFlXEgjC+AuYaXF?yHOfvYuinL1ugT$hbQAc2J>;oy}-CPNf`c*=ZJ?! zr+vkpof9}Cc_zPjz3`K3FSF(5xc0Js;&H?-ESH~|E%nvPy;tHc(M8A@Jsfiu9<-y8 zvzlp%WUH!_0K1yvj>~ryV$Q(J8T9E$V*$@->)acGQ=PoG1Lb&b&0LA`tV3lDPRWp1;hE~bYCBwI zby@?wd5MM3u+J+Zp7FY07%%Mw-h8|Q)wW4a`-A!Jyc8udkBY9o3f%HoV^4u^}>7*KNts$j{^qJ%NfiEv4=f#FJG5?;l%M+K|bKEzPU%; z7gNXwXFOJX4e;`qIx>hA?8VUwG36(i&&OlM_XqRwm_oh4I9@M~USPZq_!_)kcwK=P z7}QmgaG>96hbrf%+O=8o2FM#9oD5*l1mTU!8{r`K{RO4~rol`@m;#xCn1Y$qOhcK5 zF@-RNGKDdL9~gZ9tD$zewvm3WME$f8!rBPGvN&FMICH$lz}2n!oSXm~8*>XSSFORE zftRyi#wXI5tum>NoIJ4!m7f`dZ|+GZCf^U^ppDF{_Qq@KEO>^XguwC}#{cOmEC+uA D^jxt1 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MADDLGUN.BGF b/CONTENT/BT/VIDEO/GEO/MADDLGUN.BGF new file mode 100644 index 0000000000000000000000000000000000000000..9c5715822c9edd245173c3f908c66e3453d89385 GIT binary patch literal 3858 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_LBTO.BGF b/CONTENT/BT/VIDEO/GEO/MAD_LBTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..b419ac72ec6c2bbf0a59cc69fa723988efd8d9c0 GIT binary patch literal 1053 zcmZ?q4AXV;j510a9R(@<@H*nI81VSH!p@`adp^X*$;&wvCR9Ck6ADKIiPI$URTQ{Vu} zG#}XE=;WZqXrLg?n46eVoSm6xm7bbs9G_AZpOcoKUlN~NlEVPh#9^+$tpF2LU~psj z-odb7QcNA#QjkSY1Z3?)p7q&*#8{7>--j#)avaD(Ajh3?Q@0mgvd|jY!7wqH!>i1+ z_pVESVORTZp*2VhV0L`G{>SbX&|Z)jNFB&tn3yj^APdNsj6lo;#LQ3( zVuK`DftU@-28n^xfy6*^AaQmm2C+eMAmGF>+dx4EIj{^935QmC2SWg|3w=dB?30?8 zfe#PA(7YC+Mu-j791MDC;~+@ENVeCh!2WhP;??kJ19y) bVxZ^+$&(+o$e{&`9%LVr8r|5U7U&ZI<^f6` literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_LDOO.BGF b/CONTENT/BT/VIDEO/GEO/MAD_LDOO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..1c97aee0a6b7c7a421d4f7124a1ae2cf3624c267 GIT binary patch literal 1380 zcmZ?q4AXV;j51Nl`$YQwC(Uwu zIeO;U7c!`nPWIR@zWwF?zwIS^8>a@_|4S{mnf`ym9tI@f;K0agrohPH=x~kEO@RX> zv!QvtqmzRcqk)1nV{T$fadu{&6_7TLPpOK}Ny*PIiq9>{VE}64FjwGKfC(xvxG{Y1 zU|0aMGkQ=T?Blkj(>$A$uBRFG#O1Lm&&tmyAHn z1jNih3>JX0S%EYg5QAut97qj25QEgf=QWO-NXHGYnG}Ti3tkGpZWc2mU z*9~9!-8T-@xQUYYt+#*8S~uO;W`P@xYWzFUK#PAMlZTa0U zICG%J{qvn_{lH+>%AYgft^4hdTXd-7PTl&$Mjg-p&dUd`qIS@_cVMHIdwkmx*B@j{ zJg#?khqo`d%E-^&zRZ1o@VOkvwSYsctYt;#5?yfXW{*QG>I3(Qk`@XDo^GJ<;bXDhs`4*3TYJtPL(MZBN^w<5FWV~FbgJTnB&g<%&R0iv&6tB#! z1Bd>}J*re$8C}n73D*&35w0i9B*fH;z!dsDm4G{(N0>&KPPmeA6`_=HHQ^e<3rmZN4sx_|^zuqdS;#9RM=M7!M=3`wuZ)xsogc@&==m?z>!|&@pIihEvTZow zIOGVI?;;1tMZ$(Gos}Vvu;je6jGS4S#!Xqf`D^#5XA1O-b*caCBC>_74B2A7@p1&L z4B2w2Ak+edbF4fE?;%GdW1(D*g^S>9;N;ol=(qg%@Wp1wcLHvYANfr}pZyK=*K~&f literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_LGUN.BGF b/CONTENT/BT/VIDEO/GEO/MAD_LGUN.BGF new file mode 100644 index 0000000000000000000000000000000000000000..a43c3d8db633be50bfc7edfc0f650c83bb7a81f4 GIT binary patch literal 5053 zcmd5=3v5(H6rJ4`=pw&bET8gOYlZM>pvAP(?!NbSgOEx~l?0Sxq?Jl3Eu|j{mDsug zfwops`3n)mVh|z-$ftzvdu>F~5H)-Rg)~;BQh`8~pAtalJoXN=OCz7e#7%B?_MCTT z?##Pq?#zx#ni%a)N{bC*-K}=3H6+L$)YqCGY`2CEw%IL~e3nqiy4hVj^s*TaeShtD zMpI2Et$;;kvth=89bJr!&x-1sqPx|F{ozt#C$uU|`e<5OSe)I$T-r3-XnP2l1@*Nq zxAt<-aC>jd%#6&Uob0@WtXK15rew~WlABeWH)ZDRT*iGu;_V&nKFrQWYeR#|HIJ1B z{W|f2^4Eznbwq57ld#dt7a31FoN7(G7H4h0g*t)*wk*M^u9@dl2!n6d@iO)2YNtYh z18Y89s{Rm}Eim|o#yQkuowAjjA;)!0(CjbXpG#siuo6_m^Issd#^}s}u{Ko409;z>dsXuM-x2>V}vHFiTju-x!F6#-LaT zLoD(dkT1r?7nnGj zH`f5qrCs?-S$OWSS9xu<`P`iP_mmC$Zu$BCzV~hAo5l-@JnqcD6O@J}UH#%a?M+iY zs_LQ2{UPT1-x`%Gr(WZ7S64Q z&(QA4trxf6+#&7jV z+oRmVxVg10TwxKi!eTQ5C1wkd*xaBBF0tOvr|HS@Ha&aR?0WX}I(>Rc5r1`zwXS~4 zF?RB7mH1<878x?1SY=beTT(Xa{WeW^m^||s-uU)=xVs1Zp01_pT)n^d^n!I>v;RJ+ zYJEw#=>J+;zTi!NiHAS&A8-BM3IB@`sp{d9aFyblvT}~;4<7z94}b88e|Yi$1^%&T zHs}Kz3*qm<{2KDh1P_0ihd+3lpBcY2Klo#QLlzI<`{EMa7r(*hXZ8>Oo2g~$>c&g@ zu)L`ze(rzu= z5>V|&1kNq6+Q(bUSt}JB6qn?iyOhjrFZmTyV81RMEHD(N{K!ZZ82J)LzH}&n?-zsD zi^Bsw2TU%A=ue5dAux)CFgg@ad~)H0FUF;!OTHL`FnQb*=DMr6AT^Qhl-iWaw75u1 zN_V7`ON;BkPg*!-ZET(9c5BzI4_pThS}QbW9du~BUiIt@M`0!3=cRovbE!@3)m*9) ze>Rxc35kDZ*$M~vT-!)pY3ZfI|Mni>!9K*`U%#_Z@bH&;_=9iU{brpszSu{|pLpN+ zf+v5BKdDE&;v1jWAdk7vQvAgG#uq%r-?=H;7@y?T**pI8?^SJ62gbav5+4)dKmV!8 zD;(gD)&&_88bS>C%kzW3_g22(;V<*>2cN2as!QXG`H?^IzVQW5{usZm-FV&CznGsK zA9!DUf~Wb7Vf?k;Q8?|nNJtnd9^bSN%Sj515)$A=OaZ8?dt4VzDdDj{9 zY(udOk1kWU#gz;ajUF$eixlsJULs(K)iHRZW2|L?vs>m0@He4=NQ&{L-TL{nGe*jY;2XnY-2Y zKhE~HFJw>&30l7Ir=i;ZlV!{H>)%~smoLP;TYUlNZU!Xa;INC?Oo5TX(cwCyn*s+& zruo1QM<)j@Mgs+D#@xh|;_S>ktMt@7LAIJ`cR7V~8YWC8h-5r~<9 zm>G&eY>)&i5VJwqATf|SkQhh~B+d@SAT~%21e_RV8z{&i2bN(X;m}I&UNoUJLP3Nj+y2!{eS2R9K@8tPqZSmcOFpDI zksr0#f*sjm$k7OjGD6Xa?0MuULytz}a0iNjohTLC7hz~IL4 zy@O!^%u$gPMyCtyLgDeL*1Z4Tr8@~3&#{6J0n1f(qAiW?lWWDB{j&M)R)XT9i zagwnIi78wMoy1`{k_5?T|y}Ib(qR_IG;rz6^pGzJo?BC|Z|%NOK}T zYOw`7vLj$of$UgV62KO<#6}r%+Jz+*Y)J}N)PkZ76lEX)iZbNr2Jt~r2~q?P01$XWVgLXD literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_RBTO.BGF b/CONTENT/BT/VIDEO/GEO/MAD_RBTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..0af332d80b567ec61c2c79e6eaf879feffb3312d GIT binary patch literal 1053 zcmZ?q4AXV;j51;2Xv<_+e z&uc^M3mH@tlF#k?X{ff}KudFP!qW?O`9jRQw_jXf&wvCR9Ck6ADKIiPI$URTQ{Vu} zG#}XE=;WZqXrLg?n46eVoSm6xm7bbs9G_AZUzC=gUlN~NlEVPh#9^+$tpF2LU~psj z-odZ{WD(3#4317Z*jk^`v$sbvRZkT{4BVuSR+)H*TDHc*g34lKh&!l9Mk!4QD#!m!UC_DRi4 z?T|x@tHst{-%!sUIaHsoEVF+B6hjUfP1|gHu9l^Cz6^pGzJo?BC|Z|%NOK}TYLOia z3r=jo4)Oqc)FOKdmISaxH?l{OlK?Dgk&^%{YGGp7q81i~$k7F2!=e=wg&;mCYC+Ko ci)K)ig8=zai|k`kqY*izVaWnp)B;@(0OMa%LjV8( literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_RDOO.BGF b/CONTENT/BT/VIDEO/GEO/MAD_RDOO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..959894ae24486e240916d1697457feba1c6731bf GIT binary patch literal 1380 zcmZ?q4AXV;j51MSD9XKGyVUBJq$>|!GV$0Oo5TX(cv1Sn*s+& zruo1QM<)j@Mgs+D#@xh|;_S>kDmc^ae_WUntnAPdNs zj6lo;#LPep7J#x@fixQsgJ_T(NDVs>gVey}Kzc!9Aax*lCx%&Qfn`ECu+lpi0+1be zcD0n<&FLa2fdvw~low)$9H{+0g7z>mnCC!ZAicf}f*78I#w;jSmwZTbqE5`7!VhlRx}?oW?^E)#jGnR&w^q#Elj`#GZhk%Ws%(qDkoss1eWb!VxVjX5`&c| k`PUFx8(9pJ#V}JLrsJrXMPPvjD`P;}0VYOFKmzkM0DCy*-v9sr literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_RFOT.BGF b/CONTENT/BT/VIDEO/GEO/MAD_RFOT.BGF new file mode 100644 index 0000000000000000000000000000000000000000..fa64f70d9fbf383c4b5fc2af857a62517bc2f8c8 GIT binary patch literal 2435 zcmbVOU2GIp6uvvV>eh{wX(ur}Ca3m9!n>yk}N!P02s zrtL->S_2V?CHy4l0}ZK=pa>6?z)r;yOZc&g54?asAwHOBg3%aAv3S0zx1P3OQk#6) z&Nug*bMN{2=2lk4m)TVtR(M6eVH$?tYkG@}dY@?omS&kA&sI^^CUS?P4Hdg;@}2rK zADm0{2d%e6FqNNiUfR^}Y`^FmK6v0u^=eg7+3;((m0*9CWoEr#dPKyseXC7B-n>72 zI$~QT-jG@7+1${ytvT6Rw&~5*lDejM>)H}qwzSu6Zf_A}wK<}R3NH!ir7Mwc5mJD7Ik!WJBlVRpsUr?=-TzL$C5rKUL8VlUuI!Z+Og zX%4pFkQZ<~FNmSn>2n~4=Ja`SHgG&I$e%uk&L8p&j^~-@Ugv<txwiF6EJLcJH915?k>!ELod^0xRdCE#b%%FJ_h?^4oLG`^R} zC%dOOtw7+QXncRLovCtzi^5Z!&OJCNDSeE}(`&lr7t5DtI);L3>)3?6a(Sn#>I2_@ z>brl2aU<)Nk{G&G4N_V+m1imgRf?ORi!Fa}$;}_4E@R*4BFu@P%V5o(jW~~@_ z=E@Nh&%(v5$$-ktR0dmg{x3y{rbURi7;iydZmt?J5tucx5zF$>L}D5f@!U$=3VY@} zkz%4xj0X30m;ct-@8AMa@Op>3UfQN`sn8dUo?CtkT-g6y1uhzwyGJv^{8s(Gen9by z$SdcDRyL&uS905%H9ZO(k1?_&N2&G`(`;Q?>vA literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_RGUN.BGF b/CONTENT/BT/VIDEO/GEO/MAD_RGUN.BGF new file mode 100644 index 0000000000000000000000000000000000000000..327d1f98e4c27787c8d46f239023d559ff797273 GIT binary patch literal 5053 zcmbVQ3viUx6~4QhlHDke7$HauE~`Qd2m}}d?C!mr)gfgh0em}MTHTEQHN2Z!5AH2D21l?`***eyBj)+nK|>{ z{l5R)bI-Zw-1FbuKJA`c!qbY!yTr9luhZ#vd0n~A`DtEf=17m%;iwc-s>Oh@J7L`{_S@^4pym_T7=T$FUUNLXUvc*E{xbwXk-UQ|q zQ$wR&4WWqh*u=34M&I;z$)k_dslFFFg0(9jlEiLns#DjT4N78DA6pZPeCt=Qe-xC| z1?D{MSFX1^f+lwO=ehFN7mp|DK5?$W!cIPs6KFrx5{2&24bRF!A6}5a;54zelU_CI z;iHn+le5btFxZHW+t!BnVB_A_eu}#ALu{&78ym_cb%9lFu2DcG~)?oJ6Z^^80Gc8?WQtMV8?vQVl zy&r_X&^=U`u7KtAogd_TqYKm2n&NkZqs}&4^9}iPi`=>Izm_iF8`U^RKD9nunKt&k z9*_r{`YUrSTOMzchfj3LcYL#h3kGbp*L?7k6VkMSHMf6pLKcatG-R49U12$9g^e#sEiq3@iLG!o>JqEn;R~MGcRcvs z_BFAub7sWesU4*BjFIW(jtgf^9@}l=~hjzWLTOig2Y>LXU2?JK!GL97MBtnC2m2YBt8L!0Z}8C1(fltbpO$wmON)WO zZBk407YX~|*Z7y(Jmxof%n!b2Setw`z0F#`4m;K!fq>t%qf%YO=cxyjA}+@=Iavl2N*MY1w6FHQo zme^;TN7@*5iSa`Ly047Ygcz!I2=0fyy8A^$k`YY&gPzt zf#c7u3{1L05@5L(Bx_OGM&z&UWyhT~(0Qg(JTCJ%6Wtu*x4gFP* zZV6ETf6CzVgkZ}YVO@*~entS>RYWgDx2KJ1fEtl#FjKCVAuUu#-teT4d7 zrtOjHl>r|R+buL zU`S9TAvlilM6zNI^W056A(+HCF*xQq$upQ=S9tQg<+%(!U?>2d&A`H9{|`7>mxyD!~f?z=gDgTZ{f!C*ezV5o}& z3^$lnW#y8(z;J`vKG$bsSPO12TYlX_srJZ_uT0i~;Av zZRH=?!)0g93-&Ff?$lBJmG4rGN9OM5?V{|UQ2%+O_pN43Pw!jJ5iz&dtzmlp7rkyU z`U^hI+*#)9<-XjRzyGhpBF9-Htch@_;EFqJf8AkUWq{e4(7}iyaO|+=<^V%CB}QFh zsU4OZ!S~SV%nieQe>(Gqg{5{_ZZ>tXKI#&K?homl2qZQIb%+D0Ahg@5J14qk**ybp z4~uhGSbXA8gZLx7brk(Bi2sBjjXS3dwo3&V(sQjYGkQVn*d3i#L=ipePS7dK2mtF7 zjhC5eoHD%b9 ZKx}7Azohu!y$^0I)%%v&YwbFF{|CPvR2BdL literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_RITO.BGF b/CONTENT/BT/VIDEO/GEO/MAD_RITO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..1aec2e1cec5482bdd90857d17d8dbcb766625e81 GIT binary patch literal 1053 zcmZ?q4AXV;j51y>;2XwV7)B zC+2zE7c!_kvtP3Br=i;ZGXG`!=e=KUmoLP;TYP)qE(Rpv;INC?Oo5TX(cwCyn*s+& zruo1QM<)j@Mgs+D#@xh|;_S>ktMt@7Ok^N46_XsWRL^PFp+R*rFSp{AiHo~ zQ;z+exl8SkL+f~RslBC>o;`A?a-4CuFE`M$M-G`hkwAN!j-__K41yTGgGMbVT9f(Orm?1Yl_!CWb9)VNr-2eIPa{ y+Cb3=ic%0C6qTSTg+(h!4g|=LT4Wz%i$)17(O3_R##mr9B8N0ASzwD=pz8rtzgI#4 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAD_ROTO.BGF b/CONTENT/BT/VIDEO/GEO/MAD_ROTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..c2591669ae10e8a1cf502fd64b38ee15636c0038 GIT binary patch literal 1053 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 AGXMYp literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAX_LITO.BGF b/CONTENT/BT/VIDEO/GEO/MAX_LITO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..eb8e2d04465a89383feee58fcbcb6a5a624913f5 GIT binary patch literal 578 zcmZ?q4AXV;j51;2XnY-2Y zKhE~HFJw>&30l7Ir=i;ZlV!{H>)%~smoLP;TYUlNZU!Xa;BcSOOo5TX(cwCyn*s+& zCM`_B#mPa7(Lh0(F*mWII6E`XDm^vNI6kE+J|`_dza&1lB!>a0iNjohTLC7hz~IL4 zy@O!^<2@%kn5D9jp7xyPAMHS53YX6B133gH26IrnruT01gW2{Or2|hpjyT literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAX_LOTO.BGF b/CONTENT/BT/VIDEO/GEO/MAX_LOTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..3a0a0ae969f97ee2e22260a3db25292f7bc9ebb1 GIT binary patch literal 578 zcmZ?q4AXV;j519x*j!&tI&q>SAFNx1B$zcF$;xJd>R)7gAFt{;% z?_gK}vlL|6`YjRmZV4>*Aj?4x0a?EEhOfP`F+W%g<{+3DNH0hXS+9AgBis`+^>XY> zoMh}lVhWee?*n-ZCRQlzYX=e&v0t`-$*NR)&Vx$!ATf}=$YQ<>fh-_jG6FFZ5HkZY zSOCgq1=4Il45C4DAT{hj3{nG=1L*~cfz*NIofu{tD99iOmSG~{&`R%M2tamW+hh~_ w#K(Flp>=bLwteFLWp>D+y2~fhemU!MJLHgg&KO|7{hgk@FM}Y4?|`lb0J@~CN&o-= literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAX_RBTO.BGF b/CONTENT/BT/VIDEO/GEO/MAX_RBTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..685a7df98f7de415f21e5f61bf9f72429cf4cd0d GIT binary patch literal 578 zcmZ?q4AXV;j51;2Xv<_+e z&uc^M3mH@tlF#k?X{ff}KudFP!qW?O`9jRQw_jXf&wvCR9PTrkDKIiPI$URTQ{Vu} zq=gB%I5}uB8YoCJ<|bAYXJ_VFrKjc@$EQ@q7p3Lrm&E6m7x!${q}biJ?*%psu%HTEvIdtqmC6(R<55V9D|kst@d^#0#e4K@$t@Wekd z_SSzV*nz|pE}h?pEao<)Y#&VQ)w(}+2Z8E9Vj#DG)WO7j83I{AzGMVqCLm@8Vz2;| z%?hO1fEYxB7>Fa#jGFzmC3eNyvM sJLJ&fYO%G~H`KF74%O!?%j{nO#gIcr(>B|lt7WO3FM}Y4?|`lZ0Qx+%#Q*>R literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAX_RDLE.BGF b/CONTENT/BT/VIDEO/GEO/MAX_RDLE.BGF new file mode 100644 index 0000000000000000000000000000000000000000..dd86db1bc7b05d4d50fc9a8115120ff559483f13 GIT binary patch literal 2995 zcmai0YfMx}7`?j-h=O#rD1xtxFGQgtDo|kWtgBI|P|;Fj!IqVxL|srGp*$)OEGdY! zReUu~rP!5VO-yRj*w(oB5^AHBhk;c6Vbr#13}UI(ng%7(?_3!imLI*z$=*Hl&CK~` z<~ws&CT<9~C8kB1B!8o9GHpd1fNy1H(IuCFt4;( zdrcAYR71|@;({I9a$~c%N z@vZMy$M*Ybe%V#*uEC$3ywIpvoqwsG7X!4WkV54s-??nuKGR;J)FeuxH=S@Jy1&-@YSYf zRk4ng0VTS&Q91rjpq_5}+)7roZa~S3YjA1 zaB(fAJMFrb`Q>eTU*z%CKk4jy8gFG?n~Ud`_9&fs8~xdlvu!S}dBcNrUGwfUMJ}$n z-IS$kj%qJcumw-byI8=U40gNj3Imtav_RjMsJGU#4&spS74ygH(#mu3;MRw}HewC> zuT`)IA4cokCfUGRyB9KWVTn!5Tw3Jf<6YaA$`X_8Y}KJ67a#BT-c;7Q=ZqrGF?g>; z=R_?(-Y?Pnig_eZ-&-5+C>W2=+gz8*dak`OLd%ifl3|XoK@`n_zR>5s2I6=;4{=_e zub2m47cpPHe&QTXT7y$94t<^Zyay>aaI2*$Mmp{u1QTIAVJyLykSw);mJ9^Mpxu+; zMF58f?_&t48E^pJF$VgKBcL5|=<7p3J2jt}8|KHP=nMX3fyADw^b<^?}PC> z)k*t;)KW(e`?R}O9}nF2TYq1uaC%ue_s7+}!`y+*yY;xAa{RUM74fR$>)XuiwO=2P z>(e|Y>iWbyejgmC=OJ3u(~`9;f61ZYd7q_fu+F(*81w$es5)Yyl_k(aEq@3-&F~601V< zz^UiCK{Gh4b3=T*$~B|h-8GBl&es5ap*iPny~;JCFLJwF^ddJNhx5X&$Bq9N#xyAK>`@Vm!XT(8Bi|^@hE~ zRUn@GWNWZtl*z&fVT>?Cm=}O|ZelPpymK>iH%S;A+F+b$gZaWZVa|A9#4t*5XoGpe zV7aNfn12K`TtmV4?@x$Gw?qngGOq}Q< hsT4P5_K6X$+3hT32WOp7lBM8LNgxp<#2247;6Gc&8bJU6 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAX_RFOT.BGF b/CONTENT/BT/VIDEO/GEO/MAX_RFOT.BGF new file mode 100644 index 0000000000000000000000000000000000000000..241ad98b681bd187f2d7c85a77818b2fb3e8bedb GIT binary patch literal 1197 zcmZ{jUr5tY6vyv=zhAYr%x#*QYjQE!Ll8O_1rzT5xt6g&mIO0=aGJFk(^)!78jU?f z>oFgKihL^8AE7_sgGB5H(I0ye-+HOQhaQ5Umxx6BbI#=2(Q5Ev50 zpfgfl(fcV6Xg=lD#fPij-`>3>ZhVc&{-L5k4cF^(-?4Hk-YlQlm)Fh6vpgg4+}!n? z*m#b5O3&dQ6zl%fILsOvU_EyNjerl>1$cpO)?;jj?=1lCumji%IDu_I6;KQ80P28x z0CQk2jK@6q8}nn{)tmuL$!vfI=zsxi0=5IyfD3Q~9-syYvmb4|Y3WIr!#*& x9Jb-%u-654l|BbLGCBe}a%vl0eYz@imFURnYSR^@E6~jX*zQ03|DV_3&2LJIl^p;8 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAX_RITO.BGF b/CONTENT/BT/VIDEO/GEO/MAX_RITO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..29b21d0007e3b8ef9bcb8d4c2c2c638662c46cfb GIT binary patch literal 578 zcmZ?q4AXV;j51y>;2XwV7)B zC+2zE7c!_kvtP3Br=i;ZGXG`!=e=KUmoLP;TYP)qE(Rpv;BcSOOo5TX(cwCyn*s+& zCM`_B#mPa7(Lh0(F*mWII6E`XDm^vNI6kE+z9=m}za&1lB!>a0iNjohTLC7hz~IL4 zy@O!^%+gED%d&qMt7H$d9OMv?<$g7__V4WY!D286!Nfp%L1M^y^A3KpumMSu^_DfyB;QFWVoL5o|A)bJGqa2C^4f%$FgM1>{RcAZ7w$ zW*`O&K-sK7nhl6SG)NAlh8>7OYG868y&y4=I*_~*!)yZu8RWn+Oe7py=^YFK$Sz#h zlw*Hq?ovDC&^q2+YH#VJXOA4J9B16^%MJAGkwYd=B+%ZbW2v1lgCK_QfUX7rw)VD| literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MAX_ROTO.BGF b/CONTENT/BT/VIDEO/GEO/MAX_ROTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..53adbba78cfb8549a5086372d981a0c77ae7e711 GIT binary patch literal 578 zcmZ?q4AXV;j51;2X-sx)l zC+2zE7c!{ao4kDAPeZl+X=%&$FPpu@E?X0O&sP5+zK#31qL^U z?;Q*a8r7WaV3vAnW!t}tm9__oDO@_g59AP-7|cP3Q?z#bZwR+vU(IX}5(DW)76W+# z=5W_5KK5(<`0QaG19=7}rcvj!4`j#Qpk@1AmZjJ?-%+#&iGj>R7V~8YWC8h-5r~<9 zm>G&eY>)&i5VJwqATf|SkQhh~B+d@SAT~%21e_RV8z{&i2bN(X;m}I&U0FcWKm$^vEo!46}11qTp2xt_t10SP!TtTIzzWN>0wY@i^-n3PzYT4q(8 zk(iQS9-mv1!vKl5JIeONKCM7 zT=5GKH;OA9IxFKs3=8BB_#0&5g4Fjtb7y+1xUk8S-n?`Ao^#K+b9-gzM&H2DtqW1r z8nGjhc+`%zN5^7zq@}0cwycM$|FLRT`r|a*bSf&JeWbd^N0KYwRsR8xlyxn4rKP?oV_20es;K{^TVdB2xqe1nhsOA{FxOUy8!T0V< z>BY5;PsaLkV2qfw)?LJij(Dymo<39VoXesb-%q+zZnL>gQ`a%FMobzp=33&1RkDt8 z7Knf-h=DlZgB@Tes0R&T7Z}KWj{jqq)?jWS{vub5`Au7Ol`1+No0amNx1-+t?3*-x zuGq}&^q?y`54?5Owhbz8>Vv#D!;_!XVR=5yIA{ms0lUhCt>8~)PYrS+<=>&zH+ zW{{`3iEsp}WrKS-r&ge2|xCD99V? z+TYdvk;AI{g9Gg6MSnuQ*2mX%f5J10{z!bVFJq3ZU*>D(MSntF`^(uyA6Tc%SNBKW z2UD;5DDP{&;w&dey{q%DaBhP0^S2(n4~dyA=UwTxSN_#h*5_W%x~W(Due{~Fzc2cm zc}>06XIlDT_{)2hn5pX3IVx|#uRm+}WA3%O`F`p;v-GDA_ND!0U!tQ( zm-(7`F?a4ubnPF^k#)*^>0``2)Q5AO7VokDy4V^K-vkn1H{icP3)lnpf>y8(w1IZ8 z9~=M&!69%M905l`2e3gWI0lY`E^q>z1l^zq^nz31G&lqLz*%q((4YC3mwD*VdRQ0p g*nsu2ZswssFKS-c%tL=(n!EJw9~0ii)8Is>c;tRGAb zDmRUnY(maI7+IQalJLSngNcZ>wkWpDIYO5}DYVHScFud>@4NTyejohV-9GHgIiGjV z=X}54d(YXB^+IBLR_K1H$t+1VHp%r=_Zpq-S6>bfX+d4oB@Tndwj#kSvEA3icLP zrWO?CmsJ&&mX^QuYT4dW3F*NbVN1Y4==Hxkklpp-OJ};I?q4Z|qQ$x1LFjA9R6HEF z3@^^oJyS3gGiGNTtiUDJi!%^E4W+d~JdRD2tEB20WIxPB&H(K~jfi7055kV9WR)Yx zwa5^(L=<0etq7Syee~9bxQTw>Ib|0E2m}b`=+C;fbSNh1%ndImY{yab$0Uw6a0b*EI0AXj_-pJ22Orm1(VT31(nhXdXYOy%c=_e0OIz3~~0 zS3alip@1`La=?RQaXb#*jWk`Z?1&Ob>UocI@J#ibvj=uU$^MVjTmp{ii((iF-^b&0 z;d{}eeYa@+ZpSjL>s!9hKJ^S0t=F8FSkKeH`SCdP4(f8vj2=@?hec{Q z`r4^3M|>mSAEBPkmlwiZdSWk!fLjlH-(6o}?{DUXAM2E-&L8A;VJ>>SIfD-mxW13G z)m3?KK6uxqkJFi3tu!?5Qno;?!9;EY!iexgkij28HhRcLKC+Q-9wGoi9U}-4jF^ug z8~MmaKC+Q-0b(H{1QCkBekFw=$VNW0k&kTTvmm&A5v~_AJK4xbHXet3;Tn4cu9qOl zPF(VljmIJ1QbZ(T8DcrYiXc02S0JJgJP!Gy5%e44%7_?5EP`z0lM&=28~Iiu;t-D@ z9!10>$VTf`2=bAQ*2GDN;=p9tqBh)$qC!o#%?dmS-L$XN(Cwn`mRCOn(yIMGrTeK;LcGu#W8E2)aohcJ>kM>@1g4q-UPtDx91ORXGAZyS}^!=HIJG zi@Pqt7k*~AA0~57@i;zepJcVOx`dj?nP$cji6VxJw9r`tF7HG z>VQoNJuA2QhsuO2+a+O&tA%(8Hz(RkNORsqKg|ef@8KrcTj5 zQ(YzPE7U#2fLblIKJ>?(6t|6kpY@!$pYm;=3^;gQm`ksx;O8LF=)s(Nj`@}u+_n48 z)fDo9;+;#cXXnk`%1H61S@-ZJn|!b~)WRS29H{0rb}s+xq`{{KJ}vM`gStGQG_;ce z+4uxNlLk!-)a_|v;C4PakezINn&5G0a^TZMG_GX?O$THrE=>zG74SIZqsf4NBO|oa m1KIdQK|Y!uXqw9t%8b*QU(SPFmB0K5ttf~SX!2eQiVdGS(}=h@G2ym z@D2usq`ZUY^mgyu9eQ?ls=n&pp0nrN?mJWSX8YZ0cYEh$CY{uzX`Y#^lYMBJbXKNK zlI+R)cey0)`q$;K_@~wTCQD+EjzzG<(H?F2ImYrTiiP}@N#u1gpZ8488;8ICZgq=x zzGmiHBrdOP{e-|fHVmFkb-4xOE@!J%ohFX1}b85h_u$TrO zBN}d^>O+mn;ug+mm?dRaR6`$X{Jx?Z`hcLZ8^?`VQBBC=eg-`|>qE^XSz5z}Thyq* zeZ6=0Q0V)dSL&&)*?GavJyeliNbvHSSWl@@K2VO z{fcVfp*6MjK-ZY1HDmhaGTa%~zZXMI-Mh>zX4LgUurKx^XvXxt+*jn?LC)ZPACpCm z%8H&L>j5Dvs-X`xzUHWgKF|eCw5Qb2hiAw0;b^g@>5ponS=4~WEUjVfwvr{ISYi=imic1K8((L1B;Y literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MORNING/RAVFLOOR.BGF b/CONTENT/BT/VIDEO/GEO/MORNING/RAVFLOOR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..44f05bb77246b98833aa6a8b47fc2603a47b3bb4 GIT binary patch literal 807 zcmZ?q4AXV;j51TXWGrB?Dq;{|Kmyl}ZEz`MP+?%G zIsy>|(N!)`Hk5|&92|}?nJF+bI6CZMa#P>{38sZjaCLH6%VeM+#aNVBmYJ7YYz3i< zN|TauQsZ+=au|SmxZE5%n7SMsn2^i{+S6cAcg^uThP^jAm0jWi|3#0~wVRm6t0~T}eWpHExu^54v35c127$m?7#B4y! c4#c38$qB?0UhWKm#Zm*Z4mWGrB?Dq;{&U}LmBd*+O-16$*s zHGV-3g$ydELRRhv3B8@?a6l(@qdkayWtN=-0}^mx$TCx4WN>0gHc${^OiC#e&0|(Z5`vY$y%kIXLWKG*e(?aCF$f=%&B{RpRR8u#nL}fsZk%B(1`#IJ+`Fwasi1!?ST6eB-Z*`9cV8CfXqV``*j2)7I7*F z=nuGgM?iX^V!$v2fnP^JZia|KL_lI7zoCjTFo47$cEI8R5>_BFUj|1OkZxc=GB5!# mGZ2FWSb>-gh}nS{6dRmC%mu{UK+FTgygUzu?H!I0SAZWjAjaq3{DR784VP~7?VoU zDy))JfmC{3@R)PK)@tf!6nEs+{ZCE zM1jH0A&Rky;RwiVm|evgf_5GctAKVkKrur@(!#|DL2g2q1G(`w*P(+iPk3RIJAhB_ z%-w$nzgk*i=mWV06b3a#1{iW6`*7)VXP5xe$_T_vAO;XH12KpX0xUob;)4Jy5QF$2 ozy`!1J_vyHf%qT*V#D-;Xqa9Q4buyvVR}I{OfQHA=?97d0HA7k%>V!Z literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLB_LP.BGF b/CONTENT/BT/VIDEO/GEO/MSLB_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..30bb5dcc01ee1c993b351e63bc7b15bcd5948dc1 GIT binary patch literal 1102 zcmZ9LZAep57{|}<-OR$~s=-2#-Eb)^TqA0vTkY;P)-DUh5TRf>Wy+-G%b2B&qN2W7 zXhh(M7}1MCeTW?Op)l6&qE9h5g)x-U)-Vwf$3d+vSC^MB5@i!HT+ zczh3w)C|Wkr7XuPSdW}z)Y^@lOxBC)14vcU#!8vW%LnC-tJ2#ipAPjQ-G|i)sqH0e zsnu5}yyhigQOQ`HJ2C?L=i&Kf*2Kw>fYy!NR#|(nbD-Ye73>)7@VA}{`Vn?cloQch zi@_kJpXDt*fjS9)K)HD@aJaz=eC4qb*!tB3d|=1~>`PgIPkY>Pd;C<%cw^^x)u;0vrQs;8d5 zA1NpPh~@?its4wLKgvnR1>mruxyXkN^8c9lLOt=6pKo(ReMn8NS^jz}aAieW!1I<} z(g7=SE@0<;CXSc3uss^X-n?E7UR<$(ADfv4-`gsCjs2J5M&O3N7Ea?_C+$7yd0UM@Gm#qh@l6ydko`#M4(+?E9z4euj(zsNc6%3wi&(f1bx) zlO_ASQ!x#GR7>(~Iyq^>o-*}OJ;|SX%Gu%1@cv>o$t!d-2TXrkYo;4mQ!2pxRVoqs eU;Bn2AKynW_^Dqc-xsPHIKS349>e)55c&fLKy+9D literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLG_FR.BGF b/CONTENT/BT/VIDEO/GEO/MSLG_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ae039074a42702211e80756d2c3120b4e69adc1e GIT binary patch literal 1746 zcmb7^Ur19?9LLYy+?uI5b;~~)UPQF8(6kJs?m4^GQfehuMj`ljQ*-IsmL^6@PooDP zda@8y2q7avf-n=6dJ%MBMehaCUke{9Fv9x%?so33n=fAYa_>Hz@9%fc`Tc%7R#m%S zuDVpBCl;Nk)0y<5KHJa`C+aMgcu^2Mq})r)M0tkTIsZ@TRn}|yD#-&f52Bv>e{=9= zgqUr?r6cf;JdAZ2%S3_LNTXdeA@4i*NS4XjVlho<^1H5=Uv~PN+>Om0^;i6Ef=lhB zY=Gnimrl*zySwlL-je2f7JnnhP$x(tz66jCWMg_GB*6stS3g$BtW8%eS|N+4%iZWL z@A7uG`uuL5$7E-fx&V78OEj%6}DPDcC~%|AmJGRQ)a zO=NA6 z3kiF9UWkY7utMJyO-kXs5&a0k--;0AZ#=+UtHqpa3 z0t3hh+6KbTj0bH8C4jK6l0Z8^$slb16i_NC4P*gXK|4X|AejV;#dNjRI=k9^PVBcx zvys*Ssn)ht-ycRlytOK=#@hv1^|*CI3w5v6N}Tc5K!#oiNr^d{%pMBGVurdGpWoZ= zar%1QJ(10@fDm8|=Z1ll0lrq7Ah9Gn-roG?Y(QDppi8Ev^~2CH=#62Dcj|EwTedxu zhDK+VYGAxrHlVPDU?sIIIx!x2H!?nP$m@3frc=u^l6I1Y6U(Ug{N#q~S}!!P+qpJn zTKTo!cv{1Zsi6txS2(p)!(96a(@vaSHZapso5FCn-(OJ=8` zT-j>5x}9z9&2DE&i?^fI+p8&Afe;|8uq%c;!`u9{yFePr84On2mGjaOlOT{s@FP<1eG#2b@CS%>lJ9#qibxgth1l|?pkF@OvdiZ}H| SU|NP=WaxE}16#gfnCt(~f9s_H literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLG_LP.BGF b/CONTENT/BT/VIDEO/GEO/MSLG_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..dfe2773ae726d392cc7e871a91fed8bea0a753c9 GIT binary patch literal 344 zcmZ?q4AXV;j51>;O^<0}c$|%oG?IoEZEK6oeR)O42H< zaxzO&i&9hKb4zj247zi0`w3?%QwV2#s6a|KQX zCm&BgZv_RQ>B6220)OH!S|U5oi6I_EcV%i0l6#yz8639WF}2S)&FC;wtHB;*AFrhG eeq_E=>>azh$Gna^)^~&DSADs?51G%(zyJUVj%9WL literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLH_FR.BGF b/CONTENT/BT/VIDEO/GEO/MSLH_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..56ccf1c6fc0340ad62395fee9b0cfcba9125100b GIT binary patch literal 1595 zcmah}T}YEr7(V;vmRh#0`2&Wr3ro<%*~DtZ&e;~GVO=O_8In%6{8>|%5Cw%rgv5w0 zBG5}Q$gt?5i$>{OKU6ZiF<}Ua7g0A|7sn_aH6WrLqs4R}4Q$8NLed_$dKf2h;x3-+DAI22^mm|e$CkFaC& ziN=|+(GRcbbTwUDcR{G(W;C1&eWrUDw-u82 zK!30^?Ck0fb%p&y{>%d6j4~otbWfA(vl}-eYp0jLH&v_S!J+1>G>V**UF9sbgDMxR zFp9Iic^q|cWY4NnX7mdg3wdWTjk4t_4@eNhv%Li#oqFwtJ^P&qko(#ph> zag%o5?Ax{o$1Ym!X!$VTs%OJHxx1t8#{rroz zPoS^9yFzGv!*_~>?2{gvc|zXfAAQ<+>F<~EmB}*4gXc=co1Znb3zCP&96$1V#3gK6Z)`Lb!*6RoF%`SJ&&t_)BcD%1 zRLoZ)`{NYvxR+41(pPfmdpMoq=z}&|ys;lRIS(BAlB*GwgKuEXn&zOD z9CnuT;BntlrruZ1lbqHU-|E-*=1qN))B55&KYMp_ldt5ozPRJ3<@QbUB!_vYSp2`~ zLo(5X^x>ZjY22DZa7ZN5h?-0$lDb_wkyzA_SR@yTMRK=GEs~5Hl8i(n$w)Nq^#>Cg B^h*E$ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLH_LP.BGF b/CONTENT/BT/VIDEO/GEO/MSLH_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..b845cfe41f9e3fa4453eed624c7f72ec2b247701 GIT binary patch literal 205 zcmZ?q4AXV;j51^Ad)e#+urvb_aA3$bQ($CpVn{Ji5NAv(Dag-BEV4=}$}CCE q0pj@Fk{kw*0uKgfPX-5M6G4W6_zpMO;HIM60^;*9nZxB-85jV>eJ^JK literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLRD_FR.BGF b/CONTENT/BT/VIDEO/GEO/MSLRD_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..1efaca42477c64ff61fa2fa30bccbc692bc2f44b GIT binary patch literal 1333 zcmaKsZAepL6vxlzd`k&Uu~i0F(jZNkZTP{L-RI6X6m2>sqKK(;lXAH=7uknO{SXRb z(U){zBox7rGEhtj*&P%@T45AaL{T9H77}DoCY^Jycbf`6aJbL?aqc<)bI$YJ;_?&O zrt(wAA|P4KsnszNTtsSQy@pdKC&zLsl^gOrkN~(0`Zysj$}iTMKbS5+Ishjw%vT!m z89)}*l%XH6aF&uJqQLP@tmf(KLYakf$Sf4k_pOF0P0;IY z0_Eiv&BhJJ!r9S{CMbF7TVm9NC=?WpM)QwFtAc%mHZ_Ji6^Uko>G1xvc|B*{_O{E; zOJT#h-3{#k9a4Yv`qaSEcMp4!--m-!m?(aA?dSW4x)?I7yAp>bijPkoVa_YlVJtOZ zc{Rh>>N>wLpDOv$0I%MgV9y&N`0>3w>&*n8c;Uu)URPc;rQ-$19(cae!ble^iO z+5*0$Yz$eC@H?tntmxRoK0T29@LSpM&9fq&{01`XBu2jtx2cnd&!hZuO`Q~PRtMtR zfptFf$>_Ft?aLXPdhz9FA)ENuCiPM2SyA@80%BV=e|($4%0LUals^aEOxn|`f;0`i ND+iMJ)&qAaoKcRV%m!)7Gks*jU!AJlfjfR%wjZH11tuElg%w)f#ZXF6vpIOPjQ)g zF1D<{O-GmZkVkW1GAB0e!&uISX=1K&&w>B`&xd^ zmh~G7USG4RFpr^N!~!~IE~A|z80(AU&tYtjdcj#kU3V*pu~p*P+?B+X4smwfokCrI z)~;u{b77HuzW0_er)?u2 zFP0`>`Udm$JC}#MTKC^EA8!tSuFG?@-hYUTw{f?$=R4G?dR@FNRDDUfDK}1Hzl^ny zJ*!-C70|=RW?EhB67Kl=kCd*|LQ47PbxP{WLYA?|DFv#dH<$v>9i~~OIl`Gw=c|$P zgQ%+f2(?yqH1V~ZjQL1Oo4uDV^jxRiX^L=nzG_gu3M{8rK5eE$?w@SDZg^$BI@5lQ z3dv`J`Iiq9-AU(bk%rxEQ7q$1X_8AL>n(@RwI%HsIsN6*r z$-XRiJj>k=(V1c`W7B0NeAzzQcCOv$CZ69cT;!wMp>In^+4+7QoBix)&i)<+v6#t8S9 zR+Ihs$tLnE=^)2n0`9sRzwu?c<5})5 z4*Ni4Z*BKivRewNJnIU%5>E(se0Y%ZY4{epTydFl@{4hna%}WxCVO|5KRuVzOW)lr z67JMSKl}dB0Q!;oNSby@WXFywP#QdWWO;Dg=W1V1Qvc|le)+p_8bw1aguz859RJeP7A74vs8ZJs;Fl4IAoiJ!?#uq?>I`1gfKX#*U<>A+kJ$x zSN>J%2;%*hV|%XqYqKK{(LCjIiHQsSlY_PJjsw)%bWD26^EVH#+q5xAb5y@e4-#up zXYsC2o}f9*d&oK=T{0y`3-_icTyvb>MSnEqqfY<5&?JqYQTs)!R5s;9QP-I~QL9_v zq(1jT)P;I`B~R9@^$BG9GE&-D=XEV57A+z!f%Yzmm6%-Pt)pq$oXBfZ%?^`v@t)U> zw@uX^&buo8uR9F$jnmh+Q;n$KgY(#rz4nRk3zK)^@6p?X9XlgjNpUVEHHV3;JN1lO zeRdCR8Iy}_vp0*sBjFu;(bMJhY=cqM{VU}Y^{usU(Xy(gsIz$cEZ{p{|;a zR#c!)?}0p8^dNiXRk%9ud~go)8T?KMIINF5zP@BSW*EkB8GsR(02jl7AMgiHfYD$K z2n0`pAP@{fz*rCp!oWB%9y|rY!P8&@cm_-a7BC4+22;RP5CNuvXTftI68r*0f#<=C zU?!LaUIO#Ld=LZhg<{w(BY{^WNxX0^`k6#80beDkpDC@>xT63hTEfM{R^v%#;x955FovuM9e+}DENf^}d$$O0QcHpl_FU?a!_IRF0x D5vzCn literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLR_FR.BGF b/CONTENT/BT/VIDEO/GEO/MSLR_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..6066cd85e60353a0035b6bca46124277140b164f GIT binary patch literal 1235 zcmY+ET}TvB6vyxGthJhH>85F#Q)+ICrA9t1!<{p0tXh5qk(30rE?c1MCoB2jgQ7@`udnvHa8JXqoz>hogzjHqB|K6EHwN0ho z+U5#{x$LUl?o?DIC*h1kwYyx2s?FBLJUwg+GcTt>!<&iE-fmWqdSz13BaH}7jTq}A zsp}U&m!nd(F@yPis*|*-w8K?icC1WIx3z@N_IX-^;g*m;&~~~#9AfmUk5vw^g10ku zky{hfFLC73eT1G#r&QG}nFbqTM+|T{um}~HT>f6=h2Kh*PoT3S&=U*? ztwK&8d{9O}RZ=1|K)w44&x@wge|l1AjiVN|v~!t5rbhFm(cEJ2K3_R8rb`--*7hV3 zq*#Mu`)?j3&8lHg4bm{y^o-`N^_Bp|N?MdOs$qHhtfPI;<)YEWHzBYNa zkIUNgUme;|bTH26kIE}vtq#cfqRZ`WAWe!DqdEY^(%PwK>eJFB|6;L{238Fz*06e! z{1aldMtj;kCi^GcKj(Ss($ToRyuDfsx_?oDT2Lv zBb^s>Kgh>ZnD6erVP4O!JIKETWCOAhp-(vxNkTRu^dW9WQjk=H{uf)3G$b8yA={7) xBoo<=WFgte4kQQ3MRp>2h>Gk&b|d*n0aA$UL5h%imPM_^zI_GnsY&V)`44UCYaRdq literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSLR_LP.BGF b/CONTENT/BT/VIDEO/GEO/MSLR_LP.BGF new file mode 100644 index 0000000000000000000000000000000000000000..6d2037399aa3b1bea1666602dabe2f7722c143f4 GIT binary patch literal 443 zcmZ?q4AXV;j51^xkWGrB?Dq;{&*tuZ;Dye0T3_!5> z{(Hwl1{D>J4F}H~N;ohG&N&Fgj=j@moIo^42@E(mL@=5uFfuqXBpN7)Fea6xRahkz zWtODo0C9Y7Ne%-@)`P*>lfeOIp18*%2ax_dZZpB=A6#L75X3*!X732H?^o_jFh6_N zOfY{UzdhJaCkAf=1tEwXAmfWtQ{Xn3D{v|}`FQ$yD<}YMQ}$#~xEarOpm(~UQ~n1L zuxb7dpY1_Ds5%beJ2A{hF|9H+2X2}NL$fDC1IXX+YKk4@y7~`*+y~?Dl$_`Q;)29M l@~|)gi6iqt;!yoy^)NnA-2te6n0l}aLE=#TU_L7Y0{}=sd*A>7 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MSL_FR.BGF b/CONTENT/BT/VIDEO/GEO/MSL_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..373677410dd13497f713b307222c900015041582 GIT binary patch literal 707 zcmY*Xu}T9$5S_hCVxkrbw!#)FSO~#FB*qr8#a?64FRc zW~2}e$~9?(*vj`e3VyBj?i|v@$JMvL_3&)LGpv){DH|RVZAw*)IVs4dc0r~?w&yss zla-^Q+H#wf3uQk64&4(CQg2yuK{^7w1op?5*X@o#bDp`iJ?tt6S6ZD38N| zM;>eNh+#N<7~$IqCc(wT^xe2Vs_#P`)$bzK7m7HvPQb_Ynvc(;dm;xObs}9bOT-5c z7V$w{&FeY2PM=3Enx}tG-6xvoA77*_w&4D7^ClK-h!YH~5hIT^;uW$JN%kqm00X~B XhB3$hhujbYPYMn>XrKj$9BcjnKKh@l literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/MUZFLASH.BGF b/CONTENT/BT/VIDEO/GEO/MUZFLASH.BGF new file mode 100644 index 0000000000000000000000000000000000000000..83d4a90034eb49793b36bd7bd4282eed569ed9af GIT binary patch literal 814 zcmZ?q4AXV;j51~oE0SAZEOlAs<3{DK!4HSeKlS&$J>#=CJbL3^kk)OVYwh*#rq~~}RJK3v9d7Sh z|HH0teW5+fSfF+Lg_;l8{aIOPE3JRmCXA2QKBoMp{avSx_NY#1uou6XXJ33>$-eb< zq5WH+IS@5qyTDGJ__oG=Pf4-8=37~Nfrv=3U7y#!w0CDv0a?cg#7scU3}pi;Fdrli z5_58x!HDd&{L&I+uQ^mPb}{?`1rJCg&~5uFU#8g$H8a>xmSC~_usqE^qV$^G+;0+a zzk!0&a!Uu;Z$ixuwr9`u*sUp=Y!6aX=0DFC6yzXtbT`@B`z1}VE6$i`>+!J4?sLgC zJMD~FwxDSFk|PFIv+Z-NebA13c2_H2+M32m+2;b){M*`N2UP=#u6@?`{p}SuY_cog zH{aH6+h;qF8mmd!FuTBNEVpRbyL9J(?ea?!0NW)L&<}SrB+MJ^KV8ZNiZy`4`rQQu zu)o|HDnMR`g(D~|VPOXgQx>2Y2!q5~p%}!50X855CJti5)PvX{Ge8)`2AK`QAT|g% zG58rM2trd`W^rm>IxNjGcrX}yG8jOVK}d)nAnYA-tibT|K}yOE`}z-kwE;Q;0L^vk AegFUf literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/NBEAM.BGF b/CONTENT/BT/VIDEO/GEO/NBEAM.BGF new file mode 100644 index 0000000000000000000000000000000000000000..81a156b1807a686e202d740f9994f81b08ca7695 GIT binary patch literal 4176 zcmc&$e@vBS6#gz;1^fXQ1Qfl(1t~Oy$c!0u?{@-mp=ictIjRK==wg_O%n)k=>jy)F z%1z@Yn~?JlMwUjKB-}8r1``l#ZBcBQGeQ?XN}&z@uyeTI`+eWt`vQMk4s6<+Tbk(ds)1^e7!B+%NArCEncR_{VWE<8&XoSWRj$Et2FZ|a~Y(v z&HJTj{GT)K!plxcnsQ;d=f0dhTM{Z z(xlw{oV{<_3rq4}*;`U1A$!pl*zQvet_8h4J?%5KI)0%JvK}q2KIp1RlU0seg$HNF zfeGl39JclLWLRH#@jMPNqtt`b6Eg`#6@FMp;Rt%!4_$|h2U(2ME(th6rassmo}h6A zy$(9>!#K2~9%ZibOWa(~g?7QN_l|0F33|1-MwQv;(mbZuY?TDPjMuv0gzbc;S-@$| z`5w%DUxt2yUS@G|!$tM?_9adTC*I^ZqeBz8Xdj`1Ap>z~4C z>9dT3?=;UDGCE-DWHfTvyOGTG$_TYXeCNBY4&Euxxp1Tq?1w*OoOTh%_;~>gh8)y- zNmHHr?-o73)4CGp`bKwOd@s_|pT9|WUp$BOJoT$LJ7@Y1a=q?GnIZemZN|a#;W@A~ z42HTtn^$v0501P4>~3eWw=J!$g4hrWg zy|)-V=i=+MWtGV_wR`04P+>4q+JNvvcq1sV06{VOP>gaEqufG-4}unkA7T+=F@j>0 zqZs8VM!6-3r3imS00P&Q6o{Z0{?5ci{)*i+;L*WRv zn=A2OSkknP-X6sV@Y{C1vXNDeV4HN|W*@}OuJm$>^ei;=!kLKxjU&*r=Zkw_`t1;D zanB|Ag`XbihVjg^tj;X6k1Mk)a|tz%Dw-9JpjV!<+10rOoW{(nP<0@O>6vBr5&i5o z(RQng?Szgs;jE5LwEd?C?m)-3Iy|4bG`lyl$`Nc*gWbK^)wu*5IP)#EmDVvmPLZC* z%pv{kvugIZFF`Mw{bt~G?4`^l;E?7WX)PK@a2I)@!!u4yeSZX7`-!(t!Rdy5S{(tW zUU3NO`3N|J6Q95{`;6N82sG0f-n_C+_dfI6wxRwtxLkW$(<5*Q#fpni^$0j)HF=OU zvWw}#p8Vz-fN;pI57Ib-I;6)aSL)s|UNh+-7opylpjVUPMpVrLPV9!|@WI!|H9Z0j zX+FQBTRR^ChkB8V(A|3{YNNkV5!uxsr>@G=)#0~)r{W?s%{=Ey({Xw7#^3BtouYH5 zx$MoWwKK$mdM)&P^!K}o?il-h<~h+n=2$=Oaj?0t7q2JxCqK~X!Ja(FblU{(*=O%n z=l{O!*^Adxcx%5rSg>`@GrXlZADj)fu#a{RG;^|YFaN94V6K6=1?Dtp%QL5;cLo$= z4uG5nxdqzxkSkzyC`ZnK{>FmPy9bIf iM?pDq59B6TjGV+e#3P7U#Ck*=A|638dVUmv4(>nYHS?MP literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/NIGHT/DSKY.BGF b/CONTENT/BT/VIDEO/GEO/NIGHT/DSKY.BGF new file mode 100644 index 0000000000000000000000000000000000000000..34bc3a7dea71f39b3fe3c34d46ab4b4197b6be20 GIT binary patch literal 2177 zcma)-y;2lG6ov21tn7da{;c>9t%8b*QU(SPFmB0K5ttf~SX!2eQiVdGS(}=h@G2ym z@D2usq`ZUY^mgyu9eQ?ls=n&pp0nrN?mJWSX8YZ0cYEh$CY{uzX`Y#^lYMBJbXKNK zlI+R)cey0)`q$;K_@~wTCQD+EjzzG<(H?F2ImYrTiiP}@N#u1gpZ8488;8ICZgq=x zzGmiHBrdOP{e-|fHVmFkb-4xOE@!J%ohFX1}b85h_u$TrO zBN}d^>O+mn;ug+mm?dRaR6`$X{Jx?Z`hcLZ8^?`VQBBC=eg-`|>qE^XSz5z}Thyq* zeZ6=0Q0V)dSL&&)*?GavJyeliNbvHSSWl@@K2VO z{fcVfp*6MjK-ZY1HDmhaGTa%~zZXMI-Mh>zX4LgUurKx^XvXxt+*jn?LC)ZPACpCm z%8H&L>j5Dvs-X`xzUHWgKF|eCw5Qb2hiAw0;b^g@>5ponS=4~WEUjVfwvr{ISYi=imic1K8((L1B;Y literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/NIGHT/SKY.BGF b/CONTENT/BT/VIDEO/GEO/NIGHT/SKY.BGF new file mode 100644 index 0000000000000000000000000000000000000000..73d1df74881440037fc41cf64168c0bfa6d9014c GIT binary patch literal 1660 zcmZ8h4NO~A6nm^eHr&8vxTWG2e%^h=Ce|?lDo*LRC6{1MUHw+V$FHfh zT(GXiPiPq2%j=)_5OhvnD)U4z;a>JsaSlJF($_gkF5-}KM)a!OOO#ctDTyvB&MYk2 z_d#CqNse*xN-9cF_KTQDcDWy);pa@5h34QQVK~0Di!fY!em~%b!)}nn((WQ8x<;YZ z2Wi0TrDCBXcMDn5OX0jM{Tw~MPmN5Ut^l^UyQ(hwY#`aiwa__Rx%3_QN$+-$mc4%Dhh08^k+S8f8AmwGxXL!;N|E%$v#M^NTj<~Y521$CSK7(Z zlmkeyVFnNNT0LbmkCbfpNU`B2FszBI1YVc)obcNz87fbnhi6p(Ith9c-%nW&QnIfO zFujy_hZ)Lt-XY_GF5rVgExhzt1U83zzzq1!d15*0fg7wH;IDAw1Vz$0YzfpueXFmB z6VpgH4!E-b=S?Hiq(yoWn z@hZTFmLdiQqNi}A_x3xZZmgkOv=6IuwtH%7qQb@st2C?>l*dU;K-93CD1RVR6aGM zNQW5(+h!ye$vmdW?c!mis1gYC9McEWg{4Gf|F+q8&wAXKc6*TVimEzNHrt7+gEk?j zHq44kJN@BaV0`s4iRyIE8SHwd32K;Z71P|mgRn;G3Ny;`ypLuJzDLrw?U{szs7QKm zGj8&I1o_p1P&vh~n=`!37p+m^((Ah5H4#`f>L6JvW9+hST4V|#XnEw*PoJI{FbV?Io0i~kQYr#i#{ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/NIGHT/SPOT.BGF b/CONTENT/BT/VIDEO/GEO/NIGHT/SPOT.BGF new file mode 100644 index 0000000000000000000000000000000000000000..133beed942f3d6807b3e72a950a8bc89b1a8e73c GIT binary patch literal 522 zcmZ?q4AXV;j51Uzu?H!I0SAZWjAjaq3{DR784VP~7?VoU zDy))JfmC{3@R)PK)@tb!6nEs+{ZCE zM1jH0A&Rky;RwiVm|e=Zf7*IHtODBE0L2UqNedSr1i1-a4&=t$T!#+6JmG~+?f^cy zGk5g4_#gn%2jYVOhz-*VqG5VLG)ymuhUo>-Fufoeq#q~-0K=GoAOHXW literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/NTR.BGF b/CONTENT/BT/VIDEO/GEO/NTR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ebf8e34814414c77ccb77ec840b64f1b4ff5fdc3 GIT binary patch literal 254 zcmZ?q4AXV;j51ONeWGrB?Dq;{|0D@UFXWD^i1Ggl{ zLIxEE28DwVA%%lLwj-472vPzA4h(b56c`yC8K$}^a6klqxi~Sj8z_h|CY2QsM)tUx-poz$0Kxcr&Kp5F+AbT6^eHjE< RKrBWeW&&bnAZBG?006=gF1P>y literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWNDCAM.BGF b/CONTENT/BT/VIDEO/GEO/OWNDCAM.BGF new file mode 100644 index 0000000000000000000000000000000000000000..cc34451330d6b62376546eeed701a575a038eff7 GIT binary patch literal 2132 zcmcJQ4NOy46vyv-MSxLO6=*`1*yJS5 zum5x2?f<-Uk2NcIfs(bxY(OSn;Q45SV3^6TixPOF5G!!p29)7NM!B|@mRvg?Fp+t* zu`!NpM04I+z;|4FWa#h?-J`!2efLXW)Jg2GoQhG{N0#qLrwSZO6O4kzYR$^Y%FVQA zue7cfkVVeqmI^T-t~>R!MUhjv_k~2xv&CKEDs^WRJKSQC*H!G@YA@PmuW)?qEi5T3 zEiS3Fmsggd2N`uIxZh`&{ClAz)zD>-{S0 z(pbxH2p?SXxu3C`wj9D3%LN9xB;_OOdE2nKp}wB_?I}boCmI8tD7I+~bWo2mmJ5vK z0)t!|ijM+^I5l`R3~B(FpvFWsqSdg-4loi-tUHyiD01#7Bg-8{<1{j|GP03D)krw} zWZp$pBPksI=JxlbpPKFk7&{!BsWbTFPUkraEZhuW;by!v*UuQ#V=O#(@VN=I=UzU) z7lV#5&;hd{OGG2VT=+0U!CVl7**fi`A}%x z=2luDoDQ7X9i%Nk#FHs4|4J8(L2BwgD>dyrM!){vNcJ^s#yz3mb(WnPr!ik)lb)NC zmZ;^9tXI?bB^jv$c3rBcd5Z>VLRk-O-S#fYzEw!N)}GKAe?LKEFXAPg{o%SW~ z(tH#CYkwy_+m=rLX>KOHWRA{iC9JU-e^1wQ>xPJyYeUHqJI6W(w@9oSZ>TXzjhCH* zE*%LumyFe^$S?ZHyCt$R;z$g4Drrv~Ef3zHeFx0`6F+w0kT{Dx8Azf|UmYEIlllvS zo%qkE$z)>9HG1plOj>1HNC&QbfnyNXSl*(OIy*NlQD?Jv^=mrDAeS-7g;`{*t*TF} z2Mp?g4j9X2&+ra)kfWdFy>b>{LAOU|kXv%FTW72uFv$IXo$7{}f-X68jaEfItw%?9!k;ZO}CrWD-VN4XS(m@-qu}jW&>PmV@S-lU%YQk8) z@+mdneun_t|1CdC$5_q0GybH~6io-`>#u0n>jhuzB8<9Jyp*%HU3fdk`iK0=|b&928;qsH*)BeP$QX literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWNDLMSL.BGF b/CONTENT/BT/VIDEO/GEO/OWNDLMSL.BGF new file mode 100644 index 0000000000000000000000000000000000000000..e1ea98d63c95dcbf912da7982e030b9051137e32 GIT binary patch literal 2926 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 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWN_LANT.BGF b/CONTENT/BT/VIDEO/GEO/OWN_LANT.BGF new file mode 100644 index 0000000000000000000000000000000000000000..0dad0d0741a6d8e0af8d49c6bfc91310a66184e2 GIT binary patch literal 611 zcmZ?q4AXV;j51iH1x5x(hTm=q93YA2 z13Mg@7~UEvC^F`k=M`sX=2@ku=9whMr&Prkr6v}YmgE-|=f~%ki_L%*4$S!KR&IT6)x$NuCMfNX0I@>QUsk8^_J;9#p z@T7T}eQubm{iVMZ_AtHAWz}u}{Nse{y%v@N_SMH-ZuX4r752UihAbd|Faj|X5HkZY gSOCgq1=1inkQj&!QUmcl$mdHwq&bZ=-vdJd04k}xw*UYD literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWN_LBTO.BGF b/CONTENT/BT/VIDEO/GEO/OWN_LBTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..937c21246b9b69219aa43b2b17cb972e83bb0df1 GIT binary patch literal 3116 zcmcImZ%ou>9DnW(6h-hv3k=d9id1vVix)8u?)MxQgWY_gRkbHZth8ezt%Hm8 zi#{3q*hvK_@?j7 zr{$rbFU4o&x*|K;J6c=X{oA&-Kiu%t%MESKk;wLjXScU02}&!m(k+sfstn%nM1z*6 z@64C+Z`b}D$SM3Lw(|EHJ^D^t036c4+A+^Q*tJO?86S4I%g6qTogaT&`>K2N=Gw6` ztizFU%q`wt?HS1`C5LNN-K8Fu!iO#9Ra!}jY_ z6E?VtmPkCa_K=?3b;aSB19{yeza?V7FWMLHZXDEWR!t{jvp=aTo7r6*yL9C--8Nku zz@;%tq+*7K{M9AftmbSF6G{peJeK3ASmW}Z)tZPFhWbUV6Gzsa=+5_e-M z&rZI1%lVMkeW8EW`3_$==y2(kpWEDz^#I5Hs3|#9dvMg5H3FAhOEVVw9d25#(Q>AK zSv5rtM-8AoI5P)o$yl>)T*thqZ}eu4W6wH=Y`I^ z8~XtD;F+m2>V~_8)vlCOnX`F<`2q~x0s%ODUMTPimI$&0O9fa94xbUTTyUQtSCDrT z_Ag=k5*kK{3!?H?Gcxu7G~el*Khp6Nc_@pPSC zyram@Klz^h!@z_M&T85l->_&<*ZuKJf-C%~FW{>wjGgz_>WOO`16=oYWGc4jvl>0N zKBtr%V&CfRPH@bzZmM3dw)fw$;c-9YSU1`~>ny2lhaAovSn9{Jn!1oP^#hlzv&qqT z%vc)UqsKe7snym6LQ`_d`kCvfi@6{5BWLQ2v#?)iP*}$t&;@yUW@tb&GWUa~ zSQl1DZ`~`@D?%_ P9Ad$R)sk65Dns`VFZGBB literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWN_LFTO.BGF b/CONTENT/BT/VIDEO/GEO/OWN_LFTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..1e623803d5379c83e70ae4a594ca06e075f5fcc9 GIT binary patch literal 3116 zcmbtWe`r-@82;`r-H+6Hx3#UgbxhstkHs2u!S3$)&b=%}am*!HtzfR&Y&myZuH2j( z)|4%xnkcAKYN1#dhC$KV*u5cz6%iCHA&6N-W`Pa=iO{h3IqW%n&OlZd9ymPr{l51- z&-=a4cWT#fDT}XftO%$azvcHY3|N6e|JI=8&$7}jpYK^!{hZ2j_I@-my5i%BRSODI zc_pWHr&{?!XK$+Fm)DZ9m&Q}iAMDn-MK9ZlnfYYo+0zfltO_ zai=_3ZWa0xyE=AmZ|kVu*3xl*(^I>f+FKKeuBIJb?MfDgd#w&kgd^loUh~C}#~tXuHW?l`o7ymzrW@-& zuR$D2KbRj(4y>ut$G$q@?#H<1?BZz8*}rXbzlSR?)qwl;nch@eVmR5G^Iq!ht*fJh z(^D>Yxui3BJ^$U*gPChw&dhPKwZZ1vuTL+r$G4{^Z@j+oac zQRHA;PN+&3w)D9ib4nK_`c9|#2)bC@V?kjy|TxR8!P_I=6>u4xVf5wqo&jz9FGutM9%D`xgYc!da^*{ z$Wa&Q7v5Ora?}OdgERA@mq%yUntfv&Ye9b*M_t$tXQ=Z-YLq7#PH^V0Ha$5#>`gP&1o!HcUz^iX z@>8Gw;}PX?=q$LN?!z`usOu~p_3nP=3AnI7;>MA~w1C5YT#LNTvKD#k)N+V(i&~J7 zU5q(xK`~I6=gFDYc-(nBFnb5$YfoyT^!4P` zZ_lKD=({)idDOqT#h+@>rL0C;l&Z=y>O!3-g#fl- zOl7XA!OUPhh=r-abil#z{=eBk1saQavU)=O`ttD`-f6>xfQubJ?3og}Nux4548wqV zQB|zn_e8{9OAbndLk_M*E%P&*Y`>TdjHY!1+;BXzA z`(Z-C;i54=HTdaAS@;QS=Af&XYgr#TP9AIFewaq&UFTk|-aTV}9pDb)EzNs}!w1Rn HpYZ0f z-}AodnYr<{%neVNq}fKUy_-vt9WQTpI9)|gH>}^A-P&!$6K)kZXo7=a9GEhN8%~$O@})2!p)xYXEpA- z6N&sl%7@Kr^{d)CkmoNLaEEKRaPCVvWfZeiKF5RBY|V!3So_W_4pK5hzNO~uGfnf{Q(142n*bPrAD_7%mtWTx_*b) zAUq*B2oP-{Jctkh5uzT$SRe-&+7GaRV1c3iAPX}KU}%T4n8^Zv!0;RTn#Cf51^PrA zIC6m@AK$sk8f}vViCn+Hj9T@%(>kLHkZY`+ZfvOS=f|KhQQ)U39fh^Gc-t} z*jsVVS<#7y}kuqQ-#jytROH1qLoKj3IQ0G0t3%(`jze z!8mIB;WeFxfsJ3(>%X=+nr`+-^V$(LQREJp!bCj*J9%RluN{Gb3(PL9z?T1~Aqg#r zGfz`mLzrX3tv?zqwAqv$#=tEP(y!8u4N9xQ-#qw}*OLwyHmNZ70W!Z1Pl9kte*Al6S32eYCla&Pp0Ky3#x4YvIEh7rut` zN{(!%y2LDXVEtk$tgGjk7^Cq6_Y~$iVqt#uD<608m!*8%d9fz-aDp~Q#nA-L6?x$H zc13ZlZ^)v~`STe*1~B+8yjU*K`h$;S&g0J|sg$Di*S|-*q;h_?s0%mLt5<%q5XKdL zKbWgw;tqgjaVsNFtnF%eGv#S{w^s9jN~_j-hh+7NRIW(U%g zF$41?_)%eQMEdNbJ{z+vDjb}15{fzRfD0F-`X5&!@I literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWN_RANT.BGF b/CONTENT/BT/VIDEO/GEO/OWN_RANT.BGF new file mode 100644 index 0000000000000000000000000000000000000000..e9dc4cee9a4895ba1d79b8b154509bc357923626 GIT binary patch literal 611 zcmZ?q4AXV;j51Q^-~dT9 zAK2mO#PHTYL6I@PJg+!AGtVkLHP0k5KBX$YC^fODv?RZ%I6pqOB!>a0k;7a;KmkQY zfx(SoeFsAY%=YUh@2xGeIqcbE_S=EPPOzssJZWBLpBv_Cf9Y?9Ja zaY-du4CeBd>ug}XAax+I=d$XyfBtd8#jb^=fPM9GmzzCfdxgC(gCPsZAB;fE1jNih i3=&`kVvraJfW$y@ATf{}#P=YdFZqz>G}3$z3Qg|W8N zW|p|nur-Z7H&?UT`k-^<2L+}6>4Va2{;91D8*4Q;X|DTv=k@LhS!Rpv+FmZ6`?;Uz zy6^jXD6eWN3Ri6^_Nk>_%j=!zvwS(;dlM{ghBe>vcpg!Kttw;m)|X4HN?A#%0j`!3M(0Z=^y=| zEFAJD_^ljIWJkxgw$_fomIpg-X?~!yd234~vc37??d?i}lGj_Q7D-E0g#PqJLzeGi z@8|YctA7k;6@D38_ItG+d#ODLjz_7?-Kc#di%ZDiNcU&-x!ma^7h@++yr}(EJ$h5! zL@Czc=ud7-vIn~w^}!Rv?tX~%j{Ih?s=Z|6iZg-d;%o02(kquw*=u_y9j?4J5>Kz& zuP^O7=Wy7MIi}jqyRkQ)PqQ;mrQ6@VKJ2bz-n{H#cU|WD4W-jhRmD!7tJUpO#X;m{ zteR-lZx(br9P_^QVV52+ODi?cxA#D|zR>e)fLwI*_p!WBt6h#cUYHzo&q7VltlsCI z1@}d)cXGg8N1cB<^Nh1@XXhtz#))Hr-e$bwG zGj%r4$9l{@A8HA%M(s*SlsQWh%oAYf0DR9Eq+ABRGX#q+1K*1UO9a`18w5FmT)~Y3 zaQMy>6bM!d3I(eKSPKr{h^bKxID+yByaJyfL69m~AV?FW3l<8N3a%4eFUS;R36=>g zLB3$QV1*#8X8cy}-z?+4t9phSkE%m-0(8{zJ0H>m1}S_a+TcoS8|>m8MRxwtR~^pWk0yw9g+KHM{ndrBlYu(@^@aMN8N23elU`x(bvWjD zzOP$PY{)8M-Y+6&W4k}Db~)~s*uLM*OATmvX6%}=0e77_hxF4Z<+{=j0QHBsmx_+FdnRhsljw$ zbTGO9*KEwrdgHEMU2z~qlY{!;zVZLF*`UHS7PE5izE|SJl7rIVkb~V}8r8oun)Z)2zvnlpO)ii8&_FRCQ{pgc3=K@waI~E-0k^dZ!Gkwa8#Z2+BWM23b zIOgU2@Si&7MJzeyMQ?*+UiLfot8|{PIh`EBn{P7O8^4=v9##kc!yC6Hs_Jbg6Lxpsdv`4V%&xgaO%v8YH?3>aZIE-D z8mm}D%^)&VLMdbvMW}%^cW0xpRDvLfWiSgNjQ)rO6^8YDK6;MV(^}TS10T=*e(&%1 zKJWW`zOR1is_OXCwKX19>bBhODIUw?cR!kAxr;2H<#KISb)Bkc=g2Fe^IyF;lKcOivwiue2Za=Wlmx>=+ZrApYJ6zx8&8d!( zx6;X}wGnVwk97x2=R}xWvvODJhr)N#pSH};#Icui!EeKiTec=Q>^|nT*BsQk1~nyz>q70pQ7fJiIBL(cG~=LY^PzHW zt_S_V;Yyl1U))peaMT571kS91^JT7izRaZtJP*`h95n^U8r0tGg=a+0JWKRK{h%p( zVO?m?o~bF$jdA9=Augew%JIsayg9cfx^7-G$XDD?P+cm=X%nnR^e2&2FLwEQ*!K?`k8Um#axg2ku!BR_e+C99BV)q)Md|n zvB03r^`I%@66(OD*BypMv$~OKU^HMPFc6GLwxQj~RI*JCF)$n&8I2C+^Z(7pGz{K0 z(|~x}aC?VWZ`ZMXyED@O^}$`-_lHeYk^4_(V=8_4NXW@0hZ^8e8Ohar_ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWN_RMSL.BGF b/CONTENT/BT/VIDEO/GEO/OWN_RMSL.BGF new file mode 100644 index 0000000000000000000000000000000000000000..684c9fd1ba0759d4313dfd60490adba836f91c86 GIT binary patch literal 3235 zcmbuB4@{J09LL|gLq$6j!ca*aSCc@>lvShW`@H_>?qu$kxBa&FKJV}M zKF|9+-{1FrGPCoOUD?Z@u_$BBs@XikqFNp|uZmL5vFb?GWLmGJmnyLb&uA2N!{gLG z_~lej@-^C^*v`0$TFW{M^!?>E`X8Qa^miaYKUU|G67W<1X@f6j2sESB+8s!>W>{oU2tD zTh`T4@!?9^T;1a|SLM;MZCeS<)@;@1UpLt8>?FdZ7MAw6su#a>77SF-vlpgIb|uRz zY7MseZiTE}@wHVC#H%`@Vp~4y@JK+cphrOj=$UA8i+R-#>i2o zM&V6OBFrKzA^?Vo7%pOj2$wd`621hf5iNnHSZcLs^Z4%^gw?;bx<>b3vQtje6aup~ z7w9kC>~ZdR+auYM?8KI#Sa>b+iVp`UbFER^@y`|lYug#1Pil-Yz%WL59$0wZ{Ny#+wH8*uFyVF|s zoKgE`e~R3=vQDeM?PX)mocH3=QnF1m@&ZSSWFCtM&+DvOFIn5pN-C)|YMHUHPIh?d z?5v40j|J0peuiYhLKyw0gZfrZ4iVsvLnVWZMTESM@(f|ID3J#iEI^FWu2qK28FK;4 zQEuHQHV6*FW6?o)xMuM|nCQikB9Mo`^(Ya@L*V)m5vZ|>h!KGr)Q%PbhHLzggWNG9 zV($g6QG-0>$BDo_{6_4di8D!i$V0YRl%35Zq1q<#8jB)pRlF-O3 zEcXKqiS@wyo}o2F3CD(8ztdaja%o%4;Y%K&UuBwWwFXnLc|J(@$YawE?in^&?k((L zT3kIb&cG^tG0TY-reo2JK(*Kt>5IK{AQorLwHzBXSWj!zLvIqZp#z( zd+4H)OFqA!dgqi2jclOrk5-U-gu#3BjpQg#Y2}u_Hn8V21c)}sa zfbXiSjXd}>#<=@@s!p?wy!L&@hlZbrIkz2+mt&m0V%Nw0wMf1j7<)0kwl^=^<($Ew z#Y_1H!x&hXr9as9#N`IV{J^?n>S?LZU|543Wf$6fNKFLyHF`Bz8xRt_0{xC&X1$=- z(dX!U_8;^$?jw);pL-wuj(gnucy5l8FdVt;HOOU;7~;qfSm?4V4F-;5g&4(Deg6{1!FDq7{UGgphH+BE0Ce}nS>|7j|%f+ zGapV8nAqp@yyO^YI_2nEL^BdS^5wVg=x=p2G)mS!Dw+70i!E&W{a0!DU@&)VAsEaZ z3`gJQ^O;K3bsTSPT~57Z)TJ25_g{~iF^M7Zzxm& literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWX_LBTO.BGF b/CONTENT/BT/VIDEO/GEO/OWX_LBTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..9ba848b12c82e2a25643204ee9934bd58b90eadf GIT binary patch literal 842 zcmZ?q4AXV;j51LXXaU@r{)>Pr&Pt~q~+(A#OIdeFaR}im@9BAzyuW-+#KdG zbvSS^H6J*&@79`Md(WPkWB(@mtzG4Yzjh!oko8T)Y<7Pn7K6n=&eMF$YbSn_&u-`P z#dhuYuiAmcTr%_b@%c};zti{%EC$khMf<6(gxcl3ceE$N%{#KO5A3yLcY5LGfxO$1 ze0ML?wMlUE#J309d}#IDJM-E!4D;l__}Cwrmt%|UzG>B=_Os6{28+S`Vc=P7ALW0- z2BZ#TFDMw31RCs_cMDm=#6ZF9F5?9j<90i02h$4*gPF;a_Mj+0_M4E8E?5jX3_xNa zy~ttJ0o4oh$IVxM_Bn5iY(eJ1^fH_XwO^@H0~UkXv2JIz{c%TL8<09sxYQ)hvY$Ak z#{PTlJ1dwND6Hg;`GCbh_9BNfy1k(AgSi*dR5$K+Ffk{6H)K#9}}!4#W~bED6LQF_0Wc3?%2vpvekKw46Z9 a1;pGy%mc)NKr95r!aytn#G*h9v=;#UT{SKM literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWX_LDLE.BGF b/CONTENT/BT/VIDEO/GEO/OWX_LDLE.BGF new file mode 100644 index 0000000000000000000000000000000000000000..4e0dd8555fd0789c1703214824002b6a2d6354f6 GIT binary patch literal 2402 zcma)-dr(wW9LMkO@>m6QdBhvsp+X4-QUgQw{w}LRU;#&x)NxujErVJvNjRgh2&)zSmm91# zuida(riZ?~I}-&PM?7J2r_%b$(Lb%{IzF?;Lj))c?qDu)v2HsUBc(fE6yyA(pkvI; zH>#Vg$Lm4Tt!@@)E7n8jd&PX3P{%v=hs^Z8!s=d^XHC1l5+aBE0NLRIZ+P*<241%^ z0$#3)p$w;ek@thZo@lr>$5ZApY@kaKI2;Sv2|!t+dI-OfpGXC$elviw-oL!WKUymI zXK%#A<6FHTtfro?Y}q26dfqIaPTUBSbtOD9$8Qdszo&DY+k>l$9g=G>jgk}n}z zN@U=k##c^3q$E-iA$KEkC&EAR*Mn%;zwZVvzy-N8kqeP45$+@QsTV3#4%@hH@ojug zWf6`k(J@WinQYuA?kXFiM}yswHF(gjD)1EEmVc zT>L&Z1~MGOcfY~Pa*Z7Znv0B$fegoxZ%@*t9N5D9@t5?+%*8I}vPS#Endbd81p<}#aM?pe=fn#&mGB16lw+{u9q znv4B0D`S6N_nx$~H^w2uI93K2_rsMuyVAfoWEjUv2;-)7g*1*aj6;TTto$%8GBuON zF@|xBv2sS%Iv-AR8N*y;2JWl>)WV~D&T0hxkF|pDSO@Z2Sx(+HL|8XiKb}NhMBYR` zM2`{q5+TF3ACW&1GHeGB1ri~{b`Vi85i)Ft5QP%qm^ju7BE4{(9HXHN$7oK$?);K` z)8ZxAKu%IYfn~%jzR5NVJuR_zwoi3iChRLSQHwJ>Ka;2tDs4u)GFm$AD#YB~YFCyk zew>AgF=yHzE7dONWkT)OIvN*k0_mmio5fB|2XJE(JeC$?%eM@|s?>kV&1_4SZiN?# zzYq6={~O^nm$4Hce*ojzzw&4ec3N-RmIqN87CXC)WIhGs)17v9xe|Jt|54P9NksTxAu6@)nW%0vhk=99uGivU?t4F&3`^OX1Dsg`?_eZ z{9x;kY+s0D{b3yTmrN~dcc-vAGH{+w*v5MXAG~w)+@#|K7r!&O%NFjGe1d-FW;kyf z5tth#d^8UjWs`|jIH>9|w9c%<(Fe3-DGGIq0w=2n=$bWDf2%$oU;jd0YvIsq9g oiGjhlAm>OojboD*Z`Q%o!*Vid+`xrP5id!6mtU-G5y-{)Hzx;JtpET3 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWX_LFTO.BGF b/CONTENT/BT/VIDEO/GEO/OWX_LFTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..a95bb91c93e598643138323fdfb8a6bbfbb7eb0a GIT binary patch literal 954 zcmZ?q4AXV;j51(y>mHp%^6 z9!u;C8B|_mRqxNtpRmudY1jVJ$rbjZvYmGMA6o4gkbr|jIJ21oBZH%ZKeL+x2S_F@ zOu)s-!GYO8L7FkYyrMWeGtVkLHP0|Ur7AurEkC~`KDQ)?0jP(;4#6YGBO6>8qFKT%lDwsON?JCK;svp%p>!cCsrfW%<7`vINV%2Wf$JFumti@!Rdn=G^yxV}Kn z=hk*U_p9OR@`adfrnIx#)vYMOPZXs)!7%2D>AF#s3 zV1D!3!C@cef5HaYea)t3_Os6{Mlo-eT{GM*py+t_+QE*Yy9Vr*9dbwQkp0$?ENKsl zDrCP2`RIbhki!Ke2GR?23n-jtLiK{|fQ2bc9dg*i)WO0fa+$roP_%(9$X=NH4jpo| z|6cpf3MK|J?|23$Tny%xtBzdu@j+ZR$Zi&4HM5sat+fTY4>>+yeuLQyiVtM>fx;dX zRxtO$+yV+KkUC$6Mix-|WCUU+AZ7+)umF_J3Z&VfVjwm<5c5LCKx{rB<_BT{AQl8- zAt(m1g@ITEh^2s78i+w^Kx$=xSQdyuVjwwR22EB_CgB8PE+FOxVjdtC1!6HE76)Pp KAeIDTpc?=XUri1G literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWX_LULE.BGF b/CONTENT/BT/VIDEO/GEO/OWX_LULE.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f20b50778ac8c74c516d24d3546bb3bad8724ab6 GIT binary patch literal 3478 zcma);drVYE6vprF+64g>LD6N=uA)&y>?*cA%FbLV@=z(!nynEm#o&X82#S#sYEWv$ zS4C;m>OUo@fi}_BLQ`LRw~dw7q_sg~TboJ~BdJYI#WW`MMdzFBxt+BnxXH=h{q6bg zna7!PCM(aIl$p15mQ5RFby=;UHkWOj_01vTF=VLAVyV>9*K3g*tDL?C$7_w6q!!Pw zGwphnHpyS;HttWI?T`OuixHmvHRG=r@^0+_*OZU0Cl7ncWzpv7iNms8q4;N|H!>?z zud}&bPRqJYH5=BHRiv+4Q8Bx?w6?f>WBH0z#cQj}H6aR3afQ1Gy0mOP*Vd@lTTkz? zv;I@z2Etxwp1@P1$~oBXdDo3;>5C+by!`_IXzNHHv9!`?PK>l*&=%;;tYP7|zE(?- z(R(6+w>{dxyUrZ)5gU^iZnE=>dJRo;8DOhJ6Q!0Iw8TmlKQK-|>hgiDx-(I}j~KLI zh+CZC^b0=*zrG`3(vKMYRMu*V;KWD^rfTm`jqvB#a;0DAg%}xw82pGm*!-1ou&F@C zU9u-l`qdsQ!k8s{<>Nv*7Gj7?jI?0TVy(IotY+McJ>%v3h#@XmTwRIp%8f6K^EW%# zLGK8Dt=c2m^2oc!)x%y6wjgE-Pu%Wh#OAh4HW_Kbpl$G9^0}u?_P=Mp%OsvoWkOSjSD=F7vIkZSf<`%al6Kw=Wls=$(jvoDh5A-ZI(t|w_xdU z^08EolWX}8iS5NUfRFb^1MxAs3~O)WO5rF7}uwUmclKPt7v zX2y@@HT$o6^0ks@N+CEQosdFE7o-lJkv?kbP|8sHAT2U=yV&BO5}Q2e{%ThmwGU}# z*xjVUv#g`K)0_oXYHihbCZm>W)dy`sN$HoQH zk2)3n3jYj~jH>>vzQ5VTlqr%?2Lg-eb(&gqucJ@8r5076D*W+#pR=0QRv#sjwMiyxc;`iitIU?mP99rvh^Yw-HrkucaC4j1 z-t3E?=QL7RPUbvqo@C!U_Az4H>YAjMlI!OKNxZD8*8^?LL#Ht}XTR^SeKYxroet@T z+aInEC8_iIrAKE~=7Sat+SQ-Ma?(a$ZBrSW@5$j{7;|7A{B(bjoCmal@$sm#*Eq(9 zWDUeMV<^lV3)s`|0}CX-jDd9lqbm>Qf%z&-#vn!qht^byVXpl^bskp&s_VESP)(;K zLp8$(*9tHs9bFmds-Rv4kW7?}bS3yNnL0%e2(EmCHvzp~H2JX>bwYnEeVHvw>68mZ z69?Pt2$h>fEc(aY8N?_N!AMJ+puUe12kgkWf7HZbH?Hl@AVymCeYE)lXnmx`JZPf_ z7&E6aD;v$=H~*av(vXOh5O^QhK$}V%N}Gx5K^qE&XMC`!)V!g=X49rpbwPy?`hNjn CJduk4 literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWX_RBTO.BGF b/CONTENT/BT/VIDEO/GEO/OWX_RBTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..6ab4c8d2e5b32f1f0eccd68aa01240c33e0b244e GIT binary patch literal 842 zcmZ?q4AXV;j51no7Qg-D z-r4qr3@XQWRqX$5HDO;}kLA8;&eitKft_~0PcO4)Kmra9&zZ~=7#SQL?lZY5aDZge z!USBL94;^!C`dErmsb>LXXaU@r{)>Pr&PrkrRC?B#OIdeFaR}im@9BAzyuW-+#KdG zbvSS^{i-`A1896>+ZbptbboYVc7bND(kjMf`PmDm!1jNih3=&`kVvraJumLeU z5QD@(a=bvy2gLk9EC9q}Kr9Z#5Es076omGWMzT>Wh(D1$0v}KyA`n9c zh*NuWF+sy%m9mU2R!imG+bApAKnt>RLu7@ur7jcsTXcRW&fDebMr_}4?&tl^x%Zs= z{r>Lu}rkRavEZMfn9;uay@Gbdok&=c40KCnQQo#3m_B%xr8UWv^bb zG~K(_KQ$c=aW_05Y~%zPGlP;4)*;VTZ-!4!my-9K9Z7F#gp%&iBS)_ZhrXNj#Otm| zl1gVS@AiFaiG>gl4X$vp+-$L34_VBNr+n*FHQ9P47S=uE$?9t7f41b-&XPY;0a}jv zGS)t6VB7W^kAm!YU<{9^0%6SgsuyH7#*l>I5P0ce1Y^<7qQ%v`$FgfU z7(%c4K+o`Ti|sy;jd$!&T2t!f!`tHEwz-VxzPr-)=Zq70#He*`zF-`BO%AV=k6X(Ev7= zGn~sApNovo<@dn3{2u&Skm0kaU)jmzT&UW;4%BvR$TKmfwypm=Cg>{nCF)oEt6MH( zYRh*w?}wH6yO6ja;_tn<%#J$>GOdi;7McAoCDg8MEY)aboQn*j z!7Yzp4D-Nb;#6F!@8l?wXBZE59^SrV}N_xs6U;6XTYO@ zXMhaX<8j9I&UXc~^*F=zkQs!}AIJg%%milRVSdL9VRrD3=Y{9w5z5@DJg9Jt+3}?E zqVlGCbV)dVjLK(8I9@~LyCfX@QTZ_ZKG?gZ8WFoWn-DK zc;yJT(M~Ffyn&%;{ z;ByFOnu}O`IXgOA4xJro>>h`TKzZT&4*8$_Mbb7E$=LPrB<1(@COKjB8`2sX%I?A0 zeJ5vf`J+jKG3RqDLtZDpZMjd-ro5BRpK}H8awD@9XUzu)jPg!bU=5^ZGLGSNa0vko%+O)rc^ z=mM;7w4~zyd>MtaO+uymWWLVsCr%qyvlHaa3E5Xu*NM8Jrd{eKZwyQlb>rv%UehMs_0ua_CyP?f@l5QIFXKfPrk;H5Dhn2g49>l-fjcw!r literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/OWX_RFTO.BGF b/CONTENT/BT/VIDEO/GEO/OWX_RFTO.BGF new file mode 100644 index 0000000000000000000000000000000000000000..80bfdf2366665d8fd924f60e761d546ff25d16a9 GIT binary patch literal 954 zcmZ?q4AXV;j51zMOT7G^>d~Qh&15gu(xdOKWOi+Qr&4Gux z!y$rcMffQ@Wv}0RTWdD#?+}r*RrmX62eQ8AQ^CG`q1F3ycuZ|gYp;RDK+b#1yKeuv zL=CVQNU!+KKCqK-n?1Jy=>>^_oUZnSd7pB6pdHLS>-+q6KIWYJoHhm6fy@J``*G-r z?Ja2=yZ-ytaCP31Y&J}LSnUq3D1oa3*#QcQJ$B7-bs)FIC^*_Nbl1Su!OXij#nJxA zyc}C(w=|oY+0Q<+7%T?!uh$L^`zZetHpu=+e86hYyj#c`CI+&1Mveg6n5uo!Zfg2X_2k;4k67dfn8dST%bxy;^PDB8dlWCu*0 z2&RWB^ zJ_-x;oQg6K_D#RWPp$Fu#-3P4?AFXUlkJ;-(@4q8Gr;z;DI8j2(1I=7)x_HK?iz}s z8JD$4{^Rl#ey;pbfY`oW$tK&e_=~_%wa@??o3~kNi9t)O=;dzX%#+T5T+cIBu18F+ zCm7;BN{;TxvFCF5O-^)3KVtAB=5skaj;hfd%>Q7J)DnXh3^{{|xGdBUjQkL{(`7T` zzVyNvsU-$2vF@7lMq}L~xn9>#88R+0tVgWsgF^gX8KYe(kn0h{dSH5d5xait6Qli3 zEAvhs%okmn#l!FC2Z-IPOfuQZ*!#wf=6nuz(f_>E5`z}3yXF#er;P8|A9kO04jIV( zU#lD?NzB)nYO+q3L;8Wm^u$OlF=)Y{^|``3mOoAB@cU>&qVyvMKQOQI*#OkBD$FL# zE(~B`?=x7KuyA4U!5_YZ4=%tUVUfb3ghdOB=`}nL7B)l}{O}*2;U6n(s4!@tjT06x zY?!d&!W_az2pcIZL0FZmLU%CQKCt3?2e1C>Q^~N+=nD6)*!jNC>ln1e4t}|vDc-lULfN(K zT6rAg2kp4D7V~(qp3NP}f8NnxmH}AD{sSy2wL5^^ z^uv))`o_cGe`~wx2UfK~;fIsFW?Yoo8_i4kE!#V0T(I*~CsQv+}bF!*f(tXPt&H{R;&M@qFYjj zzt^>m_Y627yC6-6wncmS5qE~1Kr~sFP20im^su0*6kk%w&(`dboiS94&K(-VI^{@f zon90J+TKnZh%9!nxDnMd2CX-wqGT3wwobIAk6W^kGZ;-JXxnd3l8mNEbKyBw@LQzG zFo7;S?J^lns$U-b$)fK%r5{ZZu(2~HNJbOmVbT%STCq?vnhuD8oUK!dw3ryw^%G|N z%?eMZ$%)YyqbYLi;c4djb#c(7qPW%xM1EeStlz6hSCFnAKI8gPS4O9{c4TlcYj*}i zr$(1Xv4&n-e2+CfdYibm!NuDDz16phzC2RJfkw4mWOzmK&6&>9Hl1eJSYr02xwD8- zfq>0C5Xqn=1}!nX)!|hJtnAfpxgIfS!JzGBtPekC_3O=r_mLl`{4BXhKjdP$h|-Vp zqe8-Z@$b23!jBl%1N*mrOZ}2MN$9AiK1_#CeV7iA`mjfz7u03MD{XpFzYSL(Cb~>r zP?y9_XdL{2f{ZydM!v7(Fxp?+*ZRt_gW zI^Z)sg`shIT*(rSxR!zmP+Tx7RLa>>2nOv7Sm^JyFqt3rz@p{I1$zn>njaVyFa5Uv St6=aBN1ftXT>w6!2>$_~I-9%z literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PDSD_FR.BGF b/CONTENT/BT/VIDEO/GEO/PDSD_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..2a73dedfc48b26bd0497fed475dfdf903788e2f7 GIT binary patch literal 1049 zcmZ?q4AXV;j51eI;INI^Oo5TXks;AdfdeG5 zrM*{8KK|G=6e zN&72qU+qAF$TOMM;eqat{g)T%*{$+Wv@iPke}C(1PltH+y!}Py2kfo~7}>jRbGAR% zA?6@cb8x@9A&>pcCRKZ121OR+0AL1kKmx2l%m&2lK5hiNDNgk0|Sy?upJL{C+tG9!vUlhB!;9HY6k-Yk{wXDFfhEAu7=qQcb~U*i4D{( zaDNmD<=epA0<$B~pc>{rxV`9Npj3>c7w%sqJK*kvxy6^kkziziG5{wKa{)0o5QCC0 zFA(zqF+UJHF?1RzNWkN&xTGkvAhozMryLPm4Cx&V0kF6Nh1s@ix(*=|nZR)ci-S3~ q5%%5L5)Poaf{8^giFL4NSO6CT={>P^m4lw8hl4MJAcot4i3k9Fm1IHy literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PDSH_FR.BGF b/CONTENT/BT/VIDEO/GEO/PDSH_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..e6af83b1a504b24336bca79ad768762ccae828b2 GIT binary patch literal 1297 zcmah}Ur19?82|3ww3+`(M+He-LF%CycNqqjJ7;&bW#)rMA(FJ2n^{ZewrV1zJs2xr zqNtbz4w{8n(u0r?x=~0$6C~)Zr-*_y@+qI9&Ubgu?Pf*?ew=fD_xpa|cfRx8bEx5D zwbIbG*92Bk5=DziGF9Yx&5~%f7D$2+g1Rtl0yYkNhN=A1nGUQhDt%A|kjyMM$I{us zWQMJ2XV&Tj@KQA8gVHH;tt5aGd~V5t?7+TimjcISsa)uY24Z#R{Lzk}@67qr7otHx zQ#aHOLDfR`*xYF1^$RvT4C^`EBac!ZD8fl#5E-0QF|!~TAhq(zrO;wgmbS1cq28b` zT-R~Qf7ad=?&pClZn`YQ=}loFTaihHeh|$4y}OW3jtvpy@NAq*I$bP{3d*^+A6p3L zxG!>l`U0SyW~ar-ahe^?`2rYxwHP^Wt?#$(1AoOpj@$A48h1wza*pSR9M5lf$w~1% z^TK^c`q{X8UgQFSYb3iQ6OGgJGsLCq*{!3e`Fg1#u3kSwe)@U&Ihvr-Y`j+!+aQt0 zkk7Dzp$Y8y*iHou8yN~2uo;RON*GERuxB?jlrfYuDDM`X`+T%!cSRadF)Ai8qu6dehzFLQQ>2hZ)X@B`t z)#JBcJJn7nz7Ohp==2eTWtm2$pQftZ+7 d1T+$4ERvbRo(uxt%V?%Py5HzCBJ&`QDzjDA2=);agiz3&Z8+Mtrj2@}gUVamr0l1GVPdz!uzxbM-!H@H2 z7441%C!Ja+8jHpI;{#`gdi!GM9f>1A z)2X(r*|DJ;xinyw%5FYsO>%Bw2o>Uy+TrB;uJ!%zIz!BVdZeBQjH>d)sfT%Xt|#B6 z{3K()UQcNzO5{UU%I}YSIyR)MCj+eM`dU{8zG8iHGFUUPnGbbbF_mA|v^URYU* z3cA3a4^9=B$tQw*#!m!(CZ7P4&*%!Rn}BE;Y61m#nqD>gl}ty>*vcqxaZi}l#Y>G@7|bPW^Pwi7I1zHEe8Us*l(iwaQvS0@7$63Hsam0p(8<^Tb z#VEGGkgH}xv06ifG?1yrienYi8voL4lrLHG6pXkJ25L{c`~{wZJ?2}O$Yn<}sfoMk zJMwF2{rjupOHChRVE3nguwxqsdFav*w9X^PUJC}|d(#4&PoE7lxhAfLMZUnwR~Fe) za}DMTE)80LUS7oa`V$3lDRYmdcfP?($S}F?K~8zJHpMCp5SsnOT&fmgv>}{RE>$zd mDn=TrH^Y2d7c_LNPcu-p7!5)BRn4XrIRmQae_U#K0saPijkd`E literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PGNDGUN.BGF b/CONTENT/BT/VIDEO/GEO/PGNDGUN.BGF new file mode 100644 index 0000000000000000000000000000000000000000..c841606d83bda33f1c92edaf1a1e78a7301aeed6 GIT binary patch literal 4589 zcmcgwX;c(f7A_h=K*Uy|83bax;fB~a1`tEtqCqxAWKaZAVyhs8MK&2k5ygxGLX?Qk zh-Z{2Lo|~R#w9MK->Z@{8aYN2TyRK40w|*~2|p;jo&jMc`Diq*r^3X>`3Y9pf*#xspku3c4*FC;|b#Ig_g zn*oQoRA%z6_He%HjxB#B(?+;FeFgaLc7_?ATFg)%jw>APrZ!^S)k?LuuW#Ve!0-ic zFADJuQ#0P2%G6J7Mt)q;@xWWltrBm`yK5{&GH3-sdv|5AO&^&M|?!dvPS_a&sXw#FMZ3tOcL3u@S5iUAgQY z1%xInmUL?Gu|me=*^(~qRJLTh*;>ojCohp~=~K&?u>fk7!7yvWLcX)!j$hTM6k@`h zxeEIa*f0}!N!M9FM(8VZk#zLw-U(PN*#OFLL>`%?8=gqs) z`U@YuCE2f3+Xyrs{G>&)AOF-@^6&XZYoRl13^=c8Mpypmin{~9ll%+7Z%Y0Z1*r`1 zsg3s~|7zE{@D5wLv0b{2uszEJd_HDb56v>H5?Uea;6qk>-HosEH{!!gYz^=$e{Y9x z{hL@iF`7zJz5aSm4a#aiY=5T(NRnJ$2>g#LI&s%Ul|bVmrtQ#~)ydLHG&g7jE*9-4 z=UCx~0Zo#kpu5XDjyq9e~E zMX?fv=*aUZQAi6SI`T|fk(T*IqqcidmYFee@oN)f+}5XUqI%*Du`=n+%oMV@zsz>$ z=m6FKZX*|0GM%G?US1m~>F9%OR<4n3>Er-U9Tzewn4=R;Xo=;P2`e}{iR;|cB^{mk z1&=mKwsOyrgGK@r%-E4w8T4H_nBJV)T$~JKDpYjDYPDRUShPco2C-`6q^jK%F%5+_ zMxiA=9=u>@4UNUo>^z@9T=+>dtMDrTzbVhq`Ql6HLSv92&VI)!;Knt<+UV(0abjqm(A{X$Hk|*kvy#EwnyXg zfZKVc6qEH&RE*<`G%?stT>s};AM0<%on$Ymv~aWRJxtbb+UIV7cU2a!8DB0k7^DHo zu2?Uw|Brl~ULLCS45M**5Gx}NViNyh?P`8m0nrwSt-1XH{9{oOgnu3neKF6ya^M+CZ!qPbR=PlP zd=9)!4-$3n4WJQYetjRlIu(zJZRxJNc8DX&#L`a>0-u_O~WE(W!Bbh1Doub5f33$R8R+s-6kxnsfb*UF!>HbC* z@P(--d}r2(NTu(^HC~0)I>bk9V@I5^;A#9D!3>zx=U()Y%)b-~^+rFV-eVh(d^~ig zcq?QjeEV)I8g*kUk~_sv{*g{L)c(j()2TBi(F5`vG+0%5S}!w7nt9T=+-c~vsLc(> zRYwrI6@8VJQ-tm`G%j}M}CY>&+xHQ0Ga9V>SVI^AhpX3KQCo!gT_?iAY`9Y1B| z)T28Mjmw=Tmu97^HD_`yeFLwaB^2xj=n3gMe9eMn14AEo8bXz#o9!Bh` z=&R^Y(NTaxQh_E{G`_ppl_TVeCQrvN*~1e@4P4HvLo&mr#}tjrtehS*UHvg+eY7Pe z83`%jkita)O%7?ir$WOK@=A{xIyq#fO*3*Dm)SWzX6WR265%7QZ$O@@gg9i2# zoc5A$E;Ko%arw6M{}@BwoU20ONU_>o;YuGZ=OIp|SKQ%TUj_Vjt?m~`61l%K8w6y9 zc#%DvgzBnjIQG6L?mu}5nfx;Z>swR6>G?JonOcfRyIJBrZGL=zRW2;7ngeaty-3!T z9o!EcK`u~fQHd-XeDH^xe!_WmMX-3f59GjpL`D~RN6-+z4JH=+0Upmjgvfh?pw0WR zTXhL+|N5Y0dm*rhCAMbj{a|-C55By*NV-7w{^HF)-dPN7HUW}uM`$D_y0+MS*t&GQ z$N*elTleG#bp30Y|KOF6WJAeK4SL}5E1sWXE{Qv*} literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PGND_FR.BGF b/CONTENT/BT/VIDEO/GEO/PGND_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..0fd634ebe3bdb590ed65a97f2675a2bd849f328e GIT binary patch literal 1480 zcma)6Ye-a45T3iMwpR8)ds|#nf*@mcLBnY0xP}!b6qZO4`C83f%XYO=ij=S{qN1SE zKN`IxjEYEl(C*!SXpoN|A)&pb9|`qGs370X+`GG7wbzB=-uccs^UXIi=dRzB8Ef0L zBi;xR2H9XR8D(Q+aCVSvh=>T4C8-pWoG_=!n&@^7j$>t(S=o8F-F5(Cy8APg`npBd zb*p4AfDk>q4+?4#yQjmn8`1R%s`eb27`!%39b)(O0kKPl39)< zmeT!>9B0x&`<|jahdn;uSzPF>@Y9)6MYdEc7E1BkL0n3CiL78OJRes@eXugtu~t*X zSl`ncBux1oHu-G+E>N(wo#KH~eI*7*ynR;2v?^)XsjeEVyaB$-O~n3oR$j4E@L4?v zW6Yt?@8i{Sl!iluUdP$X2Emw~_g=F>jCZz7$j@D0j*O*4au8_T`2L$#{J_*$gsnPZ*gEn*Y&>xc_Jr6xPBPy%b$brnHXb`Ag_8jb5_9gy}GMiaeWW zrO8gG`v#8YWs&E`qrzY;tOEkYUP_;Brf~Hakz8<6>Pn;V;%UHC~VIKB-2?wY` zi{&B@if4HFeZ1pH(_^a7IPLTJ_F?e5PV9~eqj&+#!~VCoowQG=*OKF9l^#dOtUk&i zfT{jQ!fD;dTcyU*IKanIg`*Tp%LP1|4k0*}mNTFqV-8JQ08`laarnKPtepn6Wh`vy{^Yw zarJl{_AkA)_VqQB*fsXWv-#!)9Lo5rVu`2XRII7>GH&ZNiZwrMO52kxEGSs!Z9G$g lPa+UsrCXI7&#J8!%M$OANBMZ~+%imus3|i#`3ll?{0Xpc$JGD; literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PGN_BASE.BGF b/CONTENT/BT/VIDEO/GEO/PGN_BASE.BGF new file mode 100644 index 0000000000000000000000000000000000000000..75619379fed49d1a9ce4d77e8fcceb192b738d61 GIT binary patch literal 1820 zcmb_cO-NKx6h7~bnr51TN@mf^A81jbRz{ZI`(BecwpuyISNu$?|8V{^ zuhG!pkWpfo;c(=1r1N-pdq?<`0VaHFHS+1`#NxbZ!9tx;p`A}B2NUN~O~dg^eX&Hm z;bLl_yFZ-(^pW2RFGt{>ib7Fs0gVS(623Oecl@FC%;f!MAIo4y3hVAEr*|}k5!b;4 z=0IE);Nm%j1!A~dwvsFTNiO+|!mb?Tf`+D}h0qAdMax6mfM)VS9krA0iN#*a;(6Ly z;_KI27*~i$H5_D%J3j;q!(NX~HT#%Kny`+XG8BfzbP7XU2SZ#HA;5L9U<|}mQCD(T z##m2bEcjAqlzUSU8ytwG;^}x`1YXGza0ky8`zmMH^(PmO`on0mZFe3z7^xx!oNxbp zgDv$xYQe3eKw;HyYjH1!7SAc}k>A5XOvX@{$IUcNeP@d6#gG`qh{6^*0>PF?p@O>q z&#^H1Gfj>|uXVe#D%J)-7GuV zmc>%gIf=35H=_>bmKIpm<%Je?liczE8~;?wo!jMb(MM&Ljl&$3Rw#eKo_CEp7$Bxv z5XjFtX9wcaxxeyrxd9zse!|bsi!1!NN*Bf!etw<~;p&KjDOJ9NwI@Onq4_!-Km1A7L`lnSIo7w-XnztoyGK}RF z<`3zuk zPk11P^zUH8J-du~D6W??r+ifm%1;f&S=6O+u^le3+_`BdXAcvkL22^`fVip#9wzrx LtN+nhyuW_{A?v#r literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PGN_FR.BGF b/CONTENT/BT/VIDEO/GEO/PGN_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d77c12d5d8bc2e4abe30d2a6f1a296c55f84bf9b GIT binary patch literal 1603 zcmb7^Pe>GT6vyA}y0%uD;SvTOCX+HKaMe60?e95;wUiJ<5kctc?wYyQw!2z(h?TIm zO9?^hLWjUkSr|l@U}xk3ncw?;zrT6!H;4VF z4=Db#wNCIjWQW7;l${l>jsn@?@f69D6otkZlmcDxAIl<_tIuAa$|;wj3IMa|@twYK zxN@4F@k9Fn0*p}nz7X@S23dk;2(-#><`eVb76ne$$YoMzB7C*+LMYK033TsNI5*`6~zX3k3;fvtR#C>#{cm~fE@3rx&^Yf*4Us*%e{C3-0m zh&9F&v7TrsJ{Y;8NqN_QMK0W}n37V6v^FAdlGYbD?=FhErQK*_Dvv)B2S|##x_fj7 zb)oW^coI2gXWE!KucOaPiuYB;XfV}eKR?YGxuEL0h>?=KPuBopvNO>eh8K%v*~?Ml z?7^6qWzU??%+OHT+jr8jdC@$xAKHg84}|OUoaWKSRGy>f>c!`E*^91WF>TCV+Mv0B z=2%5?(lY}WMIpr|3hs*{ip>;TD7dP{6eSefC=|R!m8`HTIS@ME(-jHT24lV5u|czO zsAL^fvT~{R6yW`qH?+MGTq+BS{ky*Sn9Vln{mCrpPc7IFs?zcH%ui^38vB;b zPuK?AS9O|#0qUF`R_AobLWA+%o{PpGV4WBG`QIz0U_Kl!Q~|0HK%VwI_2QT^bjW1E zre(E!V8mxI>W^w%i`jFjh3F_&BmXm>Kd#r-BbHgs0Mg@rOSjMYfcuXwv~mx+N0}u7 kN-ZWZrZMt}rtUj`*kYzXgJ~KjV~sZO@~Ql<<4Q;Q7b$zoe*gdg literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PLACE1.BGF b/CONTENT/BT/VIDEO/GEO/PLACE1.BGF new file mode 100644 index 0000000000000000000000000000000000000000..b3d899d5761a5ee13032a966b9d0e626d5052680 GIT binary patch literal 238 zcmZ?q4AXV;j51ILx`?0p#oSwLzSftU%1nSq#tIF*6XeGB5xD*Gn7a literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PLACE4.BGF b/CONTENT/BT/VIDEO/GEO/PLACE4.BGF new file mode 100644 index 0000000000000000000000000000000000000000..034b8b0a9a5d5255d83ca6645ea8fa62f95d27e0 GIT binary patch literal 238 zcmZ?q4AXV;j517<90s5)hZ{qB z2SWhVIAkO2QLO-(+yD{-so4j$2gHYo!Sn+84EDYZf-E34j6lo;#LPg<%D?~sFm@et literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PLACE6.BGF b/CONTENT/BT/VIDEO/GEO/PLACE6.BGF new file mode 100644 index 0000000000000000000000000000000000000000..bba49db2e8df06643186b7e6bafdd3ce33849aac GIT binary patch literal 238 zcmZ?q4AXV;j517<90s5)hZ{qB z2SWhVIG7RkKy!c?*$OZpBnDEm4`NRPhz}Ek>ILx`?0p#oSwLzSftU%1nSq#7<90s5)hZ{qB v2SWhVI5Z=WtpJ;B548$vEd!7b!YI~*#29=T1X(~dBM>tIF*6XeGB5xD-qRcP literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PLACE8.BGF b/CONTENT/BT/VIDEO/GEO/PLACE8.BGF new file mode 100644 index 0000000000000000000000000000000000000000..b5c8b7ee8a2fe36a3edfc332a0b5b9f4b9f1d2cf GIT binary patch literal 238 zcmZ?q4AXV;j517<90s5)hZ{qB x2SWhVIG7Rk5Oa{NU;v2$G1w}Ywa8*ny$xW!z6^paATt<&mBUPu>FG+cSHkN2F-j~r-UMnX_IZO-MIHpkLHDMS*& zq%MrS=mQPCNvIK#AMdLzAz>=fh22?DY6!K&3nh!rvp9C9FZ_A;{?7S7&w0){&x)L9 z4>_FY@>R&76qHJhN>Jq_RjCD~!H_B_6phFnKssd94bSzJ5~E)wWzWwzuA)3#8J4G` zWzs>nQ#P5x*ruH&hM^RUxQCE7b%CHjcH}A%G%(N~t1Wb(3Zsyzs1DXPn=iYA)jn5E z{lzOmAA+eRsNe?5gTTEH-o2r3k^3#dH*g4b45hd=BdVoxJKOc)! zxvaoUCX>vwnU_r%81DrJ-V?bq1a`%_vLUi~a_bn8jO&s=>#c>w;~9&`d;i5N!@Zga z*88(Z_5cSAH=TA&Wh zv-aYc6&R~`eeH<_7 zGMUwOf7N9JM(a&rUEiBwUlP2)%8^UW-x3x50FXqLOqD_f7c-SgOO-|i*J=mVPO4p0 zIx0O?2301Nfhvn?H&r&319cgNoXwjSa@ToleD3^9fqGA%<^PRCo=$W!qkVjIDl|ww z##ToMpHASOo^K*PI)tT(5%OayB7L4E_`=O4@%6^7QRparfmN0dOyFmy7Dec|z2hUq z{xc#SKB6aIYL~=vq~BJbgJ={+A$xN{{swQ8yCLBBaBErYM33kCV$e_$bZzKYRIE7f z$G~jbfp{kaD;h+Ev5sZEZ0XL$jDeRi@OCV}k2fnH57^dtY~EHc%wr64lq37L+Su7a W*Tcik5Y7|E;C$iV0L~T0DE|vdyvAn$ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PLTD_FR.BGF b/CONTENT/BT/VIDEO/GEO/PLTD_FR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..984ba2ba350e156587b096a0936bdf033d63152d GIT binary patch literal 800 zcmZ?q4AXV;j51|GR3jkNUiGl3!WpHFc_9ios0}@~bVvyHCfDMS*ffytPk^`v$ z1qnzDB_K8N{fEE_Ks(UQ{^++> zuox^+fW#8@>ygFmOOF@X!Nj0?!D2AIP&@4R3C^_x*->?Tr9BpVVPbG~K)2XK?StIF*6XeGB5xDa0?oJ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PNAME2.BGF b/CONTENT/BT/VIDEO/GEO/PNAME2.BGF new file mode 100644 index 0000000000000000000000000000000000000000..8228574170cfc98346cdb7362367d2c97a187829 GIT binary patch literal 235 zcmZ?q4AXV;j51I5;fMN`cK+FWh%s|Y_zyJUqcNqTw literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PNAME3.BGF b/CONTENT/BT/VIDEO/GEO/PNAME3.BGF new file mode 100644 index 0000000000000000000000000000000000000000..383812cc17cc126177c21df170c0e6eaa7fe7aad GIT binary patch literal 235 zcmZ?q4AXV;j51tIF*6XeGB5xDap@X? literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PNAME4.BGF b/CONTENT/BT/VIDEO/GEO/PNAME4.BGF new file mode 100644 index 0000000000000000000000000000000000000000..71a15ebd9c11b994179db5655409547102cdcb2b GIT binary patch literal 235 zcmZ?q4AXV;j51I5;fMN`cK+FWh%s|Y_zyJUsRT%>S literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PNAME5.BGF b/CONTENT/BT/VIDEO/GEO/PNAME5.BGF new file mode 100644 index 0000000000000000000000000000000000000000..703888f8fdbb008d8503af36208394779f66c479 GIT binary patch literal 235 zcmZ?q4AXV;j51tIF*6XeGB5xDbH^Hm literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PNAME6.BGF b/CONTENT/BT/VIDEO/GEO/PNAME6.BGF new file mode 100644 index 0000000000000000000000000000000000000000..21252d7deea4dba2157d6129af7fbdcd15fde410 GIT binary patch literal 235 zcmZ?q4AXV;j51I5;fMN`cK+FWh%s|Y_zyJUuGZ_Z} literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PNAME7.BGF b/CONTENT/BT/VIDEO/GEO/PNAME7.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d2c7c3cb41bf3bee80073daaa96a1872c82c8075 GIT binary patch literal 235 zcmZ?q4AXV;j51tIF*6XeGB5xDb)_1K literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PNAME8.BGF b/CONTENT/BT/VIDEO/GEO/PNAME8.BGF new file mode 100644 index 0000000000000000000000000000000000000000..fac4c61034a3a1ca1b66bbf2fde79b59f83eb328 GIT binary patch literal 235 zcmZ?q4AXV;j51I5;fMN`cK+FWh%s|Y_zyJUw5g7{r literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/AVA_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/AVA_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/BLH_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/BLH_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/FIR_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/FIR_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/LOK_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/LOK_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/MAD_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/MAD_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/OWN_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/OWN_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/RAP_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/RAP_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..001d5da31f8ecf3c508476532207a04acea4e675 GIT binary patch literal 1834 zcmcJQ-%C?r7{}jpW>Z%!ty$K^I#L%dkYZ6Me@#ET9{@Uga@7mEQgeL-&WP4NXh4maD8L+ci*Rw9?UgCHAezGwg67Sajg> zxsRO5i8mbfRJut#VPkRr-h158Se#euokkU0-xuw;$^U3!BcP28UbtwFwwxax7`ire z<=n{iVTR}vM!nJ1(QS2{NhbO_jPU5muvh~I>*S7><%TwuF2;~8Fx~4U3vC>BDD^5< z2o4H668Td4^s!agv<)W{JtgAZ{9??_r-eNh2=ZjXFJdy$13Z-aT%t5=aw6e`Qr*Hv zylp=h@uAdh%JWkA4~~yHV}UjY@ym@rV!uw;3mXN<&E8na6XKcZW#M=8^CjEv6!!Q+ zvy;j_753axBjvv-?A+|v*mC22VMii!B^fi_)liE1o^VDhmD6L=hJSqFuJ9wC@(4RH z{UT}9r)g&LO zhEz+!Z}1Pk z^HFdEGyknx)8v=R=6000IchyNn;&%!RaR;&E#g6-eMDYeaTlDeVnma9bl}vIafCQ7n;PBL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/SND_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/SND_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/STI_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/STI_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/THR_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/THR_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/POLAR/VUL_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/POLAR/VUL_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f4f35ccd59235e5a7d19f7b398e7eff7bf354f7c GIT binary patch literal 188 zcmZ?q4AXV;j51(GSQuZ2ShOfF%uB8GB5xDhg3Ll literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PPC.BGF b/CONTENT/BT/VIDEO/GEO/PPC.BGF new file mode 100644 index 0000000000000000000000000000000000000000..911ccc1545968c06393cf3a46a614ea926429756 GIT binary patch literal 2666 zcmai$e^69a6vyAP$WMRpOOQlZKyV371r@=4_g-~tpz;S!C$*tetxDgw!x)#o{k4pA z!~X4CGWHn+7|&tt{kc4jrK*ZH*6*Tjy{C2hoqI@@=mzsmtQksN zE#Fr6wplwiS5xgg7G!z@;%vrziTKxTIc;FQSZr|Snmt~tsbRg9B`2Ba zACF(MnlC?W+kdB1_BzT$eeqPTNj0a_%}(c7ZRP>^EePmVba|N^S?Eg^_B~lw`K;qK zbgpyw)S8d*C@@^6QE_Ib48?@6+JEg z`v{NI+3}(k*Ef;xAGhXljZ)4bF_COE=h{rG6kpaOLp<^97w$Y~%wxmuX0|XRjmLpH zk}Nrc+>2|crf|)nT{`-z>N3k|+D75f5b#YJ*50_Xar*BBVsTAlb|v*6@MR@i40KaU zlNIMs$~i3L2>LF;xMHoM@6&FV5Vzh?Nnm~B=JN9NXU)mk^plc7sU^@v^pS^UsBiM% zOgPVn*YoR1>{q{HyE#XFb&g`r_T~x;xj=C)><;n$pOOKO9PWF5Md;XEe@3rkSKl>H znvd~dlQ>zNcjk|XLy1NyB6S8C^6cVXjMjWtND57}o@WDLRNR!Z81}hCw^w@~>N!ZP zt9Io1>}p#=+s$9H&_Wj-#y}sG`VWp}iA9rY;Qa9#MEyi{Xp4iM@<&NC8b_)B;2+z| z2YU-@?5%55196_@qtJga4(uPVQ>Ffc8cUTw-yfy^gBo}U)^xP@NqKF$$5>y@uPCRT z-X@k*kU{ZG;MvIPtQn`-9D0<^t}#Ln@|W@*O{C_oMviShMuHooxTimSeS#(otJ(FL z#Wc_7BWqQwFX>o0M}BaoU`*o>d4fK^DKNkIf=S}6=5b){ZBRps=XB&oK81Z2FUAAT!X@?kt5@Lh*}9B)><14D1-@O9z+we*8;*}c*{yu(&x7fo-A_xz3b`O$io zPR7v)ug_V>szY=ru|;IHK}2A8#`T2V@6TpUbp==-lC8f?SgSTKtmp+AH_^ImUJ&$R zSo`C+xk}sp_#Q&W=W}U+;=zFT~{BwL~&hMhf4Wq4xOi1 z8(7caDN*VPx3(7Y^MmVF>Mi*H$r=`{azv2|Z~)W*ewYF{0nRpD;Oz?Fm>b{@Oa-O^ z(}5X)2jB_dIDYp6ya69zCg2PB0kZ&q;3;4>5CF^p0)Zev0|WyhKqxR52m``_c{a50 zjsS4%X&@4q4=ezl0Tu#_fW-igM*-0Q>XraYfn`7pupEd5;(!&l-#U2XiNWu%7ykiq C&W~OI literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PROFILE1.BGF b/CONTENT/BT/VIDEO/GEO/PROFILE1.BGF new file mode 100644 index 0000000000000000000000000000000000000000..59ed31cd4793745de1c50ad25f26e165ed8a3faa GIT binary patch literal 1506 zcmX|=3sBTW9LMjDw;1t09)}!w2*>kysX%x8mFF->G(Kp??CxiO`~UrRZ!b1+UqEzX zdWez0UL+NX%#EZ*+f1^Jr6S=j3#m|8B#0~)SZ@`{QB6vTfVTfm*Au-!c4^fbg|_tr zOzAB4p!Lf~e3{LkG@#aGr&K72M!AVX>LAQ1DJs;JYY#={mlmiG8L|pWbOO3=9*>tz z8Zlv%Rw6;FcRT-1ubBoP{}oMQSHof3d5$|#VlB?5fqdN>jx)X^+U)I!21g(wYQq7st5kzn}rMMdYDI0z-ZucMHoom`l$f?@YKsn0$o0V=cLO z{yQ&{W9@_82V=R@&lRHIUqnh|p;*s5$X&Ip3cps^lkBokc=Qx=C$6o+y$ly(TQ32< zgE!bc{OhE_FAwi1^PD}g9&=m8oFPGrLAP#Idy_rv)GrXIj-dT^7~)?M32$nDdmCIolk!g`C=_h2Pc)s zc8B1B`dyymhI=J46;3Kap&Ywhz-uYY)8iFws><@y5G+8(MNVXf1 z^+^yAqvKAHra^~DOy(au;KR>8;LdMmKWx^MNsPoDioMsl^IplrmS6)}KIM#W9t>~9 z{g4II!#a{6II@L43rosY$}^iin_F$p+4xzCHN}R);#sUCg~hOSGm7cv{K?pY&czf@ z%65v3BB%IM0w{qLKZ-9US#a5y?Pq(>A?I`vX=GfSQ!eW_YW41>~VU2x< z<#nPsQ(P#nn{(D1Q;aCgyHlhT4+^V~)#*jqu{mb7dsBQUtaer_tC^jFje{r(3Oh@( eAeg1*b%6vu!2B9PZEvTi)8Wp~vyULqx8`#UF8lydD4tI1vpk+tgbXc4C!vsRpZ zL`#m3skFp&8YyiuKoQE#bXmp6ppys)IzEsE6&Q@1&B;3Fn%Sv4!DF-Xm=|;Vxpsb{L>2iBf_It}5`9;nJjGwRQ0qDL%Vyc*e9z!9cR}(3&rkh5LsF&T>p(Hu`rNKXAQtU?`q+i4yNMJ z1q2!G1X0q7$_X-blv!%9C>6fnK=vO|o#R+KK4j z9+0~&ZLlG_Q|8*mK_hNS`c6K*w&mfoc2&ls>HAjewr`uj<*yNEEV9MWvx=4ZKhgOc zMV5Iv;h4R#&6?JI5)`%>V!svV5^(yJx$>dIUbu5DU%1PgV{zrnZ^@h1oB~I0lW?xg zMC^Zki=6aRBLpWk3#az$aFcf{<+}%e-@0-Cz6nz>EVJFJb?t}rIpyLWyGo;R?jP~6 z*M1$eeSYEUgA)+-OMo+*FB}&xlQQ2{NX7f0e##fZ>2^n;D{Cs`AE~7*6~grlN8+phngN<`Lb&BO;hy^_1-*Y3z%11< zczUo^xRUX47`3_#{1ZCC6LQ~GXP9yK=T6vZ?f}oS4zbR;!-Q8IAA-r_gGpa@3b(4o zfHSLC(!19Mzh3PUZb!8RD_4CCi|%wm`HKU>Rd_8p^7T6Kzi=L^ejgFex-AL4?$2Pc z?Zm@xB_cL=3@a@L8jY zSb`nTaShk9sq) zz0KKFd|&paXCBZ<%hV>dTBk8-qQmU6Ngb6HZc?dsN*gMqm_A=2`hB&KXzcmrRlFpn z_us3*+QtzNtD=={SW$ILY;*kouvlJ{GfgTf+v1Q{o8nZ@@7h^jy1Qh@hV4~l&+VwR zmF+5(XkV9Wd01|-+*Aj~ixBbs`&s%>f&13gK=KSLA3 zE#$Xh)ZK-Hk8MT!)^Xu(RP+!T>N}iIM?}BTxdQDt5g$4 z*K7%)<@-kC4njp}h$uoPqC;zTypAFCA;&SVV+r;gGl_(OND9Tg=4W`1U7pk=>u3%q zxIUjFf`}y8@gCRb-0XPoPGTvsjEE!R33j|rAh;&S?73btVI)$B)X4J{slL~HtPTY literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PROFILE4.BGF b/CONTENT/BT/VIDEO/GEO/PROFILE4.BGF new file mode 100644 index 0000000000000000000000000000000000000000..8ecebc701ff49be9945a75751506439c787c5045 GIT binary patch literal 1402 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 yCy6;z=Q_%d5fA)aI*ugxxP^Ld`{_xn7* zmz?|}>xTT&427hX8|3mZg+Z}MRiQM<)!E?&nan5IUzRl2PFvCFF@r>{EYAizB-6(D zjd(}R`nf8$#h~SKKrHk5{pNE0q0BPKqz$fVWx7Ep+g9(Z^)$RxW3Srj-C9#u?ydJo zv>ul0x~yz*?Nj{N9fyO3GLh%R7AyF5qwEVy3KjV0E}~7tW-!=KYh5pS5@}LpW2D1C~sMLYhAY zJI}aiISZ`4$*j2Bx!OxR%?oM@(pJga#mR)sNnD^qc2j9m9=W1w4GqVGe z47EL>;#p~)Yjw7tpLpba?00nV^F4fzma!7X@1ZG<#ecVWMXalREsXC=hLShpQTg-k z`Fsr)DCkaux^FYEBV^CKD{N=M{B(F`Z6>yM)C-44ee9RK6fk-m*w|(hZus^OPN<21 zLtoo4u)_&R@yN)NhjQ{FSTrD=r>l>nT@uO=6?rY;(yNSPC4|Qu;P)h zCb4g5Q$O?8u7QSuMC>`gS2+3JaJUq^20jaza5Q(naILSX;KfJ>6bGybm)eBeZR=-C z-*rN8#E21n9l~YQsp0T(fbjt%UNjsN?#hfBwvQCRxwn$=ZU0H(dbi5pZdVD69ZY@j zKi)odm3=r}3W4X-uwrUH_UOt!Hhbz>@RhH^8)JSE`$@!ER&i@RY?d7SHOdG%p&*nC z^T()u$-S;`R8wVu)B`8L@)kj_2kz hjD%ZS9ipLr2@ypsCA5T&;Psv$%!GwVA$T3S|Nk#jUBmzY literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PROFILE8.BGF b/CONTENT/BT/VIDEO/GEO/PROFILE8.BGF new file mode 100644 index 0000000000000000000000000000000000000000..ab86090a2e30acdf00b5abf72ea6aaf5ae65d881 GIT binary patch literal 1462 zcmX|=3rv$&6o7vUMQ|XS0>#f2f$2_1#<>Y$Vg_$WAvOpsOC z3}!Q;6UnleIYY8#Au!xQnJ@&y2O%Ec4kaMaBl)EgiUiM)(^XjL zbfk@`Lt*b?-PI>N%-&x<3dK9pFqwrAsYs9p%UmroiuHy0`}1@Wxg`Z^-M;q=it`1E z+r%jRq%{h(w3B4wXzqEwPQ`95goj1J#4|P4p6KMRc}xc_mU$5Dn}xSidb!j0q(g*f z5yTsfc;-PLcm4Cv#HMZoY#1rW)4tu@)jWA14s_+ih3$vY>C3a+IYy0(XOb20uSYgo zD66>Be4Gl2x4gg|jkvzqz@6;moOn0Q9fEX5T*%7d&MoJ;_}2j!z`c6hk`v8c%eEkB z^_PJDrUt186|4_tbp||~9+58$rlPYtO3qx_ol592FA>i!S7Td?J)e8vkpYweH$?f; zOsrn9mAl+g#ntD|i8;}GaQ@K;5v;!Gwpyr_{3bV# zl%b}#oS(z-`ahyEKn9@|`*FOhpS#dA4v^4O0-N{ep(k!YI z$&7_HULQhxQYqf=ALh<;&;_PEE1-0z7Td>1xvP=JLtumn8s5-i>CUOeJX1W>?W%=* z+k#i$r`?Pk(zl)fb+Q3V$7Xn5uW2K6bRGvkw-TKBZ<4#vD0jHmbPW6lOYw%|AKc}B z?gS@OE8$dD6*k_!#9i>Jqhej?+raL_&6*3`p}A5VDcla<+L^F-s*$^=X&vHFUo>0^ zF30lAN4e`BoD>a7-jMt0L9DMn&YgarH5@z;1jhzSv2WWI?w+4_f*-Ro;Bj*q?zr2- z-Jfqwi`ick!pa@H(RAu-?q(mF;irj27@1Sy^_sERHerxik4GaM>>qx_q+noB1;CzEh>bRrG+w3=QgN-)P_EQjSX$6``~?Zeh#j~lUya3@y3c(3X8x~1uwTb8bWO|@AHfoVi;Ff*9>18U(#K{u(X8ThlQ5E7yGW70(s zB(7Z<5mE#t(N%VKFGE+N%PtC(2!p^b?7sJ%nKQe2;AOvg=Ka3!%zS63zWL(uy5`H( zK9TR$yxvTo=F9bWWN6;NnJmrYiHgXu$P@N5R+Gt(vx<;cz{Wq@{0O)?z_3NaIVj|Q#7U5)Vy=+jV-rX_0pKk zTWNEBsz=0k%j!X&!{iq*_5d@~{u0?MI`>DWa_41GK zS*uYAnkDDQxnX|)06p)kdH?_b literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PWIN2.BGF b/CONTENT/BT/VIDEO/GEO/PWIN2.BGF new file mode 100644 index 0000000000000000000000000000000000000000..b865e6858452a4311be64fd26e4cda9df49c19f7 GIT binary patch literal 1528 zcmZ9M-Afcv7{Y(0u7cee;zn zpUCrSUT=m^^W_9O{F*mdm#KL?QBgZAa)rH&)nxMXSg6#zDI(8j!wFI#iP#ik9JgC^ zGPO)|I&ez!hdF|E(K?wIidQgWX-jo!5G<4vh8-crwnLYyK&-$%lGz z=CjsBtj~Cq-@&$VUQ@679vi`e|Csy*_M~VM_uX7sFxzL`E1cA;t3SH+ZZEf4_0pKk zU1@WDsz;Yz|{Ux$ibncH#<<7~F%2iCBj)%7A%ADYe&i!G}ZoP$} z8LM6zlRu&}u21!-THDl}ci{HuSl`sSzuw-TZoP*2Myno~%8i^`vU1ayY(KxWJy*`X zZM6E@v$f~(ZmipSf9X9owqo0vJozVPz02(s^?Hliqb{Pm-?Nw=$ALDQ4n)RyH$*QPW9IOhetO8sc#nS8;D;v!?Sb|}dC)#+Ka>v@ zKxB-=5WR&^5yYHgh<UR=L@ya*4dONZ^pI;1 z@6pd1<}7Y{47ywrDauydfND)k8z*Qdlq*b?d>OvLH2$ literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PWIN3.BGF b/CONTENT/BT/VIDEO/GEO/PWIN3.BGF new file mode 100644 index 0000000000000000000000000000000000000000..c790b0cfe6c2881d4f9d7dd141766071e4079ed4 GIT binary patch literal 1528 zcmZ9MT}TvB7>3X8x~2J(Tb8bWO|@AHfw&R5!OURh52%F~1>K~kX5i1JLP&(#k4YCn zkhpebL`V^&L|56_y$oH6F1sjDA`Ak%u>0P3X3p&9ftUT}nfLp?GxMFD`sPa~>zc3B z_(XwM^LjIVnlI1ak)e5W&t_>JPgF#PMZU0?v6f7J91oP6H$~{#TrfcjBoUiJOyG8l zPNtS=&iGGj9#Lod{nc8~(={3$>c4ekFfuaQIoRDb+cD8ffG4xTT+f&`n|!Dj zXFh99#`=thg&k}g=QZ`b?~##P^dFPI!5)`P;l7(Ii{|=_yTwy_IQ-77H@4Dd)k|YC zf3?l^sU8vEZL0@;4wGNN*aOT^`%7f6>f9fh%AJ=1m8+OM6A$dnm3g_VI`@Y?yY&`_ zX03W@On#5fx<1vTW_?R{-htbrV`EF_{(5_Vy7lT88m)R{DmQd~*~(30vb|w>XRe%o z)oAs#XKT;n^?0}S{?dDFZpU^qdFpS>dZ%f*vVEf4Vr$79Q|+bp+>A3zm&yBJ_AFhd ze+pJP&+9T7Dy?$&tm-uf-dgq2pY17_^Iqc0_wvH5^0{ZDB|NE~Lopcx|^U7$1c~5Er(?hO7 zyhlH4R6xg}6Hp~oCmvL51*z}gVCO(jIQ0n>*Qdor*b?d>{CfX2@>zO0U@&`;RgT>O fs%^__3)FQK0r=(nSy? zu3eN7Aw`hVWp>=VLf4D_fC9Y;F9N%;%b@3(nKQe2;L&$}^StkSX5OOD^JN7({F*mdo3430QBgB2vW2~jwM63cSg6>%DI(8j!*Nm|iP#ik9JgC^ zGPO)|I&fO^h&nS6DA&TCuF>dF|E(K?H6x>)gWX-jo!5G<4vh8-c+wiob^nyv z=CjsBtj~Cq+rhTWyry3DJvM@Q|1tRs>`B2S?z_1%Z?@04mp`djR(^Er-Ck+4>ZLH5 zz1rsbRF4|p9jga@4wK)&*aOT^`-^9+>f9fh%AJ!Tm8+OMvmDx)E3<;DI`@Y?yY&`^ zW~_QCO#X<@xIWdRVtq?@-htbrV`EF_{(5_Vy7lVk8?Aa|DmQX|$;wS(vb|wxXRe%k z+i3N*XKT;n-B`Ev{!)8vZpU^qS@kDoz0;Ij**@NFv9&~|srFKRZrYip%j5$vdzLQK zzlO`4=XIHk6qdPrR`r@gAFO(*&-M(=c`wV#_vXTk^0{ZDrE)?&hhj1Y#u=fW%9X#7 z>+CPC>b);oRL`N96vc~{FZnxZ(Jyb#TRl>kd=17PI8&zm8%oH9k^4sG$~NXWZVBf> zZW!OIlZ+=&2(nM5QFxeZFXoc9nom7`A`j$+e2@j4IDr4V9L9JzL@ya*=J1+}dE{ig zM?dSOLFv#QC zgUA?%A$s$n0*E<<5dHMfTLjTZKWh|2hae3)3>|^U7$1cq5EMVXrSI?;1(Q4{<`0F}GEOI6iBZoFC_g`TYZMv8dGm literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PWIN5.BGF b/CONTENT/BT/VIDEO/GEO/PWIN5.BGF new file mode 100644 index 0000000000000000000000000000000000000000..a1c7e53fecdc805dbb513848db0aa5aac18a715b GIT binary patch literal 1528 zcmZ9MT}TvB7>3X8x~1uwTb8bWO|@AHfoMf;Ff*9>18U(#K{u(X8ThlQ5E7yGW70(s zB(7Z<5mE#t(N%VKFGE+N%PtC(2!p^b?7sJ%nKQe2;AOvg=Ka3!%zS63zWL(uy5`H( zK9TR$yxvTo=F9bWWN6;NnJmrYiHgXu$P@N5R+Gt(vx<;cz{Wq@{0O)?z_3NaIVj|Q#7U5)Vy=+jV-rX_0pKk zTWNEBsz=0k%j!X&!{iq*_5d@~{u0?MI`>DWa_41GK zS*uYAnkDDQxnX|)06)vCegFUf literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PWIN6.BGF b/CONTENT/BT/VIDEO/GEO/PWIN6.BGF new file mode 100644 index 0000000000000000000000000000000000000000..66150d7744ac11c5c396fada7396a6f8107adaaa GIT binary patch literal 1528 zcmZ9M-Afcv7{s%^__3)FQK0r=(nSy? zu3eN7Aw`hVWp>=VLf4D_fC9Y;F9N%;%b@3(nKQe2;L&$}^StkSX5OOD^JN7({F*mdo3430QBgB2vW2~jwM63cSg6>%DI(8j!*Nm|iP#ik9JgC^ zGPO)|I#8u~M4cH3lxty6*JyO8|JIGcnvv1Y!S1f%&TBna2S)n^JZTN)x_`=S@}b@` z^I2;m)@MA*?O@wwUQ@679vi{D|Csy*_M~7E_uX8XH`{02%b(OMD?hsRZm+ai^-`G3 zUTt%Isz;6Qj@5%chskeX>;Yz|{lzm@b?%Q$<<7~F%2iCBSq|;Ym07`6o%_R{-Fgc{ zGgiG6CVxa{T%YPuvA(4{@4)TRv9YCdf4#jw-Fo%&jaEG}l^Z#~WaXwX+1{|UGgr>N zZM6E@v$f~(ZmipSf2ln-w_`h*JpCtTz0;Ij**@NFv9&~|srFKRZrYip%j5$vdzLQK zzlO`4=XIHk6qdPrR`r@gAFO(*&-M(=c`wV#_vXTk^0{ZDrE)?&hhj1Y#u=fW%9X#7 z>+CPC>b);oRL`N96vc~{FZnxZ(Jyb#TRl>kd=17PI8&zm8%oH9k^4sG$~NXWZVBf> zZW!OIlZ+=&2(nM5QFxeZFXoc9nom7`A`j$+e2@j4IDr4V9L9JzL@ya*=J1+}dE{ig zM?dSOLFv#QC zgUA?%A$s$n0*E<<5dHMfTLjTZKWh|2hae3)3>|^U7$1cq5EMVXrSI?;1(Q4{<`0F}GEOI6iBZoFC_g`TYZNpQzUW literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PWIN7.BGF b/CONTENT/BT/VIDEO/GEO/PWIN7.BGF new file mode 100644 index 0000000000000000000000000000000000000000..184ab969a09be839ded9dcb7547ad4443820d4b9 GIT binary patch literal 1528 zcmZ9MT}TvB7>3X8x~1uwTb8bWO|@AHfoN22Ff*9>18U(#K{u(X8ThlQ5E7yGW70(s zB(7Z<5mE#t(N%VKFGE+N%PtC(2!p^b?7sJ%nKQe2;AOvg=Ka3!%zS63zWL(uy5`H( zK9TR$yxvTo=F9bWWN6;NnJmrYiHgXu$P@N5R+Gt(vx<;cz{Wq@{0O)?z_3NaIVj|Q#7U5)Vy=+jV-rX_0pKk zTWNEBsz=0k%j!X&!{iq*_5d@~{u0?MI`>DWa_41GK zS*uYAnkDDQxnX|)06@8`fB*mh literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/PWIN8.BGF b/CONTENT/BT/VIDEO/GEO/PWIN8.BGF new file mode 100644 index 0000000000000000000000000000000000000000..66ac11f0c4306d35958931628c7cf5fd938d77dc GIT binary patch literal 1528 zcmZ9M+e;K-7{F%s%(7(DkA}pg=Fei@+}IGU$0`=9}I8;L&$}^Stl-&Ai`Eee+ZMx?1L`BW8$QJf8))I-&W1(X6rieVB4aZ4=Bw|yDaoldv z$<#8<>A)GyBkIgRpj-=kx<;cz{kLum){KmH4t949cV6qcIxyNV;7MyR*ZoswlMnTl zna^4iu|DHbZU@^g^O}0q_t*&L{m0}luqOqRxbNo5yxBhEUjC$BS^3eecYCGHs+YoK z_G+8!Q$1>YcdQ=tIZS>7V-GMx?Ju6Os&jv2DtAtXRIXyOYB{tsS7rrQb?y&)cIzz+ z%~Y&J^7NmW^-fcAW&3!y#nuv;rrJyOxoKyXE|U+y>{+@@ z{~9iHp4VkEQds8hS=DO}eX#1KKHD=e=e;Z|--PBNZAA;>ylW&GKg0=1#@tpB;`ppta(Tqm-q~$xZLe`!JC3#%!1lH%P{s*{pVCjM^+>V>*-Kp%Z00I zA5}J;jA`s#=^oU#em$ckM28Go;v&G8A*2Ifw*iqSLtrawSwsq}@ z_SJv3YisxZ?%kjE^zI^5udvFjRn2Q6&Fj~;b~IbHeRZ|6wp!Gpl19I>jLx`o9oVm?xM^30%SmKyNt#{+y%mSJS6o~`%({%P@4}m2Fqk+v4X4sD~~mg zRl+J|6|?3}sfe$$Sg6ASV-J0}ryouItZY^e3nRr9_vnky;WPQH*{lNA99H4f75C_e z^Kfoh6(JZ1#lre~91Jt#VBFzg)EPgVN}J|2+&c(n&1chXs~STQZU|hmzx$^|7>0Mo z2Ndyod!X@~ZqhNtQ0S;eO-0EG9&}6?eK-KZS0|5g7}A6DhQ}MK|1(f;7`!3ba3dX_ zgx`G;9<(%SW(f?KYlIQ7N7q(LVDM5f%RV?lVc&lZ%{wdv$Qv942=`^Ia#n<@{Hb6d zbO;Rsk_raGgCHUx5h_RN8v#v)E3A4A4g~^HaHz;})HWm2UyDUXKTY&rbmxRwp8YGP z`Bjh;B``}nzO!({<_w9B5qrz?u@`dq&dFL_HEdPBH7JonbbAx6U z-@#UwJA?I;Cw1a`_eTo+&~%?Od+t~I;4d!!T-Bkw4p(X7b*B0goikn|eC?+g&upnL z<+s=8nO;E5^4-3N;5$5jzPZ71RAr{V)8GAc?zcYoD>MWKb?*6?Jhm#nY`?l$CJd{Y z74ZUdjqrzGkJ@8WFC{C@d~ FUIS^~%L4!a literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/BLH_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/BLH_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..450c45ddf90ce429d094933f3c628ce85bf483e0 GIT binary patch literal 1903 zcmbVNO=uHQ5S~q%{=^#Fx@vndD|%>4m1yv<5b`!yYr!A}@t{Gi#URv5qXkPVW&5)g zJT!Vy6E9*b-h#&*#4h!wDSC@|E1o0@y;Lt1obScAq@tHT7uRsm7@k0=!O*l}>b^xyR-sL1Shooy5kz7UId*wc6n6WhzcBnOs^@!ozl=K^ zmwskxjpMs`4_V>xfD`fml<{zQ+Tl9Vf4eq{`Z8x_Y(#VrT^`0J7ZEI z2k)w!iL8jfPQ=Nq;k~4>dDy(T;f3oqwkEcnY)IP0*80astc}gb7N@g5JcnP)R>uZv z8`%78SX2 zv$k3BJY(_H^BF2)u*(M-tvP=yCTu^FI|yjmR`6b zNu_3;j^s9eA6YDBR{-Ps0aqlvH>$*t%(So=_SF1MBFIoguq(;NwOTO90qG!Lkq*KU zQ^YI6IkbUn)B)K_YlZ@LsJMHC(_}4J^2*#$SC{{??KjcJTN=%~bRLuYm<#)x6;z!vgFP2ll`j3pmHA z!-sne75GwEV?YtZGsTxl?-+hS|NT-V7Nggj95tG@=v+0Js;OMI&*ArBS*7_`u2Ai= z=~RQJzMP!4VJPC%jD9x=GEO_tw-k~B22GhX$IYOT)cK|pF|sz>Os_>D)eQb|N>vg6 U9ibY-e^4ny&p&qlbx=OsZ^9G3YXATM literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/FIR_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/FIR_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..22f221d30a48f9101c49c6cc36e56fc30e05baa8 GIT binary patch literal 1648 zcmbVNT}YEr7(U0jz||-Rx(8fIVh9d zMFe&cmG`^oY8Qs5cG(X>7we*^5mw}aF5Iqr-?PqFN)+tC!}pwb@A-S4_ndY24>r5{ z{jFLeYZQ$}r&YA2B_l}uixLJ*k(Fxyp1ZPm)?;gR3{aEX<|5={Cdlgd}HPO!^b*i-q*_c zb>?Tu>>}sM?2yXi?rQ2Wb?~?^VWtUlw2MGnX&hjIr)j)`ro&sD<2(;;$_(R+mXqvV%1)6t1csR}(Z#u4Uq#pM zE^?j@%PMbc8-sn`;PWKRwG_Am$EH>ls!!ECLEf@*71n+FE9VOH5N~k_#7hAvZy7)j z*aavDQ~)FZHq60X{A~|lF936}k8v4b0(eLZcKJ9Be6@fgKrz4oz%_8K-GEAf5#XeA zXfT@F*!dg`4i#*0n-n1|VQywHElHTO4ombF=fU706C8cacz^o{afwH>}VQL?{kxYIA; zkMIq3#=#!aP>kMS9Q77{3jHyTexMIdYDN7~d&9iZ<)Q}*)t`KdkXWvMiNUNSx>>DC zm8&n`CY8vMFrtE%IHaT7jWt+DpVK%8ex;d(rd0)CwE%RXTh+5_^U(Bg;_NBv6 z=GFg|6Xg=pp`_wEUmYX}TmXe1UxfY^~@OpZP36H+*s^XcQ~@hzq33i*h)q2B_{fU~AKy^H@sB{{Oxe$aY59%fM#MV;yZi}s%6c3C literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/LOK_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/LOK_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..0cf4b3d446b7893c633f2d6688ec9c69f03ed6bb GIT binary patch literal 1886 zcmb`ITSyd97{|}->gsxHwT+CV1~TzNxEf`++MZq4F{>erP|(OM-2&Iu)j)fRtq{6_ zOAm=X)JsnhQ4kVQ+o7i@B`Bgmy7^#;1=d3^cKiMlXBa^Wmk#`yKj$)M=KG!RJHf{0 zO@YSNN;`AgRGTf`uG-Ta2UApAj>oAgN*}B4XRi0zi3g0DID6}UrSl$-vck35ae*$^ z?0~pYaE`;z7DbIGJR0W+?6hn+=NLwed2(f8>-8b9(d2_@}0P4qq^*33`vwFWQ1wYxEB$ zp81C7DhxmAEu#L_hR434(9CvP%DjF3f_wtLVk{z}wL6XP(Z<_2dE=d(-WGm&tVCeW z$)bpmu`3+yHvOH)Gd>x|#MLLJKmVgcj6B-Hv9>(YE*e-?Dp?09jij^O6g;y@IV6nf ztO*aMkZdG7DTM?8P7>B)LIw$An6rZ9BIS}W2XpgCD@ksW&ek}vPbMjggmdD@IwhP^o04eepJIRxngESuMjuA@f$SRx=!Zot31@5`+-on98FpLm-bR!bHQ1 zLNCMSXICgnh)}566%4R=l6MMgiLn~_bJ}<&$A)OQ&SXixRJUN3m6QdTS;q}ABs2Z6McC20*9G$j@((ptr+v=u*khzK>{ zMX~=t#e)~YQxAH{N!PQ~x?rd0%Sxbyb%goCwMkSqdm~H6WG>a==Dz?eh@pRp1vqzO59`1HZ z#R27uk1ykSQTamODH&}I)%~O3@ecxHvHye=!cqRq%N7T<@Vi!>dXed+-njWI`Uu3$;M4kRNJ;+MymO1Ra15LWiJ~Ncy;jYnh03nV0zk5Z5vXYqB=q zgML56T+G=EF+L^_n}Cg=9gBPdY+bvCt!(6FoUlpcRj~an06K&^oR#zjgzzdqA!!7* z4zLc14y_LJPTQPIr90E13$_<^qYHF?Nw&|dHvASr$nb$KXg2}xCl74?ND=1w;pP@r?q|M zo_?Q>+W+_UU+t?{1+LuE>|{sW7O!?mtGJmL=UiB8pKb^J6#QBh`r4J}mjzyOp8j{R PaxD)SW47M<1O)m8)${Kv literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/OWN_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/OWN_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..001d5da31f8ecf3c508476532207a04acea4e675 GIT binary patch literal 1834 zcmcJQ-%C?r7{}jpW>Z%!ty$K^I#L%dkYZ6Me@#ET9{@Uga@7mEQgeL-&WP4NXh4maD8L+ci*Rw9?UgCHAezGwg67Sajg> zxsRO5i8mbfRJut#VPkRr-h158Se#euokkU0-xuw;$^U3!BcP28UbtwFwwxax7`ire z<=n{iVTR}vM!nJ1(QS2{NhbO_jPU5muvh~I>*S7><%TwuF2;~8Fx~4U3vC>BDD^5< z2o4H668Td4^s!agv<)W{JtgAZ{9??_r-eNh2=ZjXFJdy$13Z-aT%t5=aw6e`Qr*Hv zylp=h@uAdh%JWkA4~~yHV}UjY@ym@rV!uw;3mXN<&E8na6XKcZW#M=8^CjEv6!!Q+ zvy;j_753axBjvv-?A+|v*mC22VMii!B^fi_)liE1o^VDhmD6L=hJSqFuJ9wC@(4RH z{UT}9r)g&LO zhEz+!Z}1Pk z^HFdEGyknx)8v=R=6000IchyNn;&%!RaR;&E#g6-eMDYeaTlDeVnma9bl}vIafCQ7n;PBL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/RAP_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/RAP_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..001d5da31f8ecf3c508476532207a04acea4e675 GIT binary patch literal 1834 zcmcJQ-%C?r7{}jpW>Z%!ty$K^I#L%dkYZ6Me@#ET9{@Uga@7mEQgeL-&WP4NXh4maD8L+ci*Rw9?UgCHAezGwg67Sajg> zxsRO5i8mbfRJut#VPkRr-h158Se#euokkU0-xuw;$^U3!BcP28UbtwFwwxax7`ire z<=n{iVTR}vM!nJ1(QS2{NhbO_jPU5muvh~I>*S7><%TwuF2;~8Fx~4U3vC>BDD^5< z2o4H668Td4^s!agv<)W{JtgAZ{9??_r-eNh2=ZjXFJdy$13Z-aT%t5=aw6e`Qr*Hv zylp=h@uAdh%JWkA4~~yHV}UjY@ym@rV!uw;3mXN<&E8na6XKcZW#M=8^CjEv6!!Q+ zvy;j_753axBjvv-?A+|v*mC22VMii!B^fi_)liE1o^VDhmD6L=hJSqFuJ9wC@(4RH z{UT}9r)g&LO zhEz+!Z}1Pk z^HFdEGyknx)8v=R=6000IchyNn;&%!RaR;&E#g6-eMDYeaTlDeVnma9bl}vIafCQ7n;PBL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/SND_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/SND_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f944a37197d7e8caff63eb47d5276e650abfce78 GIT binary patch literal 1696 zcmbVNYez(!iH~(>-Ml$cfmtO%a&6Vr`B5C zG-*yfAm7qr=fB8t0GK0Y$P%%@TPZ`<jUUF^o6-u1?jTEJJY~Np-eL1h~xvkl-rmJnC(?w7)-9p;k>E3KDbOb zmGe(ACOY)vRRv=fRHx9U>RQhA=4tTZ<^Ue!ZXW}O9P=s0M3%QGHn4HNW9+Syy+>A%c5e)nCkX*}l3!DI@3 zO8{feCOWCcF9gf4?^1Txoagh=8aFNaT+Y{)dTcPVYcJpPk#BQhuzfD)#^a^*1)0oa z8i#MDR$>p2W;tURVi|M{5e&T=)nR+HeMZf!{zYBN?I?dNEj_0u4rUCz>8HgSYkA;5m|yJZ|k!fTbl4IUIJ!6mi~? zJ&P_{+`x4>!!nui^9k9D-V=doA4`eBbDYqJV`N+#;=F@&xK!py$%AI zbzH*>J5%82O5xWodkS4qCw%#G@VjCfC3vaFO*6&_@0@-oZSLI1*S1yU0ONcQ5q;*t z%QoSWIjW5IUz@~Zghxh{@4xg!jWO6t%t*WSMUT)=^a4FW{X?Fk5BQAp=sWstfl25G zdJ(%lUR7aePyHb8eWa=-TeN+t=eKl+O-49yG{DRJ+BK7&ixN^V%vEUJs%u;pm-n|# z4Z%dXS0W^>ywjyTXgv>Xr=%gczFX4P4qLaRT5mSA@5$nMUhgQQ-yey#Ur>#0KjNQ~ zTFHd)ken!8sAW+me8vRb?MphDTBy{grDjznZ9V*VA^{(9ZS62LvE0Nn#17+XMZfOb zW1{NQ3|>sL6{6=;Q16Q|Y(yLb&{tA4>9m zAzbg1ZkkD=Lp9>jw32wPOX!GVomMjFugBR!YFOP^b8%i=no6pATK6I!nH{qajDs7db>_hW5ic{&Yru0gzIBzyJUM literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/STI_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/STI_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..001d5da31f8ecf3c508476532207a04acea4e675 GIT binary patch literal 1834 zcmcJQ-%C?r7{}jpW>Z%!ty$K^I#L%dkYZ6Me@#ET9{@Uga@7mEQgeL-&WP4NXh4maD8L+ci*Rw9?UgCHAezGwg67Sajg> zxsRO5i8mbfRJut#VPkRr-h158Se#euokkU0-xuw;$^U3!BcP28UbtwFwwxax7`ire z<=n{iVTR}vM!nJ1(QS2{NhbO_jPU5muvh~I>*S7><%TwuF2;~8Fx~4U3vC>BDD^5< z2o4H668Td4^s!agv<)W{JtgAZ{9??_r-eNh2=ZjXFJdy$13Z-aT%t5=aw6e`Qr*Hv zylp=h@uAdh%JWkA4~~yHV}UjY@ym@rV!uw;3mXN<&E8na6XKcZW#M=8^CjEv6!!Q+ zvy;j_753axBjvv-?A+|v*mC22VMii!B^fi_)liE1o^VDhmD6L=hJSqFuJ9wC@(4RH z{UT}9r)g&LO zhEz+!Z}1Pk z^HFdEGyknx)8v=R=6000IchyNn;&%!RaR;&E#g6-eMDYeaTlDeVnma9bl}vIafCQ7n;PBL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/THR_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/THR_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..22f221d30a48f9101c49c6cc36e56fc30e05baa8 GIT binary patch literal 1648 zcmbVNT}YEr7(U0jz||-Rx(8fIVh9d zMFe&cmG`^oY8Qs5cG(X>7we*^5mw}aF5Iqr-?PqFN)+tC!}pwb@A-S4_ndY24>r5{ z{jFLeYZQ$}r&YA2B_l}uixLJ*k(Fxyp1ZPm)?;gR3{aEX<|5={Cdlgd}HPO!^b*i-q*_c zb>?Tu>>}sM?2yXi?rQ2Wb?~?^VWtUlw2MGnX&hjIr)j)`ro&sD<2(;;$_(R+mXqvV%1)6t1csR}(Z#u4Uq#pM zE^?j@%PMbc8-sn`;PWKRwG_Am$EH>ls!!ECLEf@*71n+FE9VOH5N~k_#7hAvZy7)j z*aavDQ~)FZHq60X{A~|lF936}k8v4b0(eLZcKJ9Be6@fgKrz4oz%_8K-GEAf5#XeA zXfT@F*!dg`4i#*0n-n1|VQywHElHTO4ombF=fU706C8cacz^o{afwH>}VQL?{kxYIA; zkMIq3#=#!aP>kMS9Q77{3jHyTexMIdYDN7~d&9iZ<)Q}*)t`KdkXWvMiNUNSx>>DC zm8&n`CY8vMFrtE%IHaT7jWt+DpVK%8ex;d(rd0)CwE%RXTh+5_^U(Bg;_NBv6 z=GFg|6Xg=pp`_wEUmYX}TmXe1UxfY^~@OpZP36H+*s^XcQ~@hzq33i*h)q2B_{fU~AKy^H@sB{{Oxe$aY59%fM#MV;yZi}s%6c3C literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV/VUL_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV/VUL_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d6fe8fee668b5802ac36e4db5f8ea285853c74e4 GIT binary patch literal 1582 zcmbW1!D|yi6vk(hCQUUavFV|L$S5LJEJTY|DotmXCSjGOCX^his8tMwwrXvK6jZ7w zJ(!aR!K2ud3VMp9*gYyH9#c>L1r-W<7T@>GhHaXqkb%d1`}V!vnfIGF<7R%)FsDxY zMW0Xld?CN|cL%R`Nna$>(~$Lh0zoA{r`J|rWhq?Ack^TBezx!+wf!mq}dPs zK69AYlaDOZe^*&Q99yRN>Sx5SEloft9ZfO37sOC5Yvg7`zn@}!WL=1*5g^mZERkgw zG~OdFOty~<1J4n%C>h=ZB@7xl`x|pF&GE*wC5{J>hYttIy2%(G%{^p$$o7(94Z2zb zT44Pi`l}o2UB_q_f!2-6jnIwUjc_+SmyM(+9tS^SyzqZ|UT18fx8ZHrywIj!)EV3A zD~{h4Z99HWy&XmlPlqG;fg2d(9iChHAs76>2n@j!yfNGib#(>&!0y-8QNvJH$Nb{N z&;DJiaJ`0~naz3)el&5M*}tz?r{3ay0) a?r7(Lw-zYF+i9K?>;*aQ`^4Elouz+fI$%Wr literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/AVA_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/AVA_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..bc54a5e2803c75bc50a6acc036099c5d880b22d7 GIT binary patch literal 2037 zcmbW2U1$_%6o$`CcJs5wn3y#`H(}ZaC7Nh-v4%jLZzn&Ri$&s3kThCta8+XbskulI zHAdZ<8oIWW_NLHyA$lRf8!^hNpNdp*6APs@r6NiM3sn#=S}#5CnQV5HM$3NiGS7UR zJ>Tqm-q~$xZLe`!JC3#%!1lH%P{s*{pVCjM^+>V>*-Kp%Z00I zA5}J;jA`s#=^oU#em$ckM28Go;v&G8A*2Ifw*iqSLtrawSwsq}@ z_SJv3YisxZ?%kjE^zI^5udvFjRn2Q6&Fj~;b~IbHeRZ|6wp!Gpl19I>jLx`o9oVm?xM^30%SmKyNt#{+y%mSJS6o~`%({%P@4}m2Fqk+v4X4sD~~mg zRl+J|6|?3}sfe$$Sg6ASV-J0}ryouItZY^e3nRr9_vnky;WPQH*{lNA99H4f75C_e z^Kfoh6(JZ1#lre~91Jt#VBFzg)EPgVN}J|2+&c(n&1chXs~STQZU|hmzx$^|7>0Mo z2Ndyod!X@~ZqhNtQ0S;eO-0EG9&}6?eK-KZS0|5g7}A6DhQ}MK|1(f;7`!3ba3dX_ zgx`G;9<(%SW(f?KYlIQ7N7q(LVDM5f%RV?lVc&lZ%{wdv$Qv942=`^Ia#n<@{Hb6d zbO;Rsk_raGgCHUx5h_RN8v#v)E3A4A4g~^HaHz;})HWm2UyDUXKTY&rbmxRwp8YGP z`Bjh;B``}nzO!({<_w9B5qrz?u@`dq&dFL_HEdPBH7JonbbAx6U z-@#UwJA?I;Cw1a`_eTo+&~%?Od+t~I;4d!!T-Bkw4p(X7b*B0goikn|eC?+g&upnL z<+s=8nO;E5^4-3N;5$5jzPZ71RAr{V)8GAc?zcYoD>MWKb?*6?Jhm#nY`?l$CJd{Y z74ZUdjqrzGkJ@8WFC{C@d~ FUIS^~%L4!a literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/BLH_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/BLH_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..450c45ddf90ce429d094933f3c628ce85bf483e0 GIT binary patch literal 1903 zcmbVNO=uHQ5S~q%{=^#Fx@vndD|%>4m1yv<5b`!yYr!A}@t{Gi#URv5qXkPVW&5)g zJT!Vy6E9*b-h#&*#4h!wDSC@|E1o0@y;Lt1obScAq@tHT7uRsm7@k0=!O*l}>b^xyR-sL1Shooy5kz7UId*wc6n6WhzcBnOs^@!ozl=K^ zmwskxjpMs`4_V>xfD`fml<{zQ+Tl9Vf4eq{`Z8x_Y(#VrT^`0J7ZEI z2k)w!iL8jfPQ=Nq;k~4>dDy(T;f3oqwkEcnY)IP0*80astc}gb7N@g5JcnP)R>uZv z8`%78SX2 zv$k3BJY(_H^BF2)u*(M-tvP=yCTu^FI|yjmR`6b zNu_3;j^s9eA6YDBR{-Ps0aqlvH>$*t%(So=_SF1MBFIoguq(;NwOTO90qG!Lkq*KU zQ^YI6IkbUn)B)K_YlZ@LsJMHC(_}4J^2*#$SC{{??KjcJTN=%~bRLuYm<#)x6;z!vgFP2ll`j3pmHA z!-sne75GwEV?YtZGsTxl?-+hS|NT-V7Nggj95tG@=v+0Js;OMI&*ArBS*7_`u2Ai= z=~RQJzMP!4VJPC%jD9x=GEO_tw-k~B22GhX$IYOT)cK|pF|sz>Os_>D)eQb|N>vg6 U9ibY-e^4ny&p&qlbx=OsZ^9G3YXATM literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/FIR_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/FIR_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..22f221d30a48f9101c49c6cc36e56fc30e05baa8 GIT binary patch literal 1648 zcmbVNT}YEr7(U0jz||-Rx(8fIVh9d zMFe&cmG`^oY8Qs5cG(X>7we*^5mw}aF5Iqr-?PqFN)+tC!}pwb@A-S4_ndY24>r5{ z{jFLeYZQ$}r&YA2B_l}uixLJ*k(Fxyp1ZPm)?;gR3{aEX<|5={Cdlgd}HPO!^b*i-q*_c zb>?Tu>>}sM?2yXi?rQ2Wb?~?^VWtUlw2MGnX&hjIr)j)`ro&sD<2(;;$_(R+mXqvV%1)6t1csR}(Z#u4Uq#pM zE^?j@%PMbc8-sn`;PWKRwG_Am$EH>ls!!ECLEf@*71n+FE9VOH5N~k_#7hAvZy7)j z*aavDQ~)FZHq60X{A~|lF936}k8v4b0(eLZcKJ9Be6@fgKrz4oz%_8K-GEAf5#XeA zXfT@F*!dg`4i#*0n-n1|VQywHElHTO4ombF=fU706C8cacz^o{afwH>}VQL?{kxYIA; zkMIq3#=#!aP>kMS9Q77{3jHyTexMIdYDN7~d&9iZ<)Q}*)t`KdkXWvMiNUNSx>>DC zm8&n`CY8vMFrtE%IHaT7jWt+DpVK%8ex;d(rd0)CwE%RXTh+5_^U(Bg;_NBv6 z=GFg|6Xg=pp`_wEUmYX}TmXe1UxfY^~@OpZP36H+*s^XcQ~@hzq33i*h)q2B_{fU~AKy^H@sB{{Oxe$aY59%fM#MV;yZi}s%6c3C literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/LOK_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/LOK_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..0cf4b3d446b7893c633f2d6688ec9c69f03ed6bb GIT binary patch literal 1886 zcmb`ITSyd97{|}->gsxHwT+CV1~TzNxEf`++MZq4F{>erP|(OM-2&Iu)j)fRtq{6_ zOAm=X)JsnhQ4kVQ+o7i@B`Bgmy7^#;1=d3^cKiMlXBa^Wmk#`yKj$)M=KG!RJHf{0 zO@YSNN;`AgRGTf`uG-Ta2UApAj>oAgN*}B4XRi0zi3g0DID6}UrSl$-vck35ae*$^ z?0~pYaE`;z7DbIGJR0W+?6hn+=NLwed2(f8>-8b9(d2_@}0P4qq^*33`vwFWQ1wYxEB$ zp81C7DhxmAEu#L_hR434(9CvP%DjF3f_wtLVk{z}wL6XP(Z<_2dE=d(-WGm&tVCeW z$)bpmu`3+yHvOH)Gd>x|#MLLJKmVgcj6B-Hv9>(YE*e-?Dp?09jij^O6g;y@IV6nf ztO*aMkZdG7DTM?8P7>B)LIw$An6rZ9BIS}W2XpgCD@ksW&ek}vPbMjggmdD@IwhP^o04eepJIRxngESuMjuA@f$SRx=!Zot31@5`+-on98FpLm-bR!bHQ1 zLNCMSXICgnh)}566%4R=l6MMgiLn~_bJ}<&$A)OQ&SXixRJUN3m6QdTS;q}ABs2Z6McC20*9G$j@((ptr+v=u*khzK>{ zMX~=t#e)~YQxAH{N!PQ~x?rd0%Sxbyb%goCwMkSqdm~H6WG>a==Dz?eh@pRp1vqzO59`1HZ z#R27uk1ykSQTamODH&}I)%~O3@ecxHvHye=!cqRq%N7T<@Vi!>dXed+-njWI`Uu3$;M4kRNJ;+MymO1Ra15LWiJ~Ncy;jYnh03nV0zk5Z5vXYqB=q zgML56T+G=EF+L^_n}Cg=9gBPdY+bvCt!(6FoUlpcRj~an06K&^oR#zjgzzdqA!!7* z4zLc14y_LJPTQPIr90E13$_<^qYHF?Nw&|dHvASr$nb$KXg2}xCl74?ND=1w;pP@r?q|M zo_?Q>+W+_UU+t?{1+LuE>|{sW7O!?mtGJmL=UiB8pKb^J6#QBh`r4J}mjzyOp8j{R PaxD)SW47M<1O)m8)${Kv literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/OWN_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/OWN_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..001d5da31f8ecf3c508476532207a04acea4e675 GIT binary patch literal 1834 zcmcJQ-%C?r7{}jpW>Z%!ty$K^I#L%dkYZ6Me@#ET9{@Uga@7mEQgeL-&WP4NXh4maD8L+ci*Rw9?UgCHAezGwg67Sajg> zxsRO5i8mbfRJut#VPkRr-h158Se#euokkU0-xuw;$^U3!BcP28UbtwFwwxax7`ire z<=n{iVTR}vM!nJ1(QS2{NhbO_jPU5muvh~I>*S7><%TwuF2;~8Fx~4U3vC>BDD^5< z2o4H668Td4^s!agv<)W{JtgAZ{9??_r-eNh2=ZjXFJdy$13Z-aT%t5=aw6e`Qr*Hv zylp=h@uAdh%JWkA4~~yHV}UjY@ym@rV!uw;3mXN<&E8na6XKcZW#M=8^CjEv6!!Q+ zvy;j_753axBjvv-?A+|v*mC22VMii!B^fi_)liE1o^VDhmD6L=hJSqFuJ9wC@(4RH z{UT}9r)g&LO zhEz+!Z}1Pk z^HFdEGyknx)8v=R=6000IchyNn;&%!RaR;&E#g6-eMDYeaTlDeVnma9bl}vIafCQ7n;PBL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/RAP_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/RAP_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..001d5da31f8ecf3c508476532207a04acea4e675 GIT binary patch literal 1834 zcmcJQ-%C?r7{}jpW>Z%!ty$K^I#L%dkYZ6Me@#ET9{@Uga@7mEQgeL-&WP4NXh4maD8L+ci*Rw9?UgCHAezGwg67Sajg> zxsRO5i8mbfRJut#VPkRr-h158Se#euokkU0-xuw;$^U3!BcP28UbtwFwwxax7`ire z<=n{iVTR}vM!nJ1(QS2{NhbO_jPU5muvh~I>*S7><%TwuF2;~8Fx~4U3vC>BDD^5< z2o4H668Td4^s!agv<)W{JtgAZ{9??_r-eNh2=ZjXFJdy$13Z-aT%t5=aw6e`Qr*Hv zylp=h@uAdh%JWkA4~~yHV}UjY@ym@rV!uw;3mXN<&E8na6XKcZW#M=8^CjEv6!!Q+ zvy;j_753axBjvv-?A+|v*mC22VMii!B^fi_)liE1o^VDhmD6L=hJSqFuJ9wC@(4RH z{UT}9r)g&LO zhEz+!Z}1Pk z^HFdEGyknx)8v=R=6000IchyNn;&%!RaR;&E#g6-eMDYeaTlDeVnma9bl}vIafCQ7n;PBL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/SND_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/SND_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..f944a37197d7e8caff63eb47d5276e650abfce78 GIT binary patch literal 1696 zcmbVNYez(!iH~(>-Ml$cfmtO%a&6Vr`B5C zG-*yfAm7qr=fB8t0GK0Y$P%%@TPZ`<jUUF^o6-u1?jTEJJY~Np-eL1h~xvkl-rmJnC(?w7)-9p;k>E3KDbOb zmGe(ACOY)vRRv=fRHx9U>RQhA=4tTZ<^Ue!ZXW}O9P=s0M3%QGHn4HNW9+Syy+>A%c5e)nCkX*}l3!DI@3 zO8{feCOWCcF9gf4?^1Txoagh=8aFNaT+Y{)dTcPVYcJpPk#BQhuzfD)#^a^*1)0oa z8i#MDR$>p2W;tURVi|M{5e&T=)nR+HeMZf!{zYBN?I?dNEj_0u4rUCz>8HgSYkA;5m|yJZ|k!fTbl4IUIJ!6mi~? zJ&P_{+`x4>!!nui^9k9D-V=doA4`eBbDYqJV`N+#;=F@&xK!py$%AI zbzH*>J5%82O5xWodkS4qCw%#G@VjCfC3vaFO*6&_@0@-oZSLI1*S1yU0ONcQ5q;*t z%QoSWIjW5IUz@~Zghxh{@4xg!jWO6t%t*WSMUT)=^a4FW{X?Fk5BQAp=sWstfl25G zdJ(%lUR7aePyHb8eWa=-TeN+t=eKl+O-49yG{DRJ+BK7&ixN^V%vEUJs%u;pm-n|# z4Z%dXS0W^>ywjyTXgv>Xr=%gczFX4P4qLaRT5mSA@5$nMUhgQQ-yey#Ur>#0KjNQ~ zTFHd)ken!8sAW+me8vRb?MphDTBy{grDjznZ9V*VA^{(9ZS62LvE0Nn#17+XMZfOb zW1{NQ3|>sL6{6=;Q16Q|Y(yLb&{tA4>9m zAzbg1ZkkD=Lp9>jw32wPOX!GVomMjFugBR!YFOP^b8%i=no6pATK6I!nH{qajDs7db>_hW5ic{&Yru0gzIBzyJUM literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/STI_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/STI_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..001d5da31f8ecf3c508476532207a04acea4e675 GIT binary patch literal 1834 zcmcJQ-%C?r7{}jpW>Z%!ty$K^I#L%dkYZ6Me@#ET9{@Uga@7mEQgeL-&WP4NXh4maD8L+ci*Rw9?UgCHAezGwg67Sajg> zxsRO5i8mbfRJut#VPkRr-h158Se#euokkU0-xuw;$^U3!BcP28UbtwFwwxax7`ire z<=n{iVTR}vM!nJ1(QS2{NhbO_jPU5muvh~I>*S7><%TwuF2;~8Fx~4U3vC>BDD^5< z2o4H668Td4^s!agv<)W{JtgAZ{9??_r-eNh2=ZjXFJdy$13Z-aT%t5=aw6e`Qr*Hv zylp=h@uAdh%JWkA4~~yHV}UjY@ym@rV!uw;3mXN<&E8na6XKcZW#M=8^CjEv6!!Q+ zvy;j_753axBjvv-?A+|v*mC22VMii!B^fi_)liE1o^VDhmD6L=hJSqFuJ9wC@(4RH z{UT}9r)g&LO zhEz+!Z}1Pk z^HFdEGyknx)8v=R=6000IchyNn;&%!RaR;&E#g6-eMDYeaTlDeVnma9bl}vIafCQ7n;PBL;wH) literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/THR_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/THR_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..22f221d30a48f9101c49c6cc36e56fc30e05baa8 GIT binary patch literal 1648 zcmbVNT}YEr7(U0jz||-Rx(8fIVh9d zMFe&cmG`^oY8Qs5cG(X>7we*^5mw}aF5Iqr-?PqFN)+tC!}pwb@A-S4_ndY24>r5{ z{jFLeYZQ$}r&YA2B_l}uixLJ*k(Fxyp1ZPm)?;gR3{aEX<|5={Cdlgd}HPO!^b*i-q*_c zb>?Tu>>}sM?2yXi?rQ2Wb?~?^VWtUlw2MGnX&hjIr)j)`ro&sD<2(;;$_(R+mXqvV%1)6t1csR}(Z#u4Uq#pM zE^?j@%PMbc8-sn`;PWKRwG_Am$EH>ls!!ECLEf@*71n+FE9VOH5N~k_#7hAvZy7)j z*aavDQ~)FZHq60X{A~|lF936}k8v4b0(eLZcKJ9Be6@fgKrz4oz%_8K-GEAf5#XeA zXfT@F*!dg`4i#*0n-n1|VQywHElHTO4ombF=fU706C8cacz^o{afwH>}VQL?{kxYIA; zkMIq3#=#!aP>kMS9Q77{3jHyTexMIdYDN7~d&9iZ<)Q}*)t`KdkXWvMiNUNSx>>DC zm8&n`CY8vMFrtE%IHaT7jWt+DpVK%8ex;d(rd0)CwE%RXTh+5_^U(Bg;_NBv6 z=GFg|6Xg=pp`_wEUmYX}TmXe1UxfY^~@OpZP36H+*s^XcQ~@hzq33i*h)q2B_{fU~AKy^H@sB{{Oxe$aY59%fM#MV;yZi}s%6c3C literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAV1/VUL_TSHD.BGF b/CONTENT/BT/VIDEO/GEO/RAV1/VUL_TSHD.BGF new file mode 100644 index 0000000000000000000000000000000000000000..d6fe8fee668b5802ac36e4db5f8ea285853c74e4 GIT binary patch literal 1582 zcmbW1!D|yi6vk(hCQUUavFV|L$S5LJEJTY|DotmXCSjGOCX^his8tMwwrXvK6jZ7w zJ(!aR!K2ud3VMp9*gYyH9#c>L1r-W<7T@>GhHaXqkb%d1`}V!vnfIGF<7R%)FsDxY zMW0Xld?CN|cL%R`Nna$>(~$Lh0zoA{r`J|rWhq?Ack^TBezx!+wf!mq}dPs zK69AYlaDOZe^*&Q99yRN>Sx5SEloft9ZfO37sOC5Yvg7`zn@}!WL=1*5g^mZERkgw zG~OdFOty~<1J4n%C>h=ZB@7xl`x|pF&GE*wC5{J>hYttIy2%(G%{^p$$o7(94Z2zb zT44Pi`l}o2UB_q_f!2-6jnIwUjc_+SmyM(+9tS^SyzqZ|UT18fx8ZHrywIj!)EV3A zD~{h4Z99HWy&XmlPlqG;fg2d(9iChHAs76>2n@j!yfNGib#(>&!0y-8QNvJH$Nb{N z&;DJiaJ`0~naz3)el&5M*}tz?r{3ay0) a?r7(Lw-zYF+i9K?>;*aQ`^4Elouz+fI$%Wr literal 0 HcmV?d00001 diff --git a/CONTENT/BT/VIDEO/GEO/RAVFLOOR.BGF b/CONTENT/BT/VIDEO/GEO/RAVFLOOR.BGF new file mode 100644 index 0000000000000000000000000000000000000000..6f0ddbbbe12e9315c644c1b7465af51db6eaf320 GIT binary patch literal 807 zcmaKqu}%U(5Qb-GQ8^H`pt9P+*2Gv?(72G3gu<4>#z2CJ2^u|xf{M~u`64DhfF-fE z@_C$}yCKJBVUj;{xAX1%J9nG*`lp@V&AFu}JLal&wqXYq$IT>h#yn9gqa!NC-_KY2 zOeaLMMZStWON-|s=WpIG_`(@#`)}^LDi-hhA6Fg!$!G4^WP|DbTYTo1>-zOXkOs~YG9-J-4A>Y0PUna*%N}6F1F_9Z8E~7tP}2w* z_0oFG3k;-ZM&8s%8T5-WOFtBg2pI~#Vay8*q_b~h)F;M-vx5!Kvzop57cnM3^EI_A is2Y)6CbA+d?1*+ndm`M-L{t;iMf;+L=s-57^pvE*HKl`GxmTp3y#D*w`8Qq_F(j`XAxT0iX^xzmA{t3l7$QW* zbMiJuIe+Al>y_~uZWzzoi;1ix^V|Dq*8Z2Z?z*k@ajftD{q}F~-`@MT_uqS1fU|no z1Xp8)tx}~_ni{K&+Zj!5rc$IxK}{}!+A